覆写onLayout进行layout,含自定义ViewGroup例子

来源:互联网 发布:大型网络动作游戏 编辑:程序博客网 时间:2024/05/16 15:51


      视图的绘制仅在Framework层分为三个阶段measure,layout,draw。前一篇博文《 覆写onMeaure进行measure操作》   关于如何覆写onMeasure, 其目的是为了测量视图的大小也就是第一阶段,如果不了解或者关于onMeasure有什么疑惑可以了解下。 本篇博文是关于如何覆写onLayout,其目的是为了指定视图的显示位置,方法执行的前后顺序是在onMeasure之后,因为视图肯定是只有知道大小的情况下,才能确定怎么摆放。


一、自定义ViewGroup例子

例子代码 - 纵向显示两个TextView

(1)编写CustomViewGroup
[plain] view plaincopyprint?
  1. 1. CustomViewGroup继承自ViewGroup,ViewGroup是所有Layout的父类  
  2. public class CustomViewGroup extends ViewGroup {  
  3.   
  4. }  


2. 覆写View.onMeasure回调函数,用于计算所有child view的宽高,这里偷懒没有进行MeasureSpec模式判断
[plain] view plaincopyprint?
  1. @Override  
  2. protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {  
  3.       
  4.     int widthSize = MeasureSpec.getSize(widthMeasureSpec);  
  5.     int heightSize = MeasureSpec.getSize(heightMeasureSpec);  
  6.   
  7.     measureChildren(widthMeasureSpec, heightMeasureSpec);     
  8.       
  9.     setMeasuredDimension(widthSize, heightSize);  
  10. }  



3. 覆写ViewGroup.onLayout回调函数,用于指定所有child View的位置
[plain] view plaincopyprint?
  1. @Override  
  2. protected void onLayout(boolean changed, int left, int top, int right, int bottom) {  
  3.   
  4.     int mTotalHeight = 0;  
  5.       
  6.        // 遍历所有子视图     
  7.     int childCount = getChildCount();  
  8.     for (int i = 0; i < childCount; i++) {  
  9.         View childView = getChildAt(i);  
  10.           
  11.         // 获取在onMeasure中计算的视图尺寸  
  12.         int measureHeight = childView.getMeasuredHeight();  
  13.         int measuredWidth = childView.getMeasuredWidth();  
  14.           
  15.         childView.layout(left, mTotalHeight, measuredWidth, mTotalHeight + measureHeight);  
  16.           
  17.         mTotalHeight += measureHeight;  
  18.           
  19.         Log.e(TAG, "changed = " + changed   
  20.                 + ", left = " + left + ", top = " + top   
  21.                 + ", right = " + right + ", bottom = " + bottom   
  22.                 + ", measureWidth = " + measuredWidth + ", measureHieght = " + measureHeight);  
  23.           
  24.     }  
  25. }  



3.1 onLayout回调函数参数:
left, top, right, bottom是当前ViewGroup整个在屏幕上的位置,手机屏幕是480 * 800 ,其中高度去除状态栏和title大概724
如果页面只有此ViewGroup则个参数的值
left = 0, top = 0, right = 480, bottom = 724


在此ViewGroup的上面放置一个TextView当期回调的参数值
left = 0, top =  25, right = 480, bottom = 724


3.2 child.layout如何填写参数
View是一个矩形,right和bottom也可以通过以下计算获得,其中Width 和 Height由onMeasure最终设置和决定 
right = left + width 
bottom = top + height


(2)创建Activity
[plain] view plaincopyprint?
  1. public class CustomViewGroupActivity extends Activity {  
  2.   
  3.     @Override  
  4.     public void onCreate(Bundle savedInstanceState) {  
  5.         super.onCreate(savedInstanceState);  
  6.   
  7.           
  8.         CustomViewGroup customViewGroup = new CustomViewGroup(this);  
  9.         customViewGroup.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));  
  10.           
  11.         // 添加子视图  
  12.         TextView textViewOne = new TextView(this);  
  13.         textViewOne.setText("a child view");  
  14.         textViewOne.setBackgroundColor(Color.BLUE);  
  15.         textViewOne.setLayoutParams(new LayoutParams(130, 130));  
  16.         customViewGroup.addView(textViewOne);  
  17.           
  18.         TextView textViewTwo = new TextView(this);  
  19.         textViewTwo.setText("b child view");  
  20.         textViewTwo.setBackgroundColor(Color.RED);  
  21.         textViewTwo.setLayoutParams(new LayoutParams(80, 80));  
  22.         customViewGroup.addView(textViewTwo);  
  23.           
  24.         setContentView(customViewGroup);  
  25.     }  
  26.       
  27.       
  28.       
  29. }  




