Android 自定义按钮上的自定义属性不显示

Android 自定义按钮上的自定义属性不显示,android,button,custom-controls,Android,Button,Custom Controls,我扩展了Button小部件,使其能够应用多个自定义属性。 其中一个属性是一个颜色过滤器,我尝试在创建按钮时将其应用于其背景。它不起作用。(请参见下面的屏幕截图和代码) 我试图在同一个代码位置直接设置背景色,它确实改变了背景色,但这不是我需要的,因为我使用的是我自己的按钮PNG 目前有两个问题: 未应用颜色过滤器 自定义按钮是偏移、剪裁的,不可单击 第二个按钮使用普通按钮,按预期定位,可单击。第二个屏幕截图显示确实选择了正确的颜色,并且可以在代码中的该点更改按钮背景色 代码: 我使用的XML: &

我扩展了Button小部件,使其能够应用多个自定义属性。
其中一个属性是一个颜色过滤器,我尝试在创建按钮时将其应用于其背景。它不起作用。(请参见下面的屏幕截图和代码)
我试图在同一个代码位置直接设置背景色,它确实改变了背景色,但这不是我需要的,因为我使用的是我自己的按钮PNG

目前有两个问题:

  • 未应用颜色过滤器
  • 自定义按钮是偏移、剪裁的,不可单击
  • 第二个按钮使用普通按钮,按预期定位,可单击。第二个屏幕截图显示确实选择了正确的颜色,并且可以在代码中的该点更改按钮背景色

    代码:

    我使用的XML:

    <LinearLayout 
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <com.example.test.MyButton
            android:id="@+id/btn1"
            android:text="BTN1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:textSize="14sp"
            android:textColor="@color/Blue"
            android:padding="2dp"
            android:layout_margin="4dp"
            android:background="@drawable/key_selector"
            app:type="RedButton"/>
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:textSize="14sp"
            android:textColor="@color/Blue"
            android:padding="2dp"
            android:layout_margin="4dp"
            android:background="@drawable/key_selector"
            android:id="@+id/btn2"
            android:text="BTN2"/>
    </LinearLayout>
    
    
    
    setColorFilter()结果的屏幕截图

    setBackgroundColor()结果的屏幕截图

    编辑 这是我用于正常和按下状态的选择器XML

    <?xml version="1.0" encoding="utf-8"?>
    <selector xmlns:android="http://schemas.android.com/apk/res/android" >
    
        <item
            android:drawable="@drawable/key1_pressed"
            android:state_pressed="true"/>
    
        <item 
            android:drawable="@drawable/key1"/>
    
    
    </selector>
    
    
    
    自定义按钮是偏移、剪裁的,不可单击

    这是由于您使用了构造函数。
    Button
    类在其构造函数之间进行链接,但它不会将
    0
    作为样式传递给最后一个构造函数(从使用的第二个构造函数开始),而是传递一个内部样式(最终是什么构成了可视的
    Button
    )。如果你要通过:

    this(context, attrs, android.R.attr.buttonStyle);
    
    按钮应该正常

    未应用颜色过滤器

    进行上述校正后,设置颜色过滤器的代码应该可以正常工作。设置过滤器时,您将看到两个按钮都将应用过滤器(因为它们具有相同的位图(我假设您使用图像))。发生这种情况是因为相同类型的可绘图项共享一个常量状态。你可以从Romain Guy的解释中了解更多:

    让我知道这是否解决了问题(根据我的理解):


    对构造函数样式的修复解决了偏移、剪裁和可点击的问题。颜色问题并没有100%解决。我试过有无变异()。在没有mutate()的情况下,所有按钮最初都具有相同的颜色,但当您单击它们时,它们会有自己的颜色。使用mutate()(+invalidate()+requestLayout(),如指南中所示)所有按钮立即获得颜色。。。但是第一个。行中的第一个按钮在单击之前不会获得任何颜色。知道为什么吗?@ilombo也许你可以分享一些关于如何处理“点击”的代码?在这一点上,唯一的处理方法是使用一个键选择器。我还没有编码,也没有定义
    onClick
    方法。我将在问题主体中添加选择器代码。受压状态只是正常状态的一个位移。也许这可以解释发生了什么。我当前的旁路是插入一个普通按钮作为第一个按钮,宽度和高度为0dp,不可见+扭曲,我还定义了相同的键选择器。它起作用了。如果我没有定义键选择器,那么它就不工作,第二个按钮在单击之前不会获得其颜色。
    this(context, attrs, android.R.attr.buttonStyle);
    
    getBackground().mutate().setColorFilter(backGroundColor, Mode.MULTIPLY);
    
    public static class MyButton extends Button {
    
        private int backGroundColor;
        private StateListDrawable mSld;
        private PorterDuffColorFilter mColorFilter;
        private boolean mHandled = false;
    
        public MyButton(Context context, AttributeSet attrs, int defStyle) {
            // ...
            try {
                //...
                mSld = (StateListDrawable) getBackground();
                mColorFilter = new PorterDuffColorFilter(backGroundColor,
                        Mode.MULTIPLY);
                mSld.setColorFilter(mColorFilter);
            } finally {
                a.recycle();
            }
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
            if (!mHandled) {
                final Drawable current = mSld.getCurrent();
                current.mutate();
                current.setColorFilter(mColorFilter);
                mHandled = true;
            }
            super.onDraw(canvas);
        }
    
    }