У меня проблема с тем, что моя кнопка остается в подсвеченном состоянии после выполнения следующих действий:
public class MainActivity extends AppCompatActivity {
@SuppressLint("ClickableViewAccessibility")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
AppCompatButton button = (AppCompatButton) findViewById(R.id.mybutton);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.d("Test", "calling onClick");
}
});
button.setOnTouchListener(new View.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();
v.performClick();
Log.d("Test", "Performing click");
return true;
}
}
return false;
}
});
}
}
Что касается приведенного выше кода, при его использовании я ожидаю, что нажатие кнопки будет обработано касанием, и при возврате «true» обработка должна остановиться на touchListener.
Но это не так. Кнопка остается в подсвеченном состоянии, даже если щелчок вызывается.
Что я получаю это:
Test - calling onClick
Test - Performing click
с другой стороны, если я использую следующий код, кнопка нажимается, то же самое печатается, но кнопка не застревает в подсвеченном состоянии:
public class MainActivity extends AppCompatActivity {
@SuppressLint("ClickableViewAccessibility")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
AppCompatButton button = (AppCompatButton) findViewById(R.id.mybutton);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.d("Test", "calling onClick");
}
});
button.setOnTouchListener(new View.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();
// v.performClick();
Log.d("Test", "Performing click");
return false;
}
}
return false;
}
});
}
}
Я немного сбит с толку относительно того, что представляет собой цепочка респондента на событие касания. Я предполагаю, что это:
1) TouchListener
2) ClickListener
3) ParentViews
Может ли кто-нибудь это подтвердить?
android
onclicklistener
android-button
ontouchlistener
Белый медведь
источник
источник
Ответы:
Такие настройки не требуют программных изменений. Вы можете сделать это просто в
xml
файлах. Прежде всего, удалитеsetOnTouchListener
метод, который вы предоставляете вonCreate
полностью. Затем определите цвет селектора вres/color
каталоге, как показано ниже. (если каталог не существует, создайте его)Рез / цвет / button_tint_color.xml
Теперь установите его для
app:backgroundTint
атрибута кнопки :Визуальный результат:
РЕДАКТИРОВАНИЕ: (для решения проблемы сенсорного события)
С общей точки зрения поток сенсорного события начинается с
Activity
, затем течет вниз к макету (от родительского к дочерним макетам), а затем к представлениям. (Поток LTR на следующей картинке)Когда сенсорное событие достигает целевой вид, вид может обрабатывать то событие решило передать его предварительные раскладки / деятельности или нет (возвращающейся
false
изtrue
вonTouch
методе). (RTL поток на картинке выше)Теперь давайте взглянем на исходный код View, чтобы глубже понять потоки сенсорных событий. Взглянув на реализацию
dispatchTouchEvent
, мы увидим, что если вы установите aOnTouchListener
для представления, а затем вернетесьtrue
в егоonTouch
метод, тоonTouchEvent
представление представления не будет вызываться.Теперь посмотрим на
onTouchEvent
метод действия событияMotionEvent.ACTION_UP
. Мы видим, что там происходит действие «выполнить щелчок». Таким образом, возвращаясьtrue
вOnTouchListener
"onTouch
и " и, следовательно, не вызывая "onTouchEvent
, вызывает не вызовOnClickListener
"onClick
.Есть еще одна проблема
onTouchEvent
, связанная с отсутствием вызова , которая связана с нажатым состоянием, и вы упомянули этот вопрос. Как мы можем видеть в приведенном ниже блоке кода, есть экземплярUnsetPressedState
этого вызова, когда он выполняется. Результатом не вызова является то, что представление застревает в нажатом состоянии, и его состояние рисования не изменяется.setPressed
(false)
setPressed(false)
UnsetPressedState :
Что касается приведенного выше описания, вы можете изменить код, вызвав
setPressed(false)
себя, чтобы изменить состояние рисования, где действие событияMotionEvent.ACTION_UP
:источник
Now, look at the onTouchEvent method where the event action is MotionEvent.ACTION_UP. We see that perform-click action happens there. So, returning true in the OnTouchListener's onTouch and consequently not calling the onTouchEvent, causes not calling the OnClickListener's onClick.
в моем случае вызывается onClick. mUnsetPressedState проверяет, имеет ли оно значение null, перед установкой в false, а также, что runnable не запускается, если мы предварительно сжаты. Я не совсем понимаю , как вы вычитать , что он должен быть установлен в ложьonClick
Называется потому , что вы звонитеv.performClick();
. Пожалуйста, проверьте приведенный выше код вMotionEvent.ACTION_UP
разделе еще раз,setPressed(false)
в любом случаеmUnsetPressedState
вызывается , является ли он пустым или нет,prepressed
является ли он истинным или нет. Разница заключается в способе вызова,setPressed(false)
который может быть черезpost
/postDelayed
или напрямую.Вы бездельничаете
touch
иfocus
событиями. Давайте начнем с понимания поведения с тем же цветом. По умолчанию в AndroidSelector
задано фоновое изображениеButton
. Так что, просто меняя цвет фона, make остается статичным (цвет не изменится). Но это не родное поведение.Selector
может выглядеть такКак вы можете видеть выше, есть состояние
focused
и состояниеpressed
. Установив,onTouchListener
вы будете обрабатывать сенсорные события, которые не имеют ничего общего сfocus
.Selector
Кнопки должны заменитьfocus
событиеtouch
во время события нажатия на кнопку. Но в первой части вашего кода вы перехватили события дляtouch
(возвращая true из обратного вызова). Изменение цвета не может продолжаться дальше и замерзает тем же цветом. И вот почему второй вариант (без перехвата) работает нормально, и это ваше замешательство.ОБНОВИТЬ
Все, что вам нужно сделать, это изменить поведение и цвет для
Selector
. Например используя следующий фон дляButton
. И удалитьonTouchListener
из вашей реализации вообще.источник
onTouchListener
символов, сколько захотите. Вам просто не нужно использовать событие, поreturn true
.backgroundColor
.если вы назначите фон кнопке, он не изменит цвет при нажатии.
и установите его в качестве фона для вашей кнопки
источник
Вы можете просто использовать материал Chips вместо Button view. обратитесь: https://material.io/develop/android/components/chip, где они обрабатывают эти hililghted события, и вы можете настроить с применением тем.
источник