且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

在自定义按钮自定义属性不显示

更新时间:2022-10-16 21:59:03

  

自定义按钮偏移,修剪,这是无法点击

这是由于您使用的构造函数。该按钮类做链它的构造函数之间,但它并没有通过 0 最后一个构造函数的样式(从第二个构造函数是使用的),它通过一个内部风格(是什么让一个视觉按钮到底)。如果你要传递:

 这(背景下,ATTRS,android.R.attr.buttonStyle);
 

按钮应该没问题。

  

彩色滤光片不适用

在code设置彩色滤光片应该没有问题后,您对上面的更正。当您将设置过滤器,你会看到两个按钮将应用这些过滤器(因为它们具有相同的位图(我假设你使用图像))。这是因为发生在同类型股票的可绘制一个恒定的状态。你可以阅读更多从罗曼盖伊的解释这里

 的getBackground()变异()setColorFilter(BACKGROUNDCOLOR,Mode.MULTIPLY)。
 

让我知道如果这解决了问题(从我的理解):

 公共静态MyButton类扩展按钮{

    私人诠释BACKGROUNDCOLOR;
    私人StateListDrawable MSLD;
    私人PorterDuffColorFilter mColorFilter;
    私人布尔mHandled = FALSE;

    公共用作MyButton(上下文的背景下,ATTRS的AttributeSet,诠释defStyle){
        // ...
        尝试 {
            // ...
            MSLD =(StateListDrawable)的getBackground();
            mColorFilter =新PorterDuffColorFilter(BACKGROUNDCOLOR,
                    Mode.MULTIPLY);
            mSld.setColorFilter(mColorFilter);
        } 最后 {
            a.recycle();
        }
    }

    @覆盖
    保护无效的OnDraw(帆布油画){
        如果(!mHandled){
            最终绘制对象电流= mSld.getCurrent();
            current.mutate();
            current.setColorFilter(mColorFilter);
            mHandled = TRUE;
        }
        super.onDraw(画布);
    }

}
 

I extended the Button widget to be able to apply several custom attributes.
One of the attributes is a color filter I try to apply to its background when the button is created. It does not work. (See the screen shots and code below)
I tried to directly set the background color, on the same code place, and it does change the background color, but it is not what I need, since I am using my own button PNGs.

there are 2 problems so far:

  1. The color filter is not applied
  2. The custom button is offset, clipped and it is not clickable

The second button uses the normal button, and it is positioned as expected and it is clickable. The second screenshot shows that the correct color is indeed chosen, and that it is possible to change the button background color at that point in the code.

Code:

public class MyButton extends Button {
    private int backGroundColor;

    public MyButton(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        TypedArray a = context.getTheme().obtainStyledAttributes(
            attrs, 
            R.styleable.MyButton, 
            defStyle, 
            0);

        try {
            Resources res = getResources();
            switch( a.getInteger(R.styleable.MyButton_type, 0) ) {
            case 0: 
                backGroundColor = res.getColor(R.color.Black); break;
            case 1: 
                backGroundColor = res.getColor(R.color.Red); break;
            case 2: 
                backGroundColor = res.getColor(R.color.DimGray); break;
            }
            getBackground().setColorFilter(backGroundColor, Mode.MULTIPLY);
            //setBackgroundColor(backGroundColor)
        } finally {
            a.recycle();
        }
    }
    public MyButton(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }
    public MyButton(Context context) {
        this(context, null, 0);
    }
}

The XML I used:

<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>

Screenshot of setColorFilter() outcome

Screenshot of setBackgroundColor() outcome

EDIT This is the selector XML I use for the normal and pressed states.

<?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>

The custom button is offset, clipped and it is not clickable

That's due to your use of the constructors. The Button class does chain between its constructors but it doesn't pass 0 to the last constructor as the style(from the second constructor which is the one used), it passes an internal style(what makes a visual Button in the end). If you were to pass:

this(context, attrs, android.R.attr.buttonStyle);

the Button should be ok.

The color filter is not applied

The code for setting the color filter should work with no problems after you make the correction above. When you'll set the filter you'll see that both buttons will have the filter applied to them(as they have the same bitmap(I'm assuming you use an image)). This is happening because the drawables of the same type share a constant state. You can read more from Romain Guy's explanation here:

getBackground().mutate().setColorFilter(backGroundColor, Mode.MULTIPLY);

Let me know if this solves the problem(from what I understood):

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);
    }

}