具有选定状态的Android ImageButton?

90
如果我正在使用带有选择器背景的ImageButton,是否有一种状态可以更改使其改变外观?目前,我可以在按下时更改图像,但似乎没有“突出显示”或“选定”或类似状态,让我随意切换其外观。
这是我的XML;仅在按下时更改外观。
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_focused="true" android:state_pressed="false" android:drawable="@drawable/map_toolbar_details_selected" />
<item android:state_focused="true" android:state_pressed="true" android:drawable="@drawable/map_toolbar_details_selected" />
<item android:state_focused="false" android:state_pressed="true" android:drawable="@drawable/map_toolbar_details_selected" />
<item android:drawable="@drawable/map_toolbar_details" />


1
使用ImageButton并跟踪选定状态似乎有点像黑客。如果您想要切换功能,应该使用切换按钮。 - Andras Balázs Lajtha
6个回答

223

这对我有用:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- NOTE: order is important (the first matching state(s) is what is rendered) -->
    <item 
        android:state_selected="true" 
        android:drawable="@drawable/info_icon_solid_with_shadow" />
    <item 
        android:drawable="@drawable/info_icon_outline_with_shadow" />
 </selector>

然后在Java中:

//assign the image in code (or you can do this in your layout xml with the src attribute)
imageButton.setImageDrawable(getBaseContext().getResources().getDrawable(R.drawable....));

//set the click listener
imageButton.setOnClickListener(new OnClickListener() {

    public void onClick(View button) {
        //Set the button's appearance
        button.setSelected(!button.isSelected());

        if (button.isSelected()) {
            //Handle selected state change
        } else {
            //Handle de-select state change
        }

    }

});

为了实现平滑过渡,您还可以指定动画的时间:

<selector xmlns:android="http://schemas.android.com/apk/res/android" android:exitFadeDuration="@android:integer/config_mediumAnimTime">

3
这对我来说很有效,但我想补充一点,应该在你的drawable文件夹中创建这个xml文件,如果你希望ImageButton在被按下时高亮,你应该使用android:state_pressed而不是state_selected。此外,这个状态应该在没有状态的item上面,因为它更少见。 - Denis Kutlubaev
3
请注意:顺序很重要(渲染的是第一个匹配状态),这确实有效,但我不明白原因。 - Muhammad Babar
2
如果没有任何状态属性,该项将匹配任何状态。因此,请将选择器中的第二项视为“万能”状态。 - joshrl
2
顺序不重要,您只需要确保将 android:state_selected="false" 与默认值一起提供即可! - Muhammad Babar
我该如何在小部件中实现相同的功能?我有一个按钮,但似乎无法弄清楚如何做到这一点。 - Si8

20

ToggleImageButton 实现了 Checkable 接口并支持 OnCheckedChangeListenerandroid:checked xml 属性:

public class ToggleImageButton extends ImageButton implements Checkable {
    private OnCheckedChangeListener onCheckedChangeListener;

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

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

    public ToggleImageButton(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        setChecked(attrs);
    }

    private void setChecked(AttributeSet attrs) {
        TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.ToggleImageButton);
        setChecked(a.getBoolean(R.styleable.ToggleImageButton_android_checked, false));
        a.recycle();
    }

    @Override
    public boolean isChecked() {
        return isSelected();
    }

    @Override
    public void setChecked(boolean checked) {
        setSelected(checked);

        if (onCheckedChangeListener != null) {
            onCheckedChangeListener.onCheckedChanged(this, checked);
        }
    }

    @Override
    public void toggle() {
        setChecked(!isChecked());
    }

    @Override
    public boolean performClick() {
        toggle();
        return super.performClick();
    }

    public OnCheckedChangeListener getOnCheckedChangeListener() {
        return onCheckedChangeListener;
    }

    public void setOnCheckedChangeListener(OnCheckedChangeListener onCheckedChangeListener) {
        this.onCheckedChangeListener = onCheckedChangeListener;
    }

    public static interface OnCheckedChangeListener {
        public void onCheckedChanged(ToggleImageButton buttonView, boolean isChecked);
    }
}

res/values/attrs.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="ToggleImageButton">
        <attr name="android:checked" />
    </declare-styleable>
</resources>

2
我该如何使用它?我按照http://developer.android.com/training/custom-views/create-view.html中的说明操作,但无法使其正常工作。 - atisman
3
谢谢!请注意,使用state_checked选择器无法正常工作,您需要使用state_selected - Florian von Stosch

11

不使用更多图片的最佳方法:

public static void buttonEffect(View button){
    button.setOnTouchListener(new OnTouchListener() {

        public boolean onTouch(View v, MotionEvent event) {
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN: {
                    v.getBackground().setColorFilter(0xe0f47521,PorterDuff.Mode.SRC_ATOP);
                    v.invalidate();
                    break;
                }
                case MotionEvent.ACTION_UP: {
                    v.getBackground().clearColorFilter();
                    v.invalidate();
                    break;
                }
            }
            return false;
        }
    });
}

1
你可以使用getResources().getColor(R.color.lightblue)从你的xml中获取颜色。 - Beto Caldas
@András需要再按住按钮一会儿。你知道为什么吗? - lionelmessi

3
res/drawable文件夹中创建一个XML文件。例如,"btn_image.xml":
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/bg_state_1"
          android:state_pressed="true"
          android:state_selected="true"/>
    <item android:drawable="@drawable/bg_state_2"
          android:state_pressed="true"
          android:state_selected="false"/>
    <item android:drawable="@drawable/bg_state_selected"
          android:state_selected="true"/>
    <item android:drawable="@drawable/bg_state_deselected"/>
</selector>

你可以组合那些你喜欢的文件,例如,将“bg_state_1”更改为“bg_state_deselected”,将“bg_state_2”更改为“bg_state_selected”。
在任何这些文件中,你都可以写入以下内容:
<shape xmlns:android="http://schemas.android.com/apk/res/android"
       android:shape="rectangle">
    <solid android:color="#ccdd00"/>
    <corners android:radius="5dp"/>
</shape>

在布局文件中创建一个带有以下属性的ImageView或ImageButton:
<ImageView
    android:id="@+id/image"
    android:layout_width="50dp"
    android:layout_height="50dp"
    android:adjustViewBounds="true"
    android:background="@drawable/btn_image"
    android:padding="10dp"
    android:scaleType="fitCenter"
    android:src="@drawable/star"/>

代码后面的部分:
稍后在代码中:
image.setSelected(!image.isSelected());

2

试试这个:

 <item
   android:state_focused="true"
   android:state_enabled="true"
   android:drawable="@drawable/map_toolbar_details_selected" />

对于颜色,我也取得了成功,使用以下方法:

<selector
        xmlns:android="http://schemas.android.com/apk/res/android">
        <item
            android:state_selected="true"

            android:color="@color/primary_color" />
        <item
            android:color="@color/secondary_color" />
</selector>

嗯,似乎没有帮助。我正在使用CompoundButton。这种类型的按钮是否有特定于打开\关闭的状态? - Joren
是的,它被称为checked,请参见_isChecked()_ http://developer.android.com/reference/android/widget/CompoundButton.html - Bostwickenator

0
if (iv_new_pwd.isSelected()) {
                iv_new_pwd.setSelected(false);
                Log.d("mytag", "in case 1");
                edt_new_pwd.setInputType(InputType.TYPE_CLASS_TEXT);
            } else {
                Log.d("mytag", "in case 1");
                iv_new_pwd.setSelected(true);
                edt_new_pwd.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
            }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接