Hat jemand ein einfaches Beispiel für eine ListActivity, die Textansichten in einer Spalte anzeigt, und wenn Sie von links nach rechts wischen, sehen Sie diese Zeile in einer neuen Ansicht? Dies würde bedeuten, dass Sie die Daten für diese Zeile bearbeiten oder detailliertere Informationen zu dieser Zeile anzeigen. Bitte verweisen Sie nicht auf Code Shogun oder andere Websites, da ich gegoogelt und diese Antwort nicht gesehen habe.
Android Swipe auf Liste
Asaf Pinhassi
Ich hatte das gleiche Problem und habe hier keine Antwort gefunden.
Ich wollte eine Swipe-Aktion im ListView-Element erkennen und es als gewischt markieren, während OnItemClick und OnItemLongClick weiterhin unterstützt werden.
Hier ist meine Lösung:
1. Die SwipeDetector-Klasse:
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
public class SwipeDetector implements View.OnTouchListener {
public static enum Action {
LR, // Left to Right
RL, // Right to Left
TB, // Top to bottom
BT, // Bottom to Top
None // when no action was detected
}
private static final String logTag = "SwipeDetector";
private static final int MIN_DISTANCE = 100;
private float downX, downY, upX, upY;
private Action mSwipeDetected = Action.None;
public boolean swipeDetected() {
return mSwipeDetected != Action.None;
}
public Action getAction() {
return mSwipeDetected;
}
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
downX = event.getX();
downY = event.getY();
mSwipeDetected = Action.None;
return false; // allow other events like Click to be processed
case MotionEvent.ACTION_UP:
upX = event.getX();
upY = event.getY();
float deltaX = downX - upX;
float deltaY = downY - upY;
// horizontal swipe detection
if (Math.abs(deltaX) > MIN_DISTANCE) {
// left or right
if (deltaX < 0) {
Log.i(logTag, "Swipe Left to Right");
mSwipeDetected = Action.LR;
return false;
}
if (deltaX > 0) {
Log.i(logTag, "Swipe Right to Left");
mSwipeDetected = Action.RL;
return false;
}
} else if (Math.abs(deltaY) > MIN_DISTANCE) { // vertical swipe
// detection
// top or down
if (deltaY < 0) {
Log.i(logTag, "Swipe Top to Bottom");
mSwipeDetected = Action.TB;
return false;
}
if (deltaY > 0) {
Log.i(logTag, "Swipe Bottom to Top");
mSwipeDetected = Action.BT;
return false;
}
}
return false;
}
return false;
}
}
2. Ich verwende die Swipe-Detector-Klasse in der Listenansicht:
final ListView lv = getListView();
final SwipeDetector swipeDetector = new SwipeDetector();
lv.setOnTouchListener(swipeDetector);
lv.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if (swipeDetector.swipeDetected()){
// do the onSwipe action
} else {
// do the onItemClick action
}
}
});
lv.setOnItemLongClickListener(new OnItemLongClickListener() {
@Override
public boolean onItemLongClick(AdapterView<?> parent, View view,int position, long id) {
if (swipeDetector.swipeDetected()){
// do the onSwipe action
} else {
// do the onItemLongClick action
}
}
});
Auf diese Weise kann ich 3 Aktionen unterstützen – Wischen, Klicken, langes Klicken und ich kann die ListView-Elementinformationen verwenden.
SPÄTER HINZUGEFÜGT:
Da ListView eine Scroll-Aktion abfängt, ist es manchmal schwierig zu wischen. Um das Problem zu beheben, habe ich die folgende Änderung an SwipeDetector.onTouch vorgenommen:
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: {
downX = event.getX();
downY = event.getY();
mSwipeDetected = Action.None;
return false; // allow other events like Click to be processed
}
case MotionEvent.ACTION_MOVE: {
upX = event.getX();
upY = event.getY();
float deltaX = downX - upX;
float deltaY = downY - upY;
// horizontal swipe detection
if (Math.abs(deltaX) > HORIZONTAL_MIN_DISTANCE) {
// left or right
if (deltaX < 0) {
Log.i(logTag, "Swipe Left to Right");
mSwipeDetected = Action.LR;
return true;
}
if (deltaX > 0) {
Log.i(logTag, "Swipe Right to Left");
mSwipeDetected = Action.RL;
return true;
}
} else
// vertical swipe detection
if (Math.abs(deltaY) > VERTICAL_MIN_DISTANCE) {
// top or down
if (deltaY < 0) {
Log.i(logTag, "Swipe Top to Bottom");
mSwipeDetected = Action.TB;
return false;
}
if (deltaY > 0) {
Log.i(logTag, "Swipe Bottom to Top");
mSwipeDetected = Action.BT;
return false;
}
}
return true;
}
}
return false;
}
-
Warum würden andere Ereignisse wie Click nicht verarbeitet, wenn Sie true zurückgegeben hätten?
– Prometheuspk
20. Februar 2012 um 08:32 Uhr
-
@Pinhassi was wird der Wert für HORIZONTAL_MIN_DISTANCE und VERTICAL_MIN_DISTANCE sein
– AndroidDev
14. Juni 12 um 9:08 Uhr
-
HORIZONTAL_MIN_DISTANCE und VERTICAL_MIN_DISTANCE sind die Mindestabstände, die der Finger des Benutzers bewegen sollte, damit die Aktion als Streichen betrachtet wird. Ich setze es auf: HORIZONTAL_MIN_DISTANCE = 40; VERTICAL_MIN_DISTANCE = 80;
– Asaf Pinhassi
20. Juni 12 um 12:11 Uhr
-
Korrigieren Sie mich, wenn ich falsch liege, aber; sollten Sie DP-Werte für HORIZONTAL_MIN_DISTANCE & VERTICAL_MIN_DISTANCE verwenden. Diese Klasse ist eine Art Zukunftssicherer. (Für ultrahochauflösende Telefone und Tische)
– Oliver Dixon
30. April 14 um 0:16 Uhr
-
Das ist ein ziemlich toller Mann. Das einzige ist, dass es nicht so reaktionsschnell ist. Ich muss zuerst meinen Finger lange genug auf dem Objekt halten, und erst dann kann ich wischen. Außerdem registriert es die meiste Zeit nicht einmal meinen Swipe. Gibt es eine bessere Lösung?
– Gofilord
30. Januar 15 um 19:39 Uhr
Hier ist ein Ausschnitt, den ich zum Erkennen von Swipes verwende. Dann könntest du a verwenden Flipper um die Ansicht zu ändern.
@Override
public boolean onTouchEvent(MotionEvent event) {
if (gestureDetector.onTouchEvent(event)) {
return true;
} else {
return false;
}
}
private static final int SWIPE_MIN_DISTANCE = 30;
private static final int SWIPE_MAX_OFF_PATH = 250;
private static final int SWIPE_THRESHOLD_VELOCITY = 200;
class MyGestureDetector extends SimpleOnGestureListener {
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
try {
if (Math.abs(e1.getY() - e2.getY()) > SWIPE_MAX_OFF_PATH)
return false;
// right to left swipe
if (e1.getX() - e2.getX() > SWIPE_MIN_DISTANCE
&& Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
leftFling();
} else if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE
&& Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
rightFling();
}
} catch (Exception e) {
// nothing
}
return false;
}
}
-
Habe eher nach einem Prrof-Beispiel gesucht. Ich habe Viewflipper ausprobiert, aber immer etwas Seltsames mit der Listengröße, wenn Sie das tun. Ich mag deinen Code, obwohl er ziemlich sauber ist. Ich werde es in meinen zukünftigen Versuchen verwenden müssen, danke
– JPM
5. Mai 11 um 5:45 Uhr
SoliQuiD
Hier ist eine sehr vereinfachte Version, bei der die beiden Listener (onTouch für die Swipe-Erkennung und onClickIem für die Elementklickerkennung) verwendet werden, die das isSwipe-Flag verwenden, um den onClickItemListener zu stoppen, bis bestätigt wird, dass es kein Swipe war
Erkennen des Klicks
unter Berücksichtigung, dass es sich nicht um einen ersten Wisch handelt
listView.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3)
{
if(!isSwipe)
{
adapter.increase(arg2);
adapter.notifyDataSetChanged();
}
}
});
Swipe erkennen
listView.setOnTouchListener(new OnTouchListener() {
private int action_down_x = 0;
private int action_up_x = 0;
private int difference = 0;
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
action_down_x = (int) event.getX();
isSwipe=false; //until now
break;
case MotionEvent.ACTION_MOVE:
if(!isSwipe)
{
action_up_x = (int) event.getX();
difference = action_down_x - action_up_x;
if(Math.abs(difference)>50)
{
Log.d("action","action down x: "+action_down_x);
Log.d("action","action up x: "+action_up_x);
Log.d("action","difference: "+difference);
//swipe left or right
if(difference>0){
//swipe left
Log.d("action","swipe left");
adapter.decrease(selectedItem);
adapter.notifyDataSetChanged();
}
else{
//swipe right
Log.d("action","swipe right");
}
isSwipe=true;
}
}
break;
case MotionEvent.ACTION_UP:
Log.d("action", "ACTION_UP - ");
action_down_x = 0;
action_up_x = 0;
difference = 0;
break;
}
return false; //to allow the clicklistener to work after
}
})
Wenn Sie einige Schaltflächen mit Aktionen anzeigen möchten, wenn ein Listenelement gewischt wird, gibt es viele Bibliotheken im Internet, die dieses Verhalten haben. Ich habe die im Internet gefundene Bibliothek implementiert und bin sehr zufrieden. Es ist sehr einfach zu bedienen und sehr schnell. Ich habe die ursprüngliche Bibliothek verbessert und einen neuen Klick-Listener für Elementklicks hinzugefügt. Außerdem habe ich eine großartige Bibliothek für Schriftarten hinzugefügt (http://fortawesome.github.io/Font-Awesome/) und jetzt können Sie einfach einen neuen Elementtitel hinzufügen und den Symbolnamen von font awesome angeben.
Hier ist der Github-Link
.
Ich verwende bereits das Kontextmenü, um die Schriftgröße zu ändern und für ein langes Drücken für andere Aktivitäten. Ich möchte, dass der Benutzer von links nach rechts wischen kann, um den vollständigen Datenbildschirm für die Zeile zu öffnen, in der er gewischt hat.
– JPM
7. Dezember 10 um 22:32 Uhr
Ich denke, Fragmente lösen dieses Problem jetzt.
– JPM
20. April 13 um 20:28 Uhr