Кнопка Android остается нажатой при смене чертежа

Я хочу создать кнопку, которая становится красной при первом нажатии и возвращается к обычному серому цвету при втором (и выполняет некоторые действия, такие как удаление файла). Это предназначено для подтверждения того, что пользователь действительно хочет начать действие удаления.

Для этого я меняю фоновый рисунок на LayerDrawable с дополнительным ColorDrawable поверх рисуемого по умолчанию. Затем альфа ColorDrawable устанавливается на 0 или 255 в зависимости от состояния.

Переключение на красный цвет при первом нажатии работает, но при втором нажатии кнопка становится желтой, как в нажатом состоянии, в то время как она должна вернуться к обычному серому цвету.

Демонстрационный код:

package com.example.test;

import android.os.Bundle;
import android.app.Activity;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class TestActivity extends Activity {

    Button button;
    boolean showRed;
    ColorDrawable cd;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        button = new Button(this);
        button.setText("Delete");

        // Following two lines don't matter, focus isn't the problem
        button.setFocusable(false);
        button.setFocusableInTouchMode(false);

        cd = new ColorDrawable(0xffff0000);
        cd.setAlpha(0);

        button.setBackgroundDrawable(new LayerDrawable(new Drawable[] {
                button.getBackground(), cd}));

        setContentView(button);


        button.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                showRed = !showRed;

                if (showRed)
                    cd.setAlpha(255);
                else
                    cd.setAlpha(0);

                // Following line doesn't matter
                button.setSelected(false);

                button.getBackground().invalidateSelf();
            }
        });
    }
}

person Michael Butscher    schedule 30.05.2013    source источник


Ответы (3)


Почему бы вам не использовать селектор для этой цели и не поместить свой селектор в папку с возможностью рисования. Предположим, что ваш button_state.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/button_pressed" /> <!-- pressed -->
     <item android:state_focused="true"
     android:drawable="@drawable/button_focused" /> <!-- focused -->
     <item android:drawable="@drawable/button_normal" /> <!-- default -->
 </selector>

Затем в свою кнопку вы можете добавить это:

<Button
        android:id="@+id/homeButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="10px"
        android:background="@drawable/button_state" />
person Syamantak Basu    schedule 30.05.2013
comment
Если я правильно понимаю, это будет использовать только пользовательские чертежи для нажатого или сфокусированного состояния. Но на самом деле мне нужно новое состояние (action_requested или около того). - person Michael Butscher; 30.05.2013

Я думаю, что то, чего вы пытаетесь достичь, можно легко сделать, используя кнопку-переключатель вместо обычной кнопки и задав ей фон.

Кнопка-переключатель может справиться с проблемой первого и второго щелчка, поскольку они предназначены для переключения.

Я говорю, что используйте тумблер вместо обычной кнопки, тогда в зависимости от вашей ситуации вы можете сделать две вещи:

1.> Назначьте фон кнопки переключения XML-файлу селектора, который будет обрабатывать цвет для разных состояний (нажато, сфокусировано, по умолчанию и т. д.). Для состояний проверьте документы на сайте разработчика.

2.> вы можете задать цвет фона по умолчанию, тогда вы можете изменить цвет для переключения проверенных и непроверенных функций.

Единственная причина, по которой я предложил кнопку переключения, заключается в том, что с ней легко работать с параметрами первого и второго щелчка.

Кроме того, как только вы меняете фон кнопки-переключателя на любой цвет или рисуемый по умолчанию, он больше не выглядит как переключатель. Вы также можете удалить написанное on и off, оставив атрибуты textOn и textOff пустыми.

<ToggleButton
    android:id="@+id/toggleButton1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignRight="@+id/textView1"
    android:layout_below="@+id/textView1"
    android:layout_marginTop="42dp"
    android:text="ToggleButton"
    android:background="@android:color/white"
    android:textOn=""
    android:textOff="" />
person Ravi    schedule 30.05.2013
comment
Я не хочу, чтобы она выглядела как кнопка-переключатель (потому что она ничего не включает и не выключает), поэтому мне каким-то образом нужно было бы сделать ее похожей на обычную кнопку, взяв доступные ресурсы обычной кнопки. Поскольку эти ресурсы могут различаться в разных версиях Android (и у разных производителей устройств), и даже их имена не стандартизированы, это будет сложно (возможно, я что-то упускаю из виду) - person Michael Butscher; 30.05.2013
comment
и создайте 9 изображений патчей для фона кнопки - person Ravi; 30.05.2013
comment
Моя идея заключалась в том, что кнопка должна выглядеть точно так же, как обычная кнопка, по крайней мере, пока она не красная. Ваши предложения (если я правильно понимаю) будут означать копирование или ссылку на доступные для рисования ресурсы системы Android, которые могут менять содержимое или даже имя с течением времени или между производителями, чтобы специальная кнопка больше не выглядела обычной. - person Michael Butscher; 30.05.2013

Теперь я сам нашел ответ: каждый Drawable ссылается на объект обратного вызова, который информируется о необходимости перерисовки. Если объект рисования назначен представлению, этот вид является обратным вызовом, если он является частью составного объекта рисования (например, LayerDrawable), этот состав является обратным вызовом.

Строка кода

    button.setBackgroundDrawable(new LayerDrawable(new Drawable[] {
            button.getBackground(), cd}));

теперь сначала поместил кнопку, которую можно рисовать по умолчанию, в LayerDrawable (поэтому обратный вызов фона по умолчанию был установлен на LayerDrawable). А затем заменил фон кнопки по умолчанию вновь созданным Drawable. Когда это происходит, обратный вызов предыдущего Drawable устанавливается равным нулю.

В итоге фон по умолчанию не имел обратного вызова для информирования о необходимости перерисовки после изменения состояния и оставался (визуально) в неправильном состоянии.

Правильный способ сделать вышеизложенное:

    Drawable oldBg = button.getBackground();
    button.setBackgroundDrawable(null);
    button.setBackgroundDrawable(new LayerDrawable(
            new Drawable[] {oldBg, cd}));

Сначала «отключить» фон по умолчанию, а затем создать и установить новый.

person Michael Butscher    schedule 31.05.2013