首页 > 解决方案 > 自定义 ViewGroup LayoutParams 在android中不起作用

问题描述

出色地

我只是在 android 中学习自定义视图组,所以我制作了一个简单的视图组。我命名它LearnLayout 我有自定义布局参数,称为LearnLayoutParams

问题

当我对孩子使用自定义属性时。这些属性没有被解析,LearnLayoutParams我得到默认值

代码

这是我的代码文件

学习布局.java

这是自定义视图组类文件

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.os.Build;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;

import androidx.annotation.RequiresApi;

import com.test.learnviewpagertransformations.MainActivity;
import com.test.learnviewpagertransformations.R;

public class LearnLayout extends ViewGroup {

    private static final String TAG = MainActivity.TAG;

    public LearnLayout(Context context) {
        super(context);
    }

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

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

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

        int maxWidth = 0;
        int maxHeight = 0;

        for(int i=0; i<getChildCount(); i++){
            View childView = getChildAt(i);
            if(childView.getVisibility() != GONE){
                measureChildWithMargins(childView, widthMeasureSpec, 0, heightMeasureSpec, 0);

                final LearnLayoutParams lp = (LearnLayoutParams) childView.getLayoutParams();

                int childWidth = lp.leftMargin + childView.getMeasuredWidth() + lp.rightMargin;
                int childHeight = lp.topMargin + childView.getMeasuredHeight() + lp.bottomMargin;
                maxWidth = Math.max(childWidth, maxWidth);
                maxHeight = maxHeight + childHeight;
            }
        }

        setMeasuredDimension(maxWidth, maxHeight);
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {

        int fromLeft = getPaddingLeft();
        int fromTop = getPaddingTop();
        int fromRight = right - left - getPaddingRight();
        int fromBottom = bottom - top - getPaddingBottom();

        for(int i=0; i<getChildCount(); i++){
            View childView = getChildAt(i);
            if (childView.getVisibility() != GONE) {
                final LearnLayoutParams lp = (LearnLayoutParams) childView.getLayoutParams();
                childView.layout(
                        fromLeft + lp.leftMargin,
                        fromTop + lp.topMargin,
                        fromRight - lp.rightMargin,
                        fromTop + lp.topMargin + lp.height
                );
                childView.setOnClickListener(new OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        Log.i(TAG, "onLayout: " + lp.backgroundColor);
                    }
                });
                childView.setBackgroundColor(getColor(lp.backgroundColor));
                fromTop = fromTop + childView.getMeasuredHeight() + lp.topMargin + lp.bottomMargin;
            }
        }

    }

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

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

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

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

    public static class LearnLayoutParams extends MarginLayoutParams {

        public int backgroundColor = 0;

        public LearnLayoutParams(Context c, AttributeSet attrs) {
            super(c, attrs);

            TypedArray a = c.obtainStyledAttributes(R.styleable.LearnLayoutLP);
            backgroundColor = a.getInt(R.styleable.LearnLayoutLP_layout_background_color, backgroundColor);
            Log.i(TAG, "LayoutParams: " + backgroundColor);
            a.recycle();

        }

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

        public LearnLayoutParams(ViewGroup.LayoutParams source) {
            super(source);
        }

    }

    private int getColor(int backgroundColor){
        switch (backgroundColor){
            case 0:
                return Color.RED;
            case 1:
                return Color.BLUE;
            case 2:
                return Color.GREEN;
            default:
                return Color.BLACK;
        }
    }

}

activity_learn_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    android:gravity="center"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.test.learnviewpagertransformations.views.LearnLayout
        android:background="#99ff99"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" >

        <View
            app:layout_background_color="red"
            android:layout_margin="50dp"
            android:layout_width="100dp"
            android:layout_height="100dp" />

        <LinearLayout
            android:id="@+id/testView"
            android:gravity="center"
            app:layout_background_color="blue"
            android:layout_margin="50dp"
            android:layout_width="100dp"
            android:layout_height="100dp">

            <TextView
                android:textStyle="bold"
                android:textColor="#fff"
                android:text="Test"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"/>

        </LinearLayout>

        <View
            app:layout_background_color="green"
            android:layout_margin="50dp"
            android:layout_width="100dp"
            android:layout_height="100dp" />

    </com.test.learnviewpagertransformations.views.LearnLayout>

    <!--<com.test.learnviewpagertransformations.views.CustomLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        &lt;!&ndash; put first view to left. &ndash;&gt;
        <TextView
            android:background="@drawable/filled_box"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:layout_position="left"
            android:layout_gravity="fill_vertical|center_horizontal"
            android:text="l1"/>

        &lt;!&ndash; stack second view to left. &ndash;&gt;
        <TextView
            android:background="@drawable/filled_box"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:layout_position="left"
            android:layout_gravity="fill_vertical|center_horizontal"
            android:text="l2"/>

        &lt;!&ndash; also put a view on the right. &ndash;&gt;
        <TextView
            android:background="@drawable/filled_box"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:layout_position="right"
            android:layout_gravity="fill_vertical|center_horizontal"
            android:text="r1"/>

        &lt;!&ndash; by default views go in the middle; use fill vertical gravity &ndash;&gt;
        <TextView
            android:background="@drawable/green"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="fill_vertical|center_horizontal"
            android:text="fill-vert"/>

        &lt;!&ndash; by default views go in the middle; use fill horizontal gravity &ndash;&gt;
        <TextView
            android:background="@drawable/green"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical|fill_horizontal"
            android:text="fill-horiz"/>

        &lt;!&ndash; by default views go in the middle; use top-left gravity &ndash;&gt;
        <TextView
            android:background="@drawable/blue"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="top|left"
            android:text="top-left"/>

        &lt;!&ndash; by default views go in the middle; use center gravity &ndash;&gt;
        <TextView
            android:background="@drawable/blue"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:text="center"/>

        &lt;!&ndash; by default views go in the middle; use bottom-right &ndash;&gt;
        <TextView
            android:background="@drawable/blue"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom|right"
            android:text="bottom-right"/>

    </com.test.learnviewpagertransformations.views.CustomLayout>-->

</LinearLayout>

属性.xml

我为 layoutparams 制作的自定义属性

<declare-styleable name="LearnLayoutLP">
        <attr name="layout_background_color">
            <enum name="red" value="0" />
            <enum name="blue" value="1" />
            <enum name="green" value="2" />
        </attr>
    </declare-styleable>

我怎么想

onLayout 和 onMeasure 中缺少一些东西,因此我没有获得自定义属性的正确值。如果您即使在那个地方检查我的自定义 layoutparams 类,我也没有得到我使用过的值,我在日志中得到的所有值都是默认值,即 0

要求

请分享你的想法

我很乐意欢迎任何修改和改进

_/\_

标签: androidandroid-viewviewgrouplayoutparamsandroid-custom-attributes

解决方案


推荐阅读