简单的LinearLayout

package com.mingshan.linearlayout;

import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;

public class MyLinearLayout extends ViewGroup
{

    public static final int HORIZONTAL = 0;
    public static final int VERTICAL = 1;
    private int mOrientation = VERTICAL;
    private int mWidth;
    private int mHeight;

    private int mGravity;
    private int mTotalLength;

    public MyLinearLayout(Context context, AttributeSet attrs)
    {
        super(context, attrs);
        init(context, attrs);
    }

    private void init(Context context,AttributeSet attrs)
    {

    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
    {
        if(mOrientation==VERTICAL){
            measureVertical(widthMeasureSpec,heightMeasureSpec);
        }else {
            measureHorizontal(widthMeasureSpec,heightMeasureSpec);
        }
    }

    private void measureHorizontal(int widthMeasureSpec, int heightMeasureSpec)
    {

    }
    //https://blog.csdn.net/xmxkf/article/details/51490283
    private void measureVertical(int widthMeasureSpec, int heightMeasureSpec)
    {
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
        Log.i("measureVertical", "widthMode:"+widthMode);
        Log.i("measureVertical", "widthSize:"+widthSize);
        Log.i("measureVertical", "heightMode:"+heightMode);
        Log.i("measureVertical", "heightSize:"+heightSize);

        int maxWidth=0;
        int totalHeight=getPaddingTop();
        int childCount = getChildCount();
        mTotalLength = 0;
        for (int i=0;i<childCount;i++){
            View child = getChildAt(i);
            if(child.getVisibility()==View.GONE){
                continue;
            }
            final LayoutParams lp = (LayoutParams) child.getLayoutParams();
            //获取子控件的宽高约束规则
            final int childWidthMeasureSpec = getChildMeasureSpec(widthMeasureSpec,
                    lp.leftMargin+lp.rightMargin, lp. width);
            final int childHeightMeasureSpec = getChildMeasureSpec(heightMeasureSpec,
                    0, lp. height);

            child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
            final int measuredWidth = child.getMeasuredWidth();
            if(measuredWidth>maxWidth){
                maxWidth=measuredWidth;
            }
            final int measuredHeight = child.getMeasuredHeight();
            totalHeight+=measuredHeight;
            mTotalLength+=measuredHeight;
        }
        if (widthMode == MeasureSpec.EXACTLY)
        {
            mWidth = widthSize;
        }else {
            mWidth = maxWidth+getPaddingLeft()+getPaddingRight();
        }
        if(heightMode==MeasureSpec.EXACTLY){
            mHeight=heightSize;
        }else {
            mHeight=totalHeight+getPaddingBottom();
        }
        setMeasuredDimension(mWidth, mHeight);
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b)
    {
        if(mOrientation==VERTICAL){
            onLayoutVertical(changed, l, t, r, b);
        }else {
            onLayoutHorizontal(changed, l, t, r, b);
        }
    }

    private void onLayoutHorizontal(boolean changed, int l, int t, int r, int b)
    {

    }

    private void onLayoutVertical(boolean changed, int l, int t, int r, int b)
    {
        final int width = r-l;
        final int childCount = getChildCount();
        final int paddingLeft = getPaddingLeft();
        final int paddingRight = getPaddingRight();
        final int paddingTop = getPaddingTop();

        Log.i("onLayoutVertical", "childCount:"+childCount);
        Log.i("onLayoutVertical", "paddingLeft:"+paddingLeft);
        Log.i("onLayoutVertical", "paddingRight:"+paddingRight);
        Log.i("onLayoutVertical", "paddingTop:"+paddingTop);
        int startY = paddingTop;
        for(int i=0;i<childCount;i++){
            View child = getChildAt(i);
            if(child.getVisibility()==View.GONE){
                continue;
            }
            final int childWidth = child.getMeasuredWidth();
            final int childHeight = child.getMeasuredHeight();
            Log.i("onLayoutVertical", "childWidth:"+childWidth);
            Log.i("onLayoutVertical", "childHeight:"+childHeight);

            LayoutParams layoutParams = (LayoutParams) child.getLayoutParams();
            Log.i("onLayoutVertical", "layoutParams.gravity:"+layoutParams.gravity);
            switch (layoutParams.gravity){
                case Gravity.CENTER_HORIZONTAL:
                    child.layout((width>>1)-(childWidth>>1),startY, (width>>1)+(childWidth>>1),startY+childHeight);
                    break;
                case Gravity.RIGHT:
                    child.layout(width-childWidth,startY, paddingRight, startY+childHeight);
                    break;
                default:
                    child.layout(paddingLeft,startY, paddingLeft+childWidth, startY+childHeight);
                    break;
            }
            startY+=childHeight;
        }
    }

    @Override
    protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p)
    {
        return new LayoutParams(p);
    }

