Android 上的“按住”按钮需要使用 onTouchListener 更改状态(自定义 XML 选择器)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12590169/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
"Press and hold" button on Android needs to change states (custom XML selector) using onTouchListener
提问by Octoth0rpe
I've got a button graphic which needs to have "press and hold" functionality, so instead of using onClickListener, I'm using onTouchListener so that the app can react to
我有一个需要“按住”功能的按钮图形,因此我使用的是 onTouchListener,而不是使用 onClickListener,以便应用程序可以对
MotionEvent.ACTION_DOWN,
and
和
MotionEvent.ACTION_UP
Depending on how quickly those two events are triggered, I can run a "pressAndHoldHandler" in the time between the two.
根据触发这两个事件的速度,我可以在两者之间的时间内运行“pressAndHoldHandler”。
Anyway, long story short: I have numerous "basic" buttons in the same app that don't require the press and hold functionality, so they are using the onClickListener.
无论如何,长话短说:我在同一个应用程序中有许多不需要按住功能的“基本”按钮,因此它们使用 onClickListener。
Every single one of these buttons have been customized graphically with their own XML selector file:
这些按钮中的每一个都使用自己的 XML 选择器文件以图形方式自定义:
<?xml version="1.0" encoding="UTF-8"?>
<selector
xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:state_enabled="false"
android:drawable="@drawable/btn_chicken_off" />
<item
android:state_enabled="true"
android:state_pressed="true"
android:drawable="@drawable/btn_chicken_s3" />
<item
android:state_enabled="true"
android:state_focused="true"
android:drawable="@drawable/btn_chicken_s2" />
<item
android:state_enabled="true"
android:drawable="@drawable/btn_chicken_off" />
</selector>
So, the problem here is: The above selector doesn't get accessed with the onTouchListener. Only the onClickListener will pull in the state changes with the onClick() section of its own method, so these "press and hold" buttons never change state. Pretty terrible feedback for the user.
所以,这里的问题是:上面的选择器不能通过 onTouchListener 访问。只有 onClickListener 会使用它自己方法的 onClick() 部分拉入状态更改,因此这些“按住”按钮永远不会改变状态。对用户来说非常糟糕的反馈。
I'm currently forcing the above inside the switch case of ACTION_DOWN and ACTION_UP by doing the following:
我目前正在通过执行以下操作在 ACTION_DOWN 和 ACTION_UP 的 switch case 中强制执行上述操作:
if (action == MotionEvent.ACTION_DOWN) {
btn_chicken.setBackgroundResource(R.drawable.btn_chicken_s3);
}
else
if (action == MotionEvent.ACTION_UP) {
btn_chicken.setBackgroundResource(R.drawable.btn_chicken_off);
}
But it seems like a hack, and it's missing the "focused but not pressed" stage.
但这似乎是一种黑客行为,并且缺少“专注但未按下”的阶段。
Anybody tripped across this before?
以前有人绊倒过这个吗?
回答by Eyal Biran
Use the view.setPressed()
function to simulate the pressed behavior by yourself.
使用该view.setPressed()
功能可以自行模拟按下的行为。
You would probably want to enable the Pressedstate when you get ACTION_DOWN
event and disable it when you get the ACTION_UP
event.
您可能希望在获得事件时启用Pressed状态并在获得ACTION_DOWN
事件时禁用它ACTION_UP
。
Also, it will be a good idea to disable it in case the user slide out of the button. Catching the ACTION_OUTSIDE
event, as shown in the example below:
此外,如果用户滑出按钮,最好禁用它。捕获ACTION_OUTSIDE
事件,如下例所示:
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
v.setPressed(true);
// Start action ...
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_OUTSIDE:
case MotionEvent.ACTION_CANCEL:
v.setPressed(false);
// Stop action ...
break;
case MotionEvent.ACTION_POINTER_DOWN:
break;
case MotionEvent.ACTION_POINTER_UP:
break;
case MotionEvent.ACTION_MOVE:
break;
}
return true;
}
回答by Lei
Make sure to return false
at the end of the onTouchListener() function. :)
确保false
在 onTouchListener() 函数结束时返回。:)
回答by Givi
You can just set the button onClickListener and leave its onClick method empty. Your logic implement inside onTouch. That way you'll have the press effect.
您可以只设置按钮 onClickListener 并将其 onClick 方法留空。您的逻辑在 onTouch 内实现。这样你就会有新闻效果。
P.S You don't need all those state in the selector you can simply use:
PS您不需要选择器中的所有这些状态,您可以简单地使用:
<?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/IMAGE_PRESSED" />
<item android:drawable="@drawable/IMAGE" />
</selector>
回答by Andrés Pachon
I figured it out! Just use view.setSelected()
as follows:
我想到了!只需view.setSelected()
按如下方式使用:
@Override
public boolean onTouch(View v, MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_DOWN){
yourView.setSelected(true);
...
return true;
}
else if(event.getAction() == MotionEvent.ACTION_UP){
yourView.setSelected(false);
...
return true;
}
else
return false;
}
That'll make your selector work even if your view has an onTouch listener :)
即使您的视图具有 onTouch 侦听器,这也会使您的选择器正常工作 :)
回答by M. Usman Khan
Better solution:
更好的解决方案:
<?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>
@Override
public void onClick(View v) {
if (v.isActivated())
v.setActivated(false);
else
v.setActivated(true);
}