web-dev-qa-db-ja.com

Android onTouchListenerを使用して状態(カスタムXMLセレクター)を変更する必要がある)の[長押し]ボタン

「押し続ける」機能が必要なボタングラフィックがあるので、onClickListenerを使用する代わりに、アプリが反応できるようにonTouchListenerを使用しています。

 MotionEvent.ACTION_DOWN,

そして

 MotionEvent.ACTION_UP

これら2つのイベントがトリガーされる速度に応じて、2つのイベントの間に「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);
    }

しかし、それはハックのようであり、「集中しているが、押し付けられていない」ステージがありません。

これまでに誰かがつまずいたのですか?

19
Octoth0rpe

view.setPressed()関数を使用して、押された動作を自分でシミュレートします。

おそらく、ACTION_DOWNイベントを取得したときにPressed状態を有効にし、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;
}
44
Eyal Biran

OnTouchListener()関数の最後で必ずfalseを返します。 :)

4
Lei

ボタン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>
3
Givi

私はそれを考え出した!次のように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リスナーがある場合でもセレクタが機能します。

3
Andrés Pachon

より良いソリューション:

<?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);
}
2
M. Usman Khan