Android自定义ViewGroup简单处理子View的margin

简单记录一下自定义ViewGroup中的margin问题,此demo自定义了MyViewGroup达到部分LinearLayout中的horizontal中的情况。

目前只适用于wrap_content的情况

public class MyViewGroup extends ViewGroup {
    private static final String TAG = "MyViewGroup";

    public MyViewGroup(Context context) {
        this(context, null);
    }

    public MyViewGroup(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public MyViewGroup(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

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

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

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

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int totalWidth = 0;
        int totalHeight = 0;
        int childCount = getChildCount();
        for (int i = 0; i < childCount; i++) {
            View childView = getChildAt(i);
            //测量子view尺寸
            measureChild(childView, widthMeasureSpec, heightMeasureSpec);
//            measureChildren(widthMeasureSpec, heightMeasureSpec);
            totalWidth = childView.getMeasuredWidth() + totalWidth;
            ViewGroup.MarginLayoutParams layoutParams = (MarginLayoutParams) childView.getLayoutParams();
            totalWidth = totalWidth + layoutParams.leftMargin + layoutParams.rightMargin;
            totalHeight = Math.max(childView.getMeasuredHeight(), totalHeight);
        }
        setMeasuredDimension(totalWidth, totalHeight);
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        int childCount = getChildCount();
        int left = 0;
        int top = 0;
        int right = 0;
        int bottom = 0;
        for (int i = 0; i < childCount; i++) {
            View childView = getChildAt(i);
            int measuredWidth = childView.getMeasuredWidth();
            int measuredHeight = childView.getMeasuredHeight();
            Log.d(TAG, "measuredWidth: " + measuredWidth + ",measuredHeight:" + measuredHeight);
            ViewGroup.MarginLayoutParams layoutParams = (MarginLayoutParams) childView.getLayoutParams();
            Log.d(TAG, "layoutParams.leftMargin: " + layoutParams.getMarginStart() + ",layoutParams.rightMargin:" + layoutParams.getMarginEnd());
            if (i >= 1) {
                ViewGroup.MarginLayoutParams layoutParams1 = (MarginLayoutParams) getChildAt(i - 1).getLayoutParams();
                left += getChildAt(i - 1).getMeasuredWidth() + layoutParams1.getMarginEnd() + layoutParams.getMarginStart();
            } else {
                left += layoutParams.getMarginStart();
            }

            right = left + measuredWidth;
            bottom = top + measuredHeight;
            childView.layout(left, top, right, bottom);
        }
    }

    /**
     * 为每一个子view添加MarginLayoutParams
     */
    public class MyViewGroupLayoutParams extends MarginLayoutParams {

        public MyViewGroupLayoutParams(Context c, AttributeSet attrs) {
            super(c, attrs);
        }

        public MyViewGroupLayoutParams(int width, int height) {
            super(width, height);
        }

        public MyViewGroupLayoutParams(MarginLayoutParams source) {
            super(source);
        }

        public MyViewGroupLayoutParams(LayoutParams source) {
            super(source);
        }
    }
}

布局样式,参考LinearLayoutCompat

<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.LinearLayoutCompat xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <com.example.demotest.MyViewGroup
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">
        <ImageView
            android:layout_marginStart="10dp"
            android:layout_marginEnd="20dp"
            android:background="@color/teal_700"
            android:layout_width="100dp"
            android:layout_height="100dp"/>
        <ImageView
            android:background="@color/purple_200"
            android:layout_width="50dp"
            android:layout_marginEnd="20dp"
            android:layout_height="50dp"/>
        <ImageView
            android:background="@color/black"
            android:layout_width="150dp"
            android:layout_marginStart="10dp"
            android:layout_marginEnd="10dp"
            android:layout_height="150dp"/>
        
    </com.example.demotest.MyViewGroup>
    <androidx.appcompat.widget.LinearLayoutCompat
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">
        <ImageView
            android:layout_marginStart="10dp"
            android:layout_marginEnd="20dp"
            android:background="@color/teal_700"
            android:layout_width="100dp"
            android:layout_height="100dp"/>
        <ImageView
            android:background="@color/purple_200"
            android:layout_width="50dp"
            android:layout_marginEnd="20dp"
            android:layout_height="50dp"/>
        <ImageView
            android:layout_marginStart="10dp"
            android:layout_marginEnd="10dp"
            android:background="@color/black"
            android:layout_width="150dp"
            android:layout_height="150dp"/>
    </androidx.appcompat.widget.LinearLayoutCompat>
</androidx.appcompat.widget.LinearLayoutCompat>

参考下面的截图,基本上达到了LinearLayout的效果 

 后续要添加match_parent,padding,vertial的等效果...

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值