Android上的“按住”按钮需要使用onTouchListener更改状态(自定义XML选择器)

时间:2012-09-25 19:57:30

标签: android selector ontouchlistener onclicklistener

我有一个需要“按住”功能的按钮图形,所以我没有使用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()部分拉入状态更改,因此这些“按住”按钮永远不会更改状态。对用户来说是非常可怕的反馈。

我正在通过执行以下操作强制执行A​​CTION_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);
    }

但它看起来像是一个黑客,它错过了“专注但没有压力”的阶段。

之前有人绊过这个吗?

5 个答案:

答案 0 :(得分:44)

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

您可能希望在收到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;
}

答案 1 :(得分:4)

确保在onTouchListener()函数的末尾返回false。 :)

答案 2 :(得分:3)

您可以设置按钮onClickListener并将其onClick方法保留为空。 你的逻辑工具在onTouch里面。 这样你就会产生新闻效果。

P.S你不需要你可以简单使用的选择器中的所有状态:

<?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>

答案 3 :(得分: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侦听器,这也会使您的选择器工作:)

答案 4 :(得分:2)

更好的解决方案:

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