自定义viewgroup实践之仿写LinearLayout
来源:互联网 发布:泽野弘之 知乎 编辑:程序博客网 时间:2024/05/15 05:38
一般来说,自定义一个viewgroup至少需重写onmeasure()、onLayout()方法,如果对于布局有特定的需要,还需重写LayoutParam。
好了,现在来说具体的步骤:
一般而言有自定义属性,所以需得写构造方法。不是本文的重点,略过。
下面将一次详细的说明onMeasure()、onLayout()的实现。
onMeasure()具体实现
横向依次排列,首先定义一个宽度,初始值为0,每排一个view,就加入view的宽度和view的左右margin值,最后加上自身的左右padding值,就是viewgroup的宽度。
对于高度而言,子view中height加上其上下margin最大值就是其高度。然后再调用setMeasuredDimension();
在onMeasure()中最重要的是 要measure每个子view。
下面看具体代码:
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { //第一步--获取宽高模型 int widthMode = MeasureSpec.getMode(widthMeasureSpec); int heightMode = MeasureSpec.getMode(heightMeasureSpec); int usedWidth = 0; int usedHeight = 0; int usedMaxHeight = 0; Log.i("tag","kuan"+MeasureSpec.getSize(widthMeasureSpec)+" gao"+ MeasureSpec.getSize(heightMeasureSpec)); //第二步--测量每个子view,并计算出所有子view的总长 for(int i = 0; i < getChildCount(); i++){ View child = getChildAt(i); if(child == null) continue; LayoutParams lp = (LayoutParams) child.getLayoutParams(); measureChildWithMargins(child,widthMeasureSpec,usedWidth,heightMeasureSpec,usedHeight);// if(widthMode == MeasureSpec.EXACTLY){// usedWidth += lp.width + lp.layout_left_space + lp.leftMargin + lp.rightMargin;// }else{ usedWidth += child.getMeasuredWidth() + lp.layout_left_space + lp.leftMargin + lp.rightMargin;// } if(heightMode == MeasureSpec.EXACTLY){ usedMaxHeight = Math.max(usedMaxHeight,lp.height + lp.topMargin + lp.bottomMargin); }else{ usedMaxHeight = Math.max(usedMaxHeight,child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin); } } //第三步--计算出已知所用的长度,然后生成相关的宽高值 int widthSize = usedWidth + getPaddingLeft() + getPaddingRight(); int heightSize = usedMaxHeight + getPaddingTop() + getPaddingBottom(); int widthSpec = 0; int heightSpec = 0; // Check against our minimum width widthSize = Math.max(widthSize, getSuggestedMinimumWidth()); // Reconcile our calculated size with the widthMeasureSpec if(Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB){ widthSpec = resolveSize(widthSize,widthMeasureSpec); heightSpec = resolveSize(heightSize,heightMeasureSpec); }else{ widthSpec = resolveSizeAndState(widthSize, widthMeasureSpec, 0); heightSpec = resolveSizeAndState(heightSize,heightMeasureSpec,0); } widthSize = widthSpec & MEASURED_SIZE_MASK; heightSize = heightSpec & MEASURED_SIZE_MASK; //第四步--设置测量值 setMeasuredDimension(widthSize,heightSize); }
onLayout()具体实现
在这里面也要layout每个子view。在这里就可以用view的get宽高方法了,看代码:
@Override protected void onLayout(boolean changed, int l, int t, int r, int b) { Log.i("tag_layout","left" + l); int startLeft = getPaddingLeft(); final int startTop = getPaddingTop(); for(int i = 0; i < getChildCount(); i++){ View child = getChildAt(i); LayoutParams lp = (LayoutParams) child.getLayoutParams(); startLeft += lp.leftMargin + lp.layout_left_space; int viewRight = startLeft + child.getMeasuredWidth(); int viewBottom = startTop + child.getMeasuredHeight() + lp.topMargin; child.layout(startLeft,startTop + lp.topMargin,viewRight,viewBottom); startLeft = viewRight + lp.rightMargin; } }
对于LayoutParam有特殊需求的,重写LayoutParam
我这里定义了每个子view的横向间隔,看代码:
public LayoutParams(Context c, AttributeSet attrs) { super(c, attrs); TypedArray a = c.obtainStyledAttributes(attrs,R.styleable.Custom_Layout); layout_left_space = a.getDimensionPixelSize(R.styleable.Custom_Layout_layout_left_space,0); a.recycle(); }
另外,对于自定义ViewGroup,还需重写以下三个方法:
@Override public LayoutParams generateLayoutParams(AttributeSet attrs) { return new LayoutParams(getContext(),attrs); } @Override protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) { return new LayoutParams(p); } @Override protected LayoutParams generateDefaultLayoutParams() { return new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); }
如果要做ondraw(),有两种方法:
第一种 在构造方法中setWillNotDraw(false);
第二种 在构造方法中 setBackgroundResource(R.drawable.ic_launcher);
第二种 在构造方法中 setBackgroundResource(R.drawable.ic_launcher);
具体请参考ViewGroup为什么不会调用onDraw
ok,本文完毕,觉得还可以的哥们顶下。
项目源码
1 0
- 自定义viewgroup实践之仿写LinearLayout
- ViewGroup初探,自定义LinearLayout
- android之自定义viewGroup仿scrollView详解
- 自定义ViewGroup之仿网易新闻栏目管理
- 自定义ViewGroup——圆形排列LinearLayout
- 实践自定义UI-ViewGroup
- 实践自定义UI-ViewGroup
- 仿ViewPager之ViewGroup一
- android之自定义ViewGroup
- Android之自定义ViewGroup
- Android之自定义ViewGroup
- Android之自定义ViewGroup
- 自定义ViewGroup之TagLayout
- 自定义ViewGroup之别踩白块
- Android UI设计之<十四>自定义ViewGroup,实现绚丽的仿支付宝咻一咻雷达脉冲效果
- Android UI设计之<十四>自定义ViewGroup,实现绚丽的仿支付宝咻一咻雷达脉冲效果
- android之自定义viewGroup仿scrollView的两种实现(滚动跟粘性)
- Android 自定义Viewgroup之仿360手机助手详情页图片滑动
- Sicily 2014. Dairy Queen
- java反射 静态类
- PCL 1.8.0 VS2010 x64源码编译
- weblogic的Serverlog内容自定义
- BitMap同时绘制Matrix和ColorMatrix
- 自定义viewgroup实践之仿写LinearLayout
- 关于使用CXF的wsdl2java.bat出现环境变量的问题....
- 性能测试检查项
- android 如何进行 代码混淆
- 推荐算法注意事项总结
- HTTP协议—缓存
- java调用webservice接口完整源码
- C++中delete和delete[]的区别
- 东皇电动车气骗子