21

我有一个按钮图形需要具有“按住”功能,所以我没有使用 onClickListener,而是使用 onTouchListener,以便应用程序可以对

 MotionEvent.ACTION_DOWN,

 MotionEvent.ACTION_UP

根据触发这两个事件的速度,我可以在两者之间运行“pressAndHoldHandler”。

无论如何,长话短说:我在同一个应用程序中有许多不需要按住功能的“基本”按钮,因此它们正在使用 onClickListener。

这些按钮中的每一个都已使用自己的 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>

所以,这里的问题是:上面的选择器没有被 onTouchListener 访问。只有 onClickListener 会通过它自己的方法的 onClick() 部分引入状态更改,因此这些“按住”按钮永远不会更改状态。对用户来说非常糟糕的反馈。

我目前正在通过执行以下操作在 ACTION_DOWN 和 ACTION_UP 的开关盒内强制执行上述操作:

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);
    }

但这似乎是一个 hack,它缺少“专注但不紧迫”的阶段。

以前有人绊倒过吗?

4

5 回答 5

46

使用该view.setPressed()功能自行模拟按下行为。

您可能希望在收到事件时启用Pressed状态,并在收到ACTION_DOWN事件时禁用它ACTION_UP

此外,如果用户滑出按钮,最好禁用它。捕获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;
}
于 2013-09-01T06:38:17.677 回答
5

确保false在 onTouchListener() 函数结束时返回。:)

于 2013-01-09T07:45:27.520 回答
3

您可以只设置按钮 onClickListener 并将其 onClick 方法留空。您的逻辑在 onTouch 内部实现。这样你就会有新闻效果。

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>
于 2012-09-25T22:32:12.450 回答
3

我想到了!只需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;
}

即使您的视图具有 onTouch 侦听器,这也会使您的选择器工作:)

于 2012-11-19T18:49:38.503 回答
3

更好的解决方案:

<?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);
}
于 2014-03-18T10:20:17.517 回答