Android自定义View的基础知识(七)——onLayout方法作用

在编写自定义view过程当中,可能涉及到自定义容器类控件,因为存在容器类控件,并不能满足要求,那么我们需要通过继承ViewGroup类来定义容器类控件。本篇博客,会通过简单的实例给大家介绍继承ViewGroup之后,我们需要做那些必要的操作。

比如实现流式布局,何为流式布局,其实就是将容器当中所排布的控件,从左到右进行排布,然后这一行的高度以这行当中最高的控件为基准,如果排布过程当中,剩余的宽度小于要排布进去的控件的宽度,那么就自动换行,将要排布进去的控件存放到下一行当中,然后下一行的底部高度,是上一行最高的控件底部的高度。如下图所示:


如何实现这个功能呢,详细代码如下:

public class FlowLayout extends ViewGroup{
    public FlowLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
//     onLayout :计算容器内部每个控件应该放置的位置。
    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
//        获取当前容器的宽度
        int selfWidth = r-l;
//      获取当前容器当中存放了多少个子控件
        int childCount = getChildCount();
        int cl = 10;   //设定每个控件距离左边的边距
        int ct = 10;   //设定每个控件距离上边的边距
//        定义一个值,表示这一行当中最高的控件的高度
        int lineMaxHeight = 0;
        for (int i = 0; i < childCount; i++) {
            View childView = getChildAt(i);

            int childHeight = childView.getMeasuredHeight();  //测量出来的子控件的高度
            int childWidth = childView.getMeasuredWidth();      //测量出来的子控件的宽度

            int cr = cl+childWidth;
            int cb = ct+childHeight;
//            判断当前控件的右边的角标是否超过了容器的宽度,如果超过了容器的宽度,就需要换行,
//            如果没有超过容器的宽度,就不需要换行
            if (cr>selfWidth) {  //应该换行
                cl = 10;
                ct = ct+lineMaxHeight;
//                换行之后要把当前控件的高度先作为最高的高度,是比较的标准
                lineMaxHeight = childHeight;
//                换行之后,右边和下边的角标
                cr = cl+childWidth;
                cb = ct+childHeight;
            }else{
//           如果不换行,就会直接放置控件,那么就要判断,当前要放进去的是不是这一行当中最高的控件。
                 lineMaxHeight = Math.max(lineMaxHeight, childHeight);
            }
            childView.layout(cl,ct,cr,cb);
            cl = cr;
        }
    }
/**
 * onMeasure作用:
 * 1.测量当前view的宽高
 * 2.如果在容器类布局当中重新了这个方法,还可以测量容器类当中所有的子控件
 * */
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//        对于容器当中的子控件进行设置
        measureChildren(widthMeasureSpec,heightMeasureSpec);
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }
}


如代码所示,在onLayout的方法当中,我们需要对于计算每一个控件排布时,距离左,上,右,下四个角度的坐标,然后就能够确定出控件放置的位置。然后调用这个子控件layout的方法,将其进行排布。这就是onLayout方法的作用。同样为了能够去准确的获得子控件的宽度和高度,我们需要重写onMeasure方法,并且在onMeasure方法当中,调用计算子控件宽高的方法:

measureChildren(widthMeasureSpec,heightMeasureSpec);
然后就完成了简单的流式的操作,在布局当中将我们自定义的容器类控件,作为布局,然后在内部排列子控件,我们就能够看到想要的效果了!!大家可以试一试:

<?xml version="1.0" encoding="utf-8"?>
<com.animee.day406.demo03.FlowLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <Button
        android:layout_width="100dp"
        android:layout_height="30dp"
        android:text="Button1"/>
    <Button
        android:layout_width="80dp"
        android:layout_height="40dp"
        android:text="BB"/>
    <Button
        android:layout_width="150dp"
        android:layout_height="80dp"
        android:text="AA"/>
    <Button
        android:layout_width="200dp"
        android:layout_height="50dp"
        android:text="CC"/>
    <Button
        android:layout_width="40dp"
        android:layout_height="60dp" />
    <Button
        android:layout_width="300dp"
        android:layout_height="100dp" />
</com.animee.day406.demo03.FlowLayout>

关于简单流式布局的操作就结束了,你学会了~~


猜你喜欢

转载自blog.csdn.net/u012156341/article/details/79541014
今日推荐