二、 疑问

代码添加view和布局中添加view的区别?
1. 代码中添加 ViewGroup
[plain] view plaincopyprint?
  1. CustomViewGroup customViewGroup = new CustomViewGroup(this);  
  2. customViewGroup.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));  
  3.   
  4. // 添加子视图  
  5. TextView textViewOne = new TextView(this);  
  6. textViewOne.setText("a child view");  
  7. textViewOne.setBackgroundColor(Color.BLUE);  
  8. textViewOne.setLayoutParams(new LayoutParams(130, 130));  
  9. customViewGroup.addView(textViewOne);  
  10.   
  11. TextView textViewTwo = new TextView(this);  
  12. textViewTwo.setText("b child view");  
  13. textViewTwo.setBackgroundColor(Color.RED);  
  14. textViewTwo.setLayoutParams(new LayoutParams(80, 80));  
  15. customViewGroup.addView(textViewTwo);  
  16.   
  17. setContentView(customViewGroup);  



onLayout输出信息:
[plain] view plaincopyprint?
  1. changed = true, left = 0, top = 0, right = 480, bottom = 724, measureWidth = 130, measureHieght = 130  
  2. changed = true, left = 0, top = 0, right = 480, bottom = 724, measureWidth = 80, measureHieght = 80  
  3. changed = false, left = 0, top = 0, right = 480, bottom = 724, measureWidth = 130, measureHieght = 130  
  4. changed = false, left = 0, top = 0, right = 480, bottom = 724, measureWidth = 80, measureHieght = 80  



2. xml中配置添加ViewGroup
[plain] view plaincopyprint?
  1. <? xml version = "1.0" encoding = "utf-8" ?>  
  2. < com.androiddemo.CustomViewGroup xmlns:android =  
  3. "http://schemas.android.com/apk/res/android"  
  4.     android:id = "@+id/custom_viewgroup"  
  5.     android:layout_width = "fill_parent"  
  6.     android:layout_height = "wrap_content" >  
  7.   
  8.     < TextView  
  9.         android:layout_width = "130dip"  
  10.         android:layout_height = "130dip"  
  11.         android:background = "@color/blue"  
  12.         android:text = "@string/first_childview_name" />  
  13.   
  14.     < TextView  
  15.         android:layout_width = "80dip"  
  16.         android:layout_height = "80dip"  
  17.         android:background = "@color/red"  
  18.         android:text = "@string/second_childview_name" />  
  19.   
  20. </ com.androiddemo.CustomViewGroup >  



onLayout输出信息:? Width和 Height并不是TextView中设置的固定值
[plain] view plaincopyprint?
  1. changed = true, left = 0, top = 0, right = 480, bottom = 724, measureWidth = 195, measureHieght = 195  
  2. changed = true, left = 0, top = 0, right = 480, bottom = 724, measureWidth = 120, measureHieght = 120  
  3. changed = false, left = 0, top = 0, right = 480, bottom = 724, measureWidth = 195, measureHieght = 195  
  4. changed = false, left = 0, top = 0, right = 480, bottom = 724, measureWidth = 120, measureHieght = 120  




三 、扩展
× 三个方法的区别?后这个方法最终还是调用第一个方法
[plain] view plaincopyprint?
  1. childView.measure(widthMeasureSpec, heightMeasureSpec);  
  2. measureChild(childView, widthMeasureSpec, heightMeasureSpec);  
  3. measureChildren(widthMeasureSpec, heightMeasureSpec);     


× 哪些视图属性影响 measure?      padding、margin
× 哪些视图属性 影响 layout?        gravity
× view的上下左右和measurespec width和height的关系 ?


四、资料
Android官方文档: 
Layouts
http://developer.android.com/guide/topics/ui/declaring-layout.html

细说view流程上
http://blog.csdn.net/aaa2832/article/details/7844904
细说view流程下
http://blog.csdn.net/aaa2832/article/details/7849400



2013-03-31   更新与onMeasure关联博文



