Android ImageButton z wybranym stanem?

87

Gdybym używał ImageButton z selektorem jako tło, czy istnieje stan, który mogę zmienić, który spowoduje, że zmieni on swój wygląd? W tej chwili mogę zmusić go do zmiany obrazów po naciśnięciu, ale wydaje się, że nie ma „podświetlonego”, „wybranego” lub podobnego stanu, który pozwala mi dowolnie przełączać jego wygląd.

Oto mój XML; zmienia wygląd tylko po naciśnięciu.

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

Joren
źródło
1
Używanie ImageButton i śledzenie wybranego stanu wydaje się trochę hackem. Powinieneś użyć przycisku przełączania, jeśli chcesz przełączać funkcje.
Andras Balázs Lajtha

Odpowiedzi:

214

To działa dla mnie:

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

A potem w javie:

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

    }

});

Aby zapewnić płynne przejście, możesz również wspomnieć o czasie animacji:

<selector xmlns:android="http://schemas.android.com/apk/res/android" android:exitFadeDuration="@android:integer/config_mediumAnimTime">
joshrl
źródło
3
To zadziałało dla mnie, ale chciałbym dodać, że należy utworzyć ten plik XML w swoim folderze do rysowania i jeśli chcesz, aby ImageButton podświetlał po naciśnięciu, powinieneś użyć android: state_pressed zamiast state_selected. Ponadto stan ten powinien znajdować się powyżej elementu bez stanu, ponieważ jest on mniej ogólny.
Denis Kutlubaev
3
NOTE: order is important (the first matching state(s) is what is renderedto zadziałało, ale dziwne, nie rozumiem. DLACZEGO?
Muhammad Babar
2
W przypadku braku atrybutów stanu element będzie pasował do dowolnego stanu. Pomyśl więc o drugiej pozycji selektora jako o stanie „catch all”.
joshrl
2
Kolejność nie jest ważna, musisz tylko upewnić się, że dostarczasz android:state_selected="false" domyślną!
Muhammad Babar
Jak mogę zrobić to samo w widżecie? Mam przycisk, ale nie wiem, jak to zrobić.
Si8
19

ToggleImageButtonktóry realizuje Checkableinterfejsu i podpór OnCheckedChangeListeneroraz android:checkedatrybut 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>
vokilam
źródło
2
Jak mogę tego używać? Postępowałem zgodnie z instrukcją w: developer.android.com/training/custom-views/create-view.html, ale nie mogłem tego zrobić.
atisman
2
Dzięki! Zauważ, że selektor z state_checkednie działa z tym jednak, musisz użyć state_selected.
Florian von Stosch,
11

Najlepszy sposób na zrobienie tego bez większej ilości obrazów:

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;
        }
    });
}
András
źródło
1
możesz użyć metody getResources (). getColor (R.color.lightblue) do pokolorowania ze swojego xml.
Beto Caldas
@ András musi jeszcze trochę przytrzymać przycisk. Czy wiesz, dlaczego tak jest?
lionelmessi
3

Utwórz plik XML w res/drawablefolderze. Na przykład „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>

Możesz łączyć pliki, które lubisz, na przykład zmienić „bg_state_1” na „bg_state_deselected” i „bg_state_2” na „bg_state_selected”.

W każdym z tych plików możesz napisać coś takiego:

<shape xmlns:android="http://schemas.android.com/apk/res/android"
       android:shape="rectangle">
    <solid android:color="#ccdd00"/>
    <corners android:radius="5dp"/>
</shape>

Utwórz w pliku układu ImageView lub ImageButton z następującymi atrybutami:

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

Później w kodzie:

image.setSelected(!image.isSelected());
CoolMind
źródło
2

Spróbuj tego:

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

Również w przypadku kolorów, z którymi odniosłem sukces

<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>
Alex Volovoy
źródło
Hmm. Nie wydaje się pomagać. Używam CompoundButton. Czy istnieje stan specyficzny dla tego typu przycisku włączania / wyłączania?
Joren
Tak, nazywa się zaznaczone, zobacz isChecked () developer.android.com/reference/android/widget/…
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);
            }
MEGHA DOBARIYA
źródło