кнопка Android, нажатая после onClick

#android #button #state

#Android #кнопка #состояние

Вопрос:

вчера я заметил возможность интегрировать фрагменты на более старых уровнях API через пакет совместимости, но это не очень важно для вопроса. 🙂

У меня есть кнопка с OnClickListener

 Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(new OnClickListener() {
    @Override
    public void onClick(View v) {
        doSomething();
        button.setPressed(true);
    }
});
  

Из-за фактического нажатия она отображается как нажатая, а после отпускания кнопки состояние кнопки не нажато и остается таким.

Есть ли простой способ сохранить нажатой состояние кнопки после отпускания? Первое, о чем я могу подумать, это какой-то таймер, но это кажется неразумным.

Комментарии:

1. использовать setSelected(boolean state)

2. Привет, стрем — не могли бы вы, пожалуйста, перечислить, как именно вы это исправили? Вы имеете в виду, что хотите, чтобы кнопка отображалась нажатой в течение установленного времени, пока событие не завершится? Или сбросить нажатую кнопку? В любом случае, пожалуйста, покажите свое решение, потому что решение, которое вы выбрали ниже, было неправильным..

Ответ №1:

Просто отметим, что это связано с тем, что Android изменяет setPressed как до, так и после вашего onClickEvent , поэтому изменение его самостоятельно не имеет никакого эффекта. Другой способ обойти это — использовать onTouchEvent .

 button.setOnTouchListener(new OnTouchListener() {

    @Override
    public boolean onTouch(View v, MotionEvent event) {

        // show interest in events resulting from ACTION_DOWN
        if (event.getAction() == MotionEvent.ACTION_DOWN) return true;

        // don't handle event unless its ACTION_UP so "doSomething()" only runs once.
        if (event.getAction() != MotionEvent.ACTION_UP) return false;

        doSomething();
        button.setPressed(true);                    
        return true;
   }
});
  

Комментарии:

1. Мартин, мне очень нравится твой ответ. Однако, когда я нажимаю в области уведомлений или в меню параметров, нажатое состояние исчезает. У вас есть какое-либо представление о том, что происходит?

Ответ №2:

Используйте ToggleButton вместо Button .

 <ToggleButton
    android:id="@ id/button2"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_weight="1"
    android:background="@drawable/topping_selector"
    android:checked="false"
    android:textOff="Topping2"
    android:textOn="Topping2" />
  

topping_selector.xml:

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

    <item android:state_checked="true" 
        android:drawable="@drawable/btn_topping_on" />

    <item android:state_checked="false" 
        android:drawable="@drawable/btn_topping_off" />

</selector>
  

Ответ №3:

Вы можете сохранить состояния кнопки в XML-файле в папке drawable, а затем использовать в качестве фона для кнопки. Например:

  android:background="@drawable/buttonstate"
  

buttonstate.xml

 <?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true" android:drawable="@drawable/back_focused" />
    <item android:drawable="@drawable/back" /> <!-- default -->
</selector>
  

Комментарии:

1. не совсем то, на что я надеялся, но тем не менее спасибо! теперь она работает с помощью button.setSelected (true) и определяет возможность рисования для этого состояния

2. не то, что просил пользователь, не решает проблему. Этот ответ действительно не должен быть одобрен.

3. Я согласен с Чаком стремом — пожалуйста, опубликуйте пример того, как вы это сделали с помощью setSelected (true), если вам удалось добиться этого таким образом. Возвращается ли кнопка в нормальное состояние после завершения действия?

4. @strem проверьте мое решение ниже

Ответ №4:

Лучшее решение:

В XML-файле:

 <?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
    <item android:state_activated="true">
        <bitmap android:src="@drawable/image_selected"/>
    </item>
    <item>
        <bitmap android:src="@drawable/image_not_selected"/>
    </item>
</selector>
  

И в Java:

 @Override
public void onClick(View v) {
   v.setActivated(!v.isActivated());
}
  

Комментарии:

1. Ха-ха. Слишком много строк для простой задачи: v.setActivated(!v.isActivated()) Но все равно спасибо

2. если это логика, то вам не нужен селектор, чтобы .. просто настраивать вещи самостоятельно. плохое решение’

Ответ №5:

Вы можете использовать класс android.os.Handler. Некрасивая, но тоже работает:

 final Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(new OnClickListener() {
    @Override
    public void onClick(View v) {
        doSomething();
        new Handler().post(new Runnable() {
            @Override
            public void run() {
                button.setPressed(true);
            }
        });
    }
});
  

Ответ №6:

Другим решением является расширение Button и переопределение setPressed(boolean pressed) метода, чтобы вы могли обрабатывать вызовы платформы из onClickEvent , используя флаг, например, изменяя логический нажатый параметр в зависимости от ваших потребностей.

 public class MyButton extends Button {
   boolean isSelected = false;  //this is your flag
   @Override
   public void setPressed(boolean pressed) {
       if(isSelected) {
           //here you change the parameter so it stays pressed
           super.setPressed(true);
           return;
       }
       super.setPressed(pressed);
   }

   public void setIsSelected(boolean selected) {
       this.isSelected = selected;
   }

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

Ответ №7:

Это решение, которое я использовал, оно также работает на Android 7.0 на данный момент.

YourActivity.java

 public void onStandbyStart(String message) {
    startStandbyBtn.setActivated(true);
}

public void onBackOnline(String message) {
    startStandbyBtn.setActivated(false);
}
  

YourActivityLayout

 <Button
        ...
        style="@style/generic_btn_style"
        ... />
  

values/styles.xml

     <style name="generic_btn_style" parent="@android:style/Widget.Button">
        <item name="android:gravity">center_vertical|center_horizontal</item>
        <item name="android:background">@drawable/generic_btn</item>
        <item name="android:textColor">@color/selector_white_black</item>
        <item name="android:focusable">true</item>
        <item name="android:clickable">true</item>
</style>
  

drawable/generic_btn.xml
Этот селектор выбирает фон кнопки. Я использую нажатую как активированную.

 <?xml version="1.0" encoding="utf-8"?>

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/generic_btn_disabled" android:state_enabled="false" />
    <item android:drawable="@drawable/generic_btn_pressed" android:state_enabled="true" android:state_pressed="true" />
    <item android:drawable="@drawable/generic_btn_pressed" android:state_activated="true" />
    <item android:drawable="@drawable/generic_btn_focused" android:state_enabled="true" android:state_focused="true" />
    <item android:drawable="@drawable/generic_btn_enabled" android:state_enabled="true" />
</selector>
  

color /selector_black_white
Здесь я устанавливаю цвет текста. В моем случае мне нужно выбрать цвет текста черным при нажатии.

 <?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:color="#fff" android:state_pressed="true" /> <!-- pressed -->
    <item android:color="#fff" android:state_activated="true" /> <!-- pressed -->
    <item android:color="#000" /> <!-- default -->
</selector>