Android Advanced Custom ViewGroup custom layout

Foreword

In our practical applications, often you need to use custom controls, such as custom round head, custom pedometer and so on. But sometimes we need not only custom control, for example, FloatingActionButton we are very common, so we very often have a need, click on a pop-up FloatingActionButton more FloatingActionButton, the general idea of ​​this requirement is to write the n button and then one by one to animate. But this is too much trouble, so there is a FloatingActionButtonMenu online open source library, which is to use a custom layout "ViewGroup" Let me introduce to his family, how to customize the layout "layout."


difficulty

Compared to Custom View, ViewGroup difficulty is customize, and determining the layout size determination sub-control position. Unlike the single sub-View To better pollen mode, to get a good measurement of the width, length and width of the ViewGroup varies with the number of sub-View and a single change in size. This is the largest Hom, so how to determine the size of ViewGroup it?


step

Here I designed a similar ViewGroup LinearLayout linear layout as an example for everyone.

First of all, if it is a LinearLayout then when setting wrap_content, he would have to subspace that is the widest of its width. Meanwhile in height will be the sum of all the child controls height. So we wrote two methods were used to measure the width and height of ViewGroup.


    private int getMaxWidth(){
        int count = getChildCount();
        int maxWidth = 0;
        for (int i = 0 ; i < count ; i ++){
            int currentWidth = getChildAt(i).getMeasuredWidth();
            if (maxWidth < currentWidth){
                maxWidth = currentWidth;
            }
        }
        return maxWidth;
    }
 
    private int getTotalHeight(){
        int count = getChildCount();
        int totalHeight = 0;
        for (int i = 0 ; i < count ; i++){
            totalHeight += getChildAt(i).getMeasuredHeight();
        }
        return totalHeight;
    }
    

For the purposes of ViewGroup we can roughly be divided into two modes: fixed length and width mode (match_parent), adaptive mode (wrap_content), according to these two models, it can be divided to draw the ViewGroup. Here on measureChildren this method, he is used to measure all of the sub-View, which triggers onMeasure function for each sub-View, but we have to be careful to distinguish between the measureChild, measureChild is measured on a single view

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
 
        measureChildren(widthMeasureSpec, heightMeasureSpec);
 
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int width     = MeasureSpec.getSize(widthMeasureSpec);
        int heightMode= MeasureSpec.getMode(heightMeasureSpec);
        int height    = MeasureSpec.getSize(heightMeasureSpec);
 
        if (widthMode == MeasureSpec.AT_MOST && heightMode == MeasureSpec.AT_MOST){
            int groupWidth = getMaxWidth();
            int groupHeight= getTotalHeight();
 
            setMeasuredDimension(groupWidth, groupHeight);
        }else if (widthMode == MeasureSpec.AT_MOST){
            setMeasuredDimension(getMaxWidth(), height);
        }else if (heightMode == MeasureSpec.AT_MOST){
            setMeasuredDimension(width, getTotalHeight());
        }
    }

Rewrite onLayout

Integrity above these things, our layout size seventy-nine has come out, and then we add it in the layout file activity inside and add a few sub-View and then run it, take a look at the effect of:

    <com.entry.android_view_user_defined_first.views.MyLinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@color/colorAccent">
 
        <Button
            android:layout_width="100dp"
            android:layout_height="50dp"
            android:text="qwe"/>
 
        <Button
            android:layout_width="250dp"
            android:layout_height="150dp"
            android:text="qwe"/>
 
        <Button
            android:layout_width="200dp"
            android:layout_height="75dp"
            android:text="qwe"/>
 
    </com.entry.android_view_user_defined_first.views.MyLinearLayout>

Operating results are as follows:

We came out to see the layout, also like the size of the lacks the problem, but the child View it? ? ! So I did not see the child View to see before the code, and then we rewrite the system of onLayout () or empty it! ! In other words, the size and location of the sub-View simply has not been set! Let's re-write the onLayout () method.

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        int count = getChildCount();
        int currentHeight = 0;
        for (int i = 0 ; i < count ; i++){
            View view = getChildAt(i);
            int height = view.getMeasuredHeight();
            int width  = view.getMeasuredWidth();
            view.layout(l, currentHeight, l + width, currentHeight + height);
            currentHeight += height;
        }
    }

Run it and see:

Successful wood there!

Since this article is a summary of their own learning process, if there is an error in the text, I hope you can point out in the comments area

Finally, I wish you all a happy programming!

Guess you like

Origin www.cnblogs.com/yuanhao-1999/p/11068467.html