原文地址:http://blog.csdn.net/love_world_/article/details/8108970

      视图的绘制仅在Framework层分为三个阶段measure,layout,draw。前一篇博文《 覆写onMeaure进行measure操作》   关于如何覆写onMeasure, 其目的是为了测量视图的大小也就是第一阶段,如果不了解或者关于onMeasure有什么疑惑可以了解下。 本篇博文是关于如何覆写onLayout,其目的是为了指定视图的显示位置,方法执行的前后顺序是在onMeasure之后,因为视图肯定是只有知道大小的情况下,才能确定怎么摆放。


一、自定义ViewGroup例子

例子代码 - 纵向显示两个TextView

(1)编写CustomViewGroup
[plain] view plaincopyprint?
  1. 1. CustomViewGroup继承自ViewGroup,ViewGroup是所有Layout的父类  
  2. public class CustomViewGroup extends ViewGroup {  
  3.   
  4. }  


2. 覆写View.onMeasure回调函数,用于计算所有child view的宽高,这里偷懒没有进行MeasureSpec模式判断
[plain] view plaincopyprint?
  1. @Override  
  2. protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {  
  3.       
  4.     int widthSize = MeasureSpec.getSize(widthMeasureSpec);  
  5.     int heightSize = MeasureSpec.getSize(heightMeasureSpec);  
  6.   
  7.     measureChildren(widthMeasureSpec, heightMeasureSpec);     
  8.       
  9.     setMeasuredDimension(widthSize, heightSize);  
  10. }  



3. 覆写ViewGroup.onLayout回调函数,用于指定所有child View的位置
[plain] view plaincopyprint?
  1. @Override  
  2. protected void onLayout(boolean changed, int left, int top, int right, int bottom) {  
  3.   
  4.     int mTotalHeight = 0;  
  5.       
  6.        // 遍历所有子视图     
  7.     int childCount = getChildCount();  
  8.     for (int i = 0; i < childCount; i++) {  
  9.         View childView = getChildAt(i);  
  10.           
  11.         // 获取在onMeasure中计算的视图尺寸  
  12.         int measureHeight = childView.getMeasuredHeight();  
  13.         int measuredWidth = childView.getMeasuredWidth();  
  14.           
  15.         childView.layout(left, mTotalHeight, measuredWidth, mTotalHeight + measureHeight);  
  16.           
  17.         mTotalHeight += measureHeight;  
  18.           
  19.         Log.e(TAG, "changed = " + changed   
  20.                 + ", left = " + left + ", top = " + top   
  21.                 + ", right = " + right + ", bottom = " + bottom   
  22.                 + ", measureWidth = " + measuredWidth + ", measureHieght = " + measureHeight);  
  23.           
  24.     }  
  25. }  



3.1 onLayout回调函数参数:
left, top, right, bottom是当前ViewGroup整个在屏幕上的位置,手机屏幕是480 * 800 ,其中高度去除状态栏和title大概724
如果页面只有此ViewGroup则个参数的值
left = 0, top = 0, right = 480, bottom = 724


在此ViewGroup的上面放置一个TextView当期回调的参数值
left = 0, top =  25, right = 480, bottom = 724


3.2 child.layout如何填写参数
View是一个矩形,right和bottom也可以通过以下计算获得,其中Width 和 Height由onMeasure最终设置和决定 
right = left + width 
bottom = top + height


(2)创建Activity
[plain] view plaincopyprint?
  1. public class CustomViewGroupActivity extends Activity {  
  2.   
  3.     @Override  
  4.     public void onCreate(Bundle savedInstanceState) {  
  5.         super.onCreate(savedInstanceState);  
  6.   
  7.           
  8.         CustomViewGroup customViewGroup = new CustomViewGroup(this);  
  9.         customViewGroup.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));  
  10.           
  11.         // 添加子视图  
  12.         TextView textViewOne = new TextView(this);  
  13.         textViewOne.setText("a child view");  
  14.         textViewOne.setBackgroundColor(Color.BLUE);  
  15.         textViewOne.setLayoutParams(new LayoutParams(130, 130));  
  16.         customViewGroup.addView(textViewOne);  
  17.           
  18.         TextView textViewTwo = new TextView(this);  
  19.         textViewTwo.setText("b child view");  
  20.         textViewTwo.setBackgroundColor(Color.RED);  
  21.         textViewTwo.setLayoutParams(new LayoutParams(80, 80));  
  22.         customViewGroup.addView(textViewTwo);  
  23.           
  24.         setContentView(customViewGroup);  
  25.     }  
  26.       
  27.       
  28.       
  29. }  




