2012-09-25 5 views
18

Ich habe eine Schaltfläche Grafik, die "drücken und halten" -Funktion haben muss, so dass ich OnClickListener verwenden, verwende ich onTouchListener so dass die App auf"Drücken und halten" -Taste auf Android muss Status ändern (benutzerdefinierte XML-Selektor) mit OnTouchListener

reagieren können
MotionEvent.ACTION_DOWN, 

und

MotionEvent.ACTION_UP 

Je nachdem, wie schnell diese beiden Ereignisse ausgelöst werden, kann ich eine „pressAndHoldHandler“ in der Zeit zwischen den beiden laufen.

Wie auch immer, lange Geschichte kurz: Ich habe zahlreiche "grundlegende" Schaltflächen in der gleichen App, die nicht die drücken und halten-Funktion benötigen, so dass sie den onClickListener verwenden.

Jeder einzelne dieser Tasten haben grafisch mit ihrer eigenen XML-Selektor-Datei angepasst worden:

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

Also, das Problem hier ist: Die obige Selektor erhält nicht mit dem onTouchListener abgerufen. Nur der onClickListener zieht die Statusänderungen mit dem onClick() - Abschnitt seiner eigenen Methode ein, sodass diese "Drücken und Halten" -Schaltflächen den Status nie ändern. Ziemlich schreckliches Feedback für den Benutzer.

Ich zwinge zur Zeit der oben innerhalb des Schaltergehäuses von ACTION_DOWN und ACTION_UP durch folgende Maßnahmen:

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

Aber es scheint wie ein Hack, und es ist die „fokussierte aber nicht gedrückt“ Bühne fehlt.

Hat jemand schon einmal darüber gestolpert?

+0

Das war genau mein Problem. Danke für die gute Beschreibung. – Suragch

Antwort

41

Verwenden Sie die view.setPressed() Funktion, um das gedrückte Verhalten selbst zu simulieren.

Sie würden wahrscheinlich wollen die Gepresste Zustand aktivieren, wenn Sie ACTION_DOWN Ereignis erhalten und es deaktivieren, wenn Sie die ACTION_UP Veranstaltung.

Es ist auch eine gute Idee, es zu deaktivieren, falls der Benutzer aus der Taste rutschen sollte.das ACTION_OUTSIDE Ereignis Fangen, wie im Beispiel unten gezeigt:

@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; 
} 
+2

Ich glaube nicht, dass ACTION_OUTSIDE tatsächlich ausgelöst wird. Das scheint speziell für das Berühren außerhalb von Dialogen zu sein. – yincrash

+0

"ACTION_CANCEL" wäre ein guter Ort, um 'view.setPressed (false) aufzurufen; ' –

+0

Setzen' view.setPressed (false) 'in' MotionEvent.ACTION_UP: 'funktionierte für mich.Ich konnte nicht erreichen, dass es nicht funktionierte, auch wenn ich aus der Sicht rutschte, anstatt nur meine hochzuheben Finger. – Suragch

2

Sie können nur die Schaltfläche onClickListener setzen und seine onClick-Methode leer lassen. Ihre Logik in onTouch implementieren. Auf diese Weise haben Sie den Presse-Effekt.

P.S Sie nicht alle diesen Staat im Selektor benötigen, können Sie einfach verwenden:

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

Nun, ich habe es versucht, und es wird nicht funktionieren: onTouch ist keine Methode von onClickListener. und ich muss immer noch die für diejenigen, die einen Trackball verwenden. irgendwelche anderen Ideen Leute? – Octoth0rpe

+0

ich bedeutete für Sie, Ihre ontouch-Methode so zu lassen, wie sie ist, aber entfernen Sie das Stück Code, der den Hintergrund von ihm ändert. ZUSÄTZLICH, setze die Ansicht auf Klick-Listener (zB yourView.setOnClickListener (new OnClick ....) und lass es leer. So hast du den Presse-Effekt. – Givi

+0

Ich kann bestätigen, dass das obige nicht funktioniert :(@ Octoth0rpe: Haben Sie einen Workaround gefunden? –

2

ich es herausgefunden! Nur view.setSelected() wie folgt verwenden:

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

Das wird Ihre Auswahl funktionieren, auch wenn Ihre Ansicht hat einen OnTouch Hörer :)

3

Stellen Sie sicher, zurückzukehren false am Ende des onTouchListener() Funktion machen. :)

1

Bessere Lösung:

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