You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Android自定义LinearLayout控件边框布局切换问题排查与实现

正确实现方案

1. 确保EditText的初始化时机正确

ValidLayout不要在构造方法里添加EditText,而是在onFinishInflate()方法中执行——这个方法会在布局inflation完成后调用,此时View树已构建完成,添加子View更可靠:

public class ValidLayout extends LinearLayout {
    protected EditText mEditText;

    // 三个构造方法统一调用init()
    public ValidLayout(Context context) {
        super(context);
        init();
    }

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

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

    private void init() {
        // 仅做基础初始化,不添加子View
        setOrientation(LinearLayout.HORIZONTAL);
    }

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        // 布局加载完成后添加EditText
        mEditText = new EditText(getContext());
        LayoutParams params = new LayoutParams(
            LayoutParams.MATCH_PARENT, 
            LayoutParams.MATCH_PARENT
        );
        // 按需设置padding、margin等属性
        mEditText.setLayoutParams(params);
        addView(mEditText);
    }
}

2. 正确解析自定义属性并延迟切换边框

在SupplementEditText中,解析属性后不要立刻调用setBorderSide,而是用post()延迟到View初始化完成后执行,避免EditText为空:

public class SupplementEditText extends ValidLayout {
    public enum BorderSide { LEFT, RIGHT }
    private BorderSide mBorderSide = BorderSide.RIGHT; // 默认右侧边框

    public SupplementEditText(Context context) {
        super(context);
        init(null);
    }

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

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

    private void init(AttributeSet attrs) {
        if (attrs != null) {
            TypedArray ta = getContext().obtainStyledAttributes(
                attrs, 
                R.styleable.SupplementEditText
            );
            // 解析枚举值,对应attrs.xml中的配置
            int sideIndex = ta.getInt(
                R.styleable.SupplementEditText_borderSide, 
                1 // 默认对应RIGHT,与attrs.xml中的value=1匹配
            );
            mBorderSide = BorderSide.values()[sideIndex];
            ta.recycle();
        }

        // 延迟执行,确保EditText已被添加
        post(() -> setBorderSide(mBorderSide));
    }

    public void setBorderSide(BorderSide borderSide) {
        mBorderSide = borderSide;
        if (mEditText == null) {
            Log.w("SupplementEditText", "EditText尚未初始化,无法设置边框");
            return;
        }

        Drawable bgDrawable;
        if (borderSide == BorderSide.RIGHT) {
            bgDrawable = ContextCompat.getDrawable(
                getContext(), 
                R.drawable.supplemental_edittext
            );
        } else {
            bgDrawable = ContextCompat.getDrawable(
                getContext(), 
                R.drawable.supplemental_edittext_left
            );
        }

        // 兼容不同Android版本的背景设置
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
            mEditText.setBackground(bgDrawable);
        } else {
            mEditText.setBackgroundDrawable(bgDrawable);
        }

        // 触发重绘和布局更新
        mEditText.invalidate();
        requestLayout();
    }
}

3. 确保自定义属性配置正确

res/values/attrs.xml中,枚举值的顺序要与代码中的BorderSide枚举完全对应:

<declare-styleable name="SupplementEditText">
    <attr name="borderSide" format="enum">
        <enum name="left" value="0"/>
        <enum name="right" value="1"/>
    </attr>
</declare-styleable>

4. 验证Drawable文件的边框方向

右侧边框的supplemental_edittext.xml示例:

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_focused="true">
        <shape android:shape="rectangle">
            <solid android:color="@android:color/white"/>
            <stroke android:width="2dp" android:color="@color/your_blue_color"/>
            <corners 
                android:topRightRadius="16dp" 
                android:bottomRightRadius="16dp"/>
        </shape>
    </item>
    <item>
        <shape android:shape="rectangle">
            <solid android:color="@android:color/white"/>
            <stroke android:width="1dp" android:color="@color/your_gray_color"/>
            <corners 
                android:topRightRadius="16dp" 
                android:bottomRightRadius="16dp"/>
        </shape>
    </item>
</selector>

左侧边框的supplemental_edittext_left.xml只需将圆角设置在左侧:

<corners 
    android:topLeftRadius="16dp" 
    android:bottomLeftRadius="16dp"/>

内容的提问来源于stack exchange,提问作者Nodoid

火山引擎 最新活动