二、 疑问

代码添加view和布局中添加view的区别?
1. 代码中添加 ViewGroup
[plain] view plaincopyprint?
  1. CustomViewGroup customViewGroup = new CustomViewGroup(this);  
  2. customViewGroup.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));  
  3.   
  4. // 添加子视图  
  5. TextView textViewOne = new TextView(this);  
  6. textViewOne.setText("a child view");  
  7. textViewOne.setBackgroundColor(Color.BLUE);  
  8. textViewOne.setLayoutParams(new LayoutParams(130, 130));  
  9. customViewGroup.addView(textViewOne);  
  10.   
  11. TextView textViewTwo = new TextView(this);  
  12. textViewTwo.setText("b child view");  
  13. textViewTwo.setBackgroundColor(Color.RED);  
  14. textViewTwo.setLayoutParams(new LayoutParams(80, 80));  
  15. customViewGroup.addView(textViewTwo);  
  16.   
  17. setContentView(customViewGroup);  



onLayout输出信息:
[plain] view plaincopyprint?
  1. changed = true, left = 0, top = 0, right = 480, bottom = 724, measureWidth = 130, measureHieght = 130  
  2. changed = true, left = 0, top = 0, right = 480, bottom = 724, measureWidth = 80, measureHieght = 80  
  3. changed = false, left = 0, top = 0, right = 480, bottom = 724, measureWidth = 130, measureHieght = 130  
  4. changed = false, left = 0, top = 0, right = 480, bottom = 724, measureWidth = 80, measureHieght = 80  



2. xml中配置添加ViewGroup
[plain] view plaincopyprint?
  1. <? xml version = "1.0" encoding = "utf-8" ?>  
  2. < com.androiddemo.CustomViewGroup xmlns:android =  
  3. "http://schemas.android.com/apk/res/android"  
  4.     android:id = "@+id/custom_viewgroup"  
  5.     android:layout_width = "fill_parent"  
  6.     android:layout_height = "wrap_content" >  
  7.   
  8.     < TextView  
  9.         android:layout_width = "130dip"  
  10.         android:layout_height = "130dip"  
  11.         android:background = "@color/blue"  
  12.         android:text = "@string/first_childview_name" />  
  13.   
  14.     < TextView  
  15.         android:layout_width = "80dip"  
  16.         android:layout_height = "80dip"  
  17.         android:background = "@color/red"  
  18.         android:text = "@string/second_childview_name" />  
  19.   
  20. </ com.androiddemo.CustomViewGroup >  



onLayout输出信息:? Width和 Height并不是TextView中设置的固定值
[plain] view plaincopyprint?
  1. changed = true, left = 0, top = 0, right = 480, bottom = 724, measureWidth = 195, measureHieght = 195  
  2. changed = true, left = 0, top = 0, right = 480, bottom = 724, measureWidth = 120, measureHieght = 120  
  3. changed = false, left = 0, top = 0, right = 480, bottom = 724, measureWidth = 195, measureHieght = 195  
  4. changed = false, left = 0, top = 0, right = 480, bottom = 724, measureWidth = 120, measureHieght = 120  




三 、扩展
× 三个方法的区别?后这个方法最终还是调用第一个方法
[plain] view plaincopyprint?
  1. childView.measure(widthMeasureSpec, heightMeasureSpec);  
  2. measureChild(childView, widthMeasureSpec, heightMeasureSpec);  
  3. measureChildren(widthMeasureSpec, heightMeasureSpec);     


× 哪些视图属性影响 measure?      padding、margin
× 哪些视图属性 影响 layout?        gravity
× view的上下左右和measurespec width和height的关系 ?


四、资料
Android官方文档: 
Layouts
http://developer.android.com/guide/topics/ui/declaring-layout.html

细说view流程上
http://blog.csdn.net/aaa2832/article/details/7844904
细说view流程下
http://blog.csdn.net/aaa2832/article/details/7849400



2013-03-31   更新与onMeasure关联博文



原文地址:http://blog.csdn.net/love_world_/article/details/8108970