自定义ViewGroup

来源:互联网 发布:java完全自学手册 pdf 编辑:程序博客网 时间:2024/06/05 01:23


一.什么是ViewGroup

ViewGroup继承自View,他可以包含很多继承自View的类,并且合理的安排他的位置。

接下来是一段引用自谷歌官方对ViewGroup介绍

A ViewGroup is a special view that can contain other views (called children.) The view group is the base class for layouts and views containers.

This class also defines theViewGroup.LayoutParams class which serves as the base class for layouts parameters.

二.自定义ViewGroup需要做什么

1.如果我们要自定义一个ViewGroup要做什么

  • 写构造函数
  • 重写onMeasure,
  • 重写onLayout方法

如果我们想一个做一个最简单的ViewGroup,我们只需要做上面3步。这个ViewGroup就可以根据我们的重写的方法来测量大小和摆放子控件的位置

如下

public class CustomViewGroup2 extends ViewGroup {    public CustomViewGroup2(Context context) {        super(context);    }    public CustomViewGroup2(Context context, AttributeSet attrs) {        super(context, attrs);    }    public CustomViewGroup2(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);    }    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        super.onMeasure(widthMeasureSpec, heightMeasureSpec);        int childCount = getChildCount();        for(int i = 0; i < childCount; i++){            View child = getChildAt(i);            measureChild(child, widthMeasureSpec, heightMeasureSpec);        }    }    @Override    protected void onLayout(boolean changed, int l, int t, int r, int b) {        int childCount = getChildCount();        int left = getPaddingLeft();        int top = getPaddingTop();        for(int i = 0; i < childCount; i++){            View child = getChildAt(i);            //设置每个控件的位置            child.layout(left, top, child.getMeasuredWidth(), child.getMeasuredHeight() + top);            top += child.getMeasuredHeight();        }    }}


2.onMeasure中做什么?

在OnMeasure中我们需要做的有两点

  • 测量ViewGroup的大小并通过setMeasureDimension传入具体值
  • 调用子控件测量大小方法measureChild
setMeasureDimension这个传入具体的控件高度,我在我们代码中没有调用这个函数,取而代之用的是super.onMeasure,在View中的OnMeasure有套很简单的测量控件大小的策略,但是不建议大家用,因为这套策略不会去计算子控件的大小。

我们可以这样去写个测量子控件并且简略的onMeasure

    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        //MeasureSpec中的宽度值        int width = MeasureSpec.getSize(widthMeasureSpec);        //子视图的个数        int childCount = getChildCount();        //最终的高度        int finalHeight = 0;        for(int i = 0; i < childCount; i++){            View child = getChildAt(i);            measureChild(child, widthMeasureSpec, heightMeasureSpec);            finalHeight += child.getMeasuredHeight();        }        setMeasuredDimension(width, finalHeight);    }
这个方法就会去计算每一个子view的高度,并把他们相加然后传入setMesureDimension。

其实学过自定义View的都知道我们可以利用传入的widthMeasureSpec、heightMeasureSpec这两个参数配合MeasureSpec实现跟多的情况,ViewGroup中当然也可以用这些。如果不清楚的可以去看自定义View。

measureChild方法可以测量出每个传入View的大小。如果没有调用这个的话那么控件的宽和高都是0。这个方法在最后回去调用onMeasure方法测量自身大小。

总结来说在onMeasure中根据自己的需求去计算我们ViewGroup的大小。调用measureChild测量子View的大小,最后通过我们计算出的大小来传入setMeasureDimension。

3.onLayout中做什么?

onLayout中我们需要做的是为每一个子View布置他的位置。也就是给每个子View随意的设计上下左右的边界。

  • 在layout中 调用view.layou方法设置这个View的
这个值得我们注意一点的就是onLayout和layou方法中上下左右四个参数都是相对于父控件来说的,而不是相对于手机的坐标原点的。


三.如果我的ViewGroup需要响应特殊事件 

这边内容涉及到事件传递,下一次再独立总结一篇


顺便记下我在写ViewGroup的时候记下的知识点



getHeight() 和 getMeasuredHeight()
getMeasuredHeight()返回的是原始测量高度,与屏幕无关,getHeight()返回的是在屏幕上显示的高度。实际上在当屏幕可以包裹内容的时候,他们的值是相等的,只有当view超出屏幕后,才能看出他们的区别。当超出屏幕后,getMeasuredHeight()等于getHeight()加上屏幕之外没有显示的高度。


getX()和getRowY(),getScrollY()
getX()相对于View的左上角的坐标,getRowY()相对于屏幕左上角未加工的坐标,getScroll()获取偏移量

scrollTo(x,y)和scrollBy(x,y)
scrollTo显示区域移动到x,y位置
scrollBy显示区域移动x,y个距离


0 0
原创粉丝点击