    @Override
    public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs)
    {
        return new LayoutParams(getContext(), attrs);
    }

    @Override
    protected ViewGroup.LayoutParams generateDefaultLayoutParams()
    {
        return new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
    }

    @Override
    protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
        return p instanceof MyLinearLayout.LayoutParams;
    }

    public static class LayoutParams extends ViewGroup.MarginLayoutParams {

        public float weight;

        public int gravity = -1;

        public LayoutParams(Context c, AttributeSet attrs) {
            super(c, attrs);
            Log.i("LayoutParams","Context c, AttributeSet attrs");
            TypedArray a = c.obtainStyledAttributes(attrs, R.styleable.MyLinearLayout_Layout);
//                    c.obtainStyledAttributes(attrs, com.android.internal.R.styleable.LinearLayout_Layout);
            weight = a.getFloat(R.styleable.MyLinearLayout_Layout_layout_weight, 0);
            gravity = a.getInt(R.styleable.MyLinearLayout_Layout_layout_gravity, Gravity.LEFT);
//            weight = a.getFloat(com.android.internal.R.styleable.LinearLayout_Layout_layout_weight, 0);
//            gravity = a.getInt(com.android.internal.R.styleable.LinearLayout_Layout_layout_gravity, -1);

            a.recycle();
        }

        public LayoutParams(int width, int height) {
            super(width, height);
            Log.i("LayoutParams","int width, int height");
            weight = 0;
        }

        public LayoutParams(int width, int height, float weight) {
            super(width, height);
            Log.i("LayoutParams","int width, int height, float weight");
            this.weight = weight;
        }

        public LayoutParams(ViewGroup.LayoutParams p) {
            super(p);
            Log.i("LayoutParams","ViewGroup.LayoutParams p");
        }

        public LayoutParams(ViewGroup.MarginLayoutParams source) {
            super(source);
            Log.i("LayoutParams","ViewGroup.MarginLayoutParams source");
        }

        public LayoutParams(LinearLayout.LayoutParams source) {
            super(source);
            Log.i("LayoutParams","LinearLayout.LayoutParams source");

            this.weight = source.weight;
            this.gravity = source.gravity;
        }

    }

}

<declare-styleable name="MyLinearLayout">
    <attr name="orientation" format="integer"/>
</declare-styleable>
<declare-styleable name="MyLinearLayout_Layout">
    <attr name="layout_weight" format="float"/>
    <attr name="layout_gravity" format="enum">
        <enum name="top" value="48"/>
        <enum name="bottom" value="80"/>
        <enum name="left" value="3"/>
        <enum name="right" value="5"/>
        <enum name="start" value="8388611"/>
        <enum name="end" value="8388613"/>
        <enum name="center_vertical" value="16"/>
        <enum name="center_horizontal" value="1"/>
        <enum name="center" value="17"/>
    </attr>
</declare-styleable>

猜你喜欢

转载自blog.csdn.net/weixin_42167360/article/details/80506628