Jak wykryć przesunięcie w lewo lub w prawo w systemie Android?


93

Mam EditTextwidok w Androidzie. Na tym chcę wykryć przesunięcie w lewo lub w prawo. Jestem w stanie uzyskać to na pustym miejscu, używając poniższego kodu. Ale to nie działa, gdy przesuwam palcem po EditText. Jak mogę to zrobić? Daj mi znać, jeśli robię coś źle. Dziękuję Ci.

Używany kod:

switch (touchevent.getAction())
{
    case MotionEvent.ACTION_DOWN:
    {
        oldTouchValue = touchevent.getX();
        break;
    }
    case MotionEvent.ACTION_UP:
    {
        float currentX = touchevent.getX();
        if (oldTouchValue < currentX)
        {
            // swiped left
        }
        if (oldTouchValue > currentX )
        {
            swiped right
        }
    break;
    }
}

Pomocny samouczek dotyczący tego wymagania techrepublic.com/blog/software-engineer/ ...
amitabha2715

Odpowiedzi:


111

Najprostszy detektor ruchu od lewej do prawej:

W swojej klasie aktywności dodaj następujące atrybuty:

private float x1,x2;
static final int MIN_DISTANCE = 150;

i zastąp onTouchEvent()metodę:

@Override
public boolean onTouchEvent(MotionEvent event)
{     
    switch(event.getAction())
    {
      case MotionEvent.ACTION_DOWN:
          x1 = event.getX();                          
      break;          
      case MotionEvent.ACTION_UP:
          x2 = event.getX();
          float deltaX = x2 - x1;
          if (Math.abs(deltaX) > MIN_DISTANCE)
          {
              Toast.makeText(this, "left2right swipe", Toast.LENGTH_SHORT).show ();
          }
          else
          {
              // consider as something else - a screen tap for example
          }                       
      break;    
    }            
    return super.onTouchEvent(event);        
}

dzięki, to działa, ale czy możesz mi powiedzieć, jak to działa, jeśli jest scrollView?
LS_

Ponieważ getAction()zwraca mieszane dane zarówno typu akcji, jak i indeksu wskaźnika, nie byłoby lepiej użyć getActionMasked(), które zwraca tylko typ akcji?
lartkma

To rozwiązanie jest przestarzałe. Teraz możesz użyć gestu onFling.
Donato

59

Podoba mi się kod z @ user2999943. Ale tylko drobne zmiany do moich własnych celów.

@Override
public boolean onTouchEvent(MotionEvent event)
{     
    switch(event.getAction())
    {
      case MotionEvent.ACTION_DOWN:
          x1 = event.getX();                         
      break;         
      case MotionEvent.ACTION_UP:
          x2 = event.getX();
          float deltaX = x2 - x1;

          if (Math.abs(deltaX) > MIN_DISTANCE)
          {
              // Left to Right swipe action
              if (x2 > x1)
              {
                  Toast.makeText(this, "Left to Right swipe [Next]", Toast.LENGTH_SHORT).show ();                     
              }

              // Right to left swipe action               
              else 
              {
                  Toast.makeText(this, "Right to Left swipe [Previous]", Toast.LENGTH_SHORT).show ();                    
              }

          }
          else
          {
              // consider as something else - a screen tap for example
          }                          
      break;   
    }           
    return super.onTouchEvent(event);       
}

1
Hej, wygląda na to, że gdy ten kod znajduje się w działaniu ze ScrollView, to nie działa. Każdy pomysł, dlaczego? Świetny kod inaczej
Jona

Jona, ten sam widok musi być w stanie odebrać zdarzenia ACTION_DOWN i ACTION_UP, aby to zadziałało.
Al Wang

@AlWang co masz na myśli?
JK

Wygląda na to, że w przypadku Jony ScrollView przechwytuje MotionEvent. Powinieneś spojrzeć na stackoverflow.com/questions/12884250/…, aby znaleźć implementację.
Al Wang

czy możesz mi powiedzieć, jak wykryć również przesunięcie w górę iw dół
Maulik

33

To jest urocza klasa, której używam (w przypadkach, gdy chcę złapać zdarzenie w widoku, jeśli jest to ViewGroup, używam drugiej implementacji):

import android.util.Log;
import android.view.MotionEvent;
import android.view.View;

public class SwipeDetector implements View.OnTouchListener{

    private int min_distance = 100;
    private float downX, downY, upX, upY;
    private View v;

    private onSwipeEvent swipeEventListener;



    public SwipeDetector(View v){
        this.v=v;
        v.setOnTouchListener(this);
    }

    public void setOnSwipeListener(onSwipeEvent listener)
    {
        try{
            swipeEventListener=listener;
        }
        catch(ClassCastException e)
        {
            Log.e("ClassCastException","please pass SwipeDetector.onSwipeEvent Interface instance",e);
        }
    }


    public void onRightToLeftSwipe(){
        if(swipeEventListener!=null)
            swipeEventListener.SwipeEventDetected(v,SwipeTypeEnum.RIGHT_TO_LEFT);
        else
            Log.e("SwipeDetector error","please pass SwipeDetector.onSwipeEvent Interface instance");
    }

    public void onLeftToRightSwipe(){
        if(swipeEventListener!=null)
            swipeEventListener.SwipeEventDetected(v,SwipeTypeEnum.LEFT_TO_RIGHT);
        else
            Log.e("SwipeDetector error","please pass SwipeDetector.onSwipeEvent Interface instance");
    }

    public void onTopToBottomSwipe(){
        if(swipeEventListener!=null)
            swipeEventListener.SwipeEventDetected(v,SwipeTypeEnum.TOP_TO_BOTTOM);
        else
            Log.e("SwipeDetector error","please pass SwipeDetector.onSwipeEvent Interface instance");
    }

    public void onBottomToTopSwipe(){
        if(swipeEventListener!=null)
            swipeEventListener.SwipeEventDetected(v,SwipeTypeEnum.BOTTOM_TO_TOP);
        else
            Log.e("SwipeDetector error","please pass SwipeDetector.onSwipeEvent Interface instance");
    }

    public boolean onTouch(View v, MotionEvent event) {
        switch(event.getAction()){
        case MotionEvent.ACTION_DOWN: {
            downX = event.getX();
            downY = event.getY();
            return true;
        }
        case MotionEvent.ACTION_UP: {
            upX = event.getX();
            upY = event.getY();

            float deltaX = downX - upX;
            float deltaY = downY - upY;

            //HORIZONTAL SCROLL
            if(Math.abs(deltaX) > Math.abs(deltaY))
            {
                if(Math.abs(deltaX) > min_distance){
                    // left or right
                    if(deltaX < 0) 
                    {
                        this.onLeftToRightSwipe();
                        return true;
                    }
                    if(deltaX > 0) {
                        this.onRightToLeftSwipe();
                        return true; 
                    }
                }
                else {
                    //not long enough swipe...
                    return false; 
                }
            }
            //VERTICAL SCROLL
            else 
            {
                if(Math.abs(deltaY) > min_distance){
                    // top or down
                    if(deltaY < 0) 
                    { this.onTopToBottomSwipe();
                    return true; 
                    }
                    if(deltaY > 0)
                    { this.onBottomToTopSwipe(); 
                    return true;
                    }
                }
                else {
                    //not long enough swipe...
                    return false;
                }
            }

            return true;
        }
        }
        return false;
    }
    public interface onSwipeEvent
    {
        public void SwipeEventDetected(View v, SwipeTypeEnum SwipeType);
    }

    public SwipeDetector setMinDistanceInPixels(int min_distance)
{
    this.min_distance=min_distance;
    return this;
}

    public enum SwipeTypeEnum
    {
        RIGHT_TO_LEFT,LEFT_TO_RIGHT,TOP_TO_BOTTOM,BOTTOM_TO_TOP
    }

}

a to jest przykład użycia:

filters_container=(RelativeLayout)root.findViewById(R.id.filters_container);
    new SwipeDetector(filters_container).setOnSwipeListener(new SwipeDetector.onSwipeEvent() {
        @Override
        public void SwipeEventDetected(View v, SwipeDetector.SwipeTypeEnum swipeType) {
            if(swipeType==SwipeDetector.SwipeTypeEnum.LEFT_TO_RIGHT)
                getActivity().onBackPressed();
        }
    });

W niektórych przypadkach chcesz wykryć gesty machnięcia na kontenerze i przekazać zdarzenia dotykowe do elementów podrzędnych, więc w takim przypadku możesz utworzyć grupę Widok niestandardowy, powiedzmy RelativeLayout i nadpisać onInterceptTouchEvent, a tam możesz wykryć zdarzenie przesunięcia bez blokowania przejścia zdarzenia dotykowego do widoków podrzędnych, na przykład:

    import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.RelativeLayout;


public class SwipeDetectRelativeLayout extends RelativeLayout {


    private float x1,x2;
    static final int MIN_DISTANCE=150;
    private onSwipeEventDetected mSwipeDetectedListener;


    public SwipeDetectRelativeLayout(Context context) {
        super(context);
    }

    public SwipeDetectRelativeLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public SwipeDetectRelativeLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {

        switch(ev.getAction())
        {
            case MotionEvent.ACTION_DOWN:
                x1 = ev.getX();
                break;
            case MotionEvent.ACTION_UP:
                x2 = ev.getX();
                float deltaX = x2 - x1;
                if (Math.abs(deltaX) > MIN_DISTANCE)
                {
                        //swiping right to left
                        if(deltaX<0)
                        {
                            if(mSwipeDetectedListener!=null)
                                mSwipeDetectedListener.swipeEventDetected();
                        }
                }
                break;
        }
        return super.onInterceptTouchEvent(ev);
    }

    public interface onSwipeEventDetected
    {
        public void swipeEventDetected();
    }

    public void registerToSwipeEvents(onSwipeEventDetected listener)
    {
        this.mSwipeDetectedListener=listener;
    }
}

doskonała implementacja, użyłem pierwszej opcji, a także dodałem obsługę onTouch, więc mam omówienie następnych poprzednich i onTouch, dzięki!
ziniestro,

@Gal Rom Jak korzystać z drugiej metody?
smoothdvd

Doskonała odpowiedź! Zdecydowanie działa przy niewielkim wysiłku i bardzo skutecznie.
xarlymg89

Niesamowita realizacja.
Tugrul

9

Zdarzenia typu Swipe to rodzaj onTouchwydarzeń. Po prostu upraszczając odpowiedź @Gal Rom, po prostu śledź pionowe i poziome delty, a dzięki odrobinie matematyki możesz określić, jakim rodzajem przesunięcia był touchEvent. (Ponownie podkreślę, że było to OSTATECZNIE oparte na poprzedniej odpowiedzi, ale prostota może spodobać się nowicjuszom). Chodzi o to, aby rozszerzyć OnTouchListener, wykryć, jakiego rodzaju przesunięcie (dotyk) właśnie się wydarzyło i wywołać określone metody dla każdego rodzaju.

public class SwipeListener implements View.OnTouchListener {
    private int min_distance = 100;
    private float downX, downY, upX, upY;
    View v;

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        this.v = v;
        switch(event.getAction()) { // Check vertical and horizontal touches
            case MotionEvent.ACTION_DOWN: {
                downX = event.getX();
                downY = event.getY();
                return true;
            }
            case MotionEvent.ACTION_UP: {
                upX = event.getX();
                upY = event.getY();

                float deltaX = downX - upX;
                float deltaY = downY - upY;

                //HORIZONTAL SCROLL
                if (Math.abs(deltaX) > Math.abs(deltaY)) {
                    if (Math.abs(deltaX) > min_distance) {
                        // left or right
                        if (deltaX < 0) {
                            this.onLeftToRightSwipe();
                            return true;
                        }
                        if (deltaX > 0) {
                            this.onRightToLeftSwipe();
                            return true;
                        }
                    } else {
                        //not long enough swipe...
                        return false;
                    }
                }
                //VERTICAL SCROLL
                else {
                    if (Math.abs(deltaY) > min_distance) {
                        // top or down
                        if (deltaY < 0) {
                            this.onTopToBottomSwipe();
                            return true;
                        }
                        if (deltaY > 0) {
                            this.onBottomToTopSwipe();
                            return true;
                        }
                    } else {
                        //not long enough swipe...
                        return false;
                    }
                }
                return false;
            }
        }
        return false;
    }

    public void onLeftToRightSwipe(){
        Toast.makeText(v.getContext(),"left to right",   
                                      Toast.LENGTH_SHORT).show();
    }

    public void onRightToLeftSwipe() {
        Toast.makeText(v.getContext(),"right to left",
                                     Toast.LENGTH_SHORT).show();
    }

    public void onTopToBottomSwipe() {
        Toast.makeText(v.getContext(),"top to bottom", 
                                     Toast.LENGTH_SHORT).show();
    }

    public void onBottomToTopSwipe() {
        Toast.makeText(v.getContext(),"bottom to top", 
                                    Toast.LENGTH_SHORT).show();
    }
}

3

Napisałem prostą klasę, która ułatwia wykrywanie zdarzeń przesuwania - TOP, RIGHT, BOTTOM, LEFT.

1: Wykryj pojedyncze zdarzenie przesunięcia

// Detect and consume specific events
// {Available methods} - detectTop, detectRight, detectBottom, detectLeft
SwipeEvents.detectTop(swipeElement, new SwipeEvents.SwipeSingleCallback() {
    @Override
    public void onSwipe() {
        showToast("Swiped - detectTop");
    }
});

2: Wykryj dowolne zdarzenia przesunięcia za pomocą jednego wywołania zwrotnego.

SwipeEvents.detect( swipeElement, new SwipeEvents.SwipeCallback() {
    @Override
    public void onSwipeTop() {
        //Swiped top
    }

    @Override
    public void onSwipeRight() {
        //Swiped right
    }

    @Override
    public void onSwipeBottom() {
        //Swiped bottom
    }

    @Override
    public void onSwipeLeft() {
        //Swiped left
    }
});

Oto post na blogu z wyjaśnieniem, jak używać: http://bmutinda.com/android-detect-swipe-events/

Stworzyłem również Gist dla fragmentów kodu dostępnych tutaj: https://gist.github.com/bmutinda/9578f70f1df9bd0687b8

Dzięki.


3

Detektor ruchu od lewej do prawej i od prawej do lewej

Najpierw zadeklaruj dwie zmienne typu float.

private float x1, x2;

Po drugie, połącz widok XML w java. Tak jak jaImageView

ImageView img = (ImageView) findViewById(R.id.imageView);

Po trzecie, setOnTouchListenerna twoim ImageView.

img.setOnTouchListener(
                    new View.OnTouchListener() {
                    @Override
                    public boolean onTouch(View v, MotionEvent event) {
                        // TODO Auto-generated method stub
                        switch (event.getAction()) {
                        case MotionEvent.ACTION_DOWN:
                            x1 = event.getX();
                            break;
                        case MotionEvent.ACTION_UP:
                            x2 = event.getX();
                            float deltaX = x2 - x1;
                            if (deltaX < 0) {
                                Toast.makeText(MainActivity.this,
                                        "Right to Left swipe",
                                        Toast.LENGTH_SHORT).show();
                            }else if(deltaX >0){
                                Toast.makeText(MainActivity.this,
                                        "Left to Right swipe",
                                        Toast.LENGTH_SHORT).show();
                            }
                            break;
                        }

                        return false;
                    }
                });

3

Chcę dodać do zaakceptowanej odpowiedzi, która działa częściowo, ale brakuje zmiennej czasu, co czyni ją doskonałą.

Najprostszy detektor przesuwania od lewej do prawej ze zmienną czasową:

W swojej klasie aktywności dodaj następujące atrybuty:

private float x1,x2;
private long startClickTime;
static final int MIN_DISTANCE = 150;
static final int MAX_SWIPE_TIME = 200;

i nadpisz metodę onTouchEvent ():

    @Override
    public boolean onTouchEvent(MotionEvent event)
    {
        switch(event.getAction())
        {
            case MotionEvent.ACTION_DOWN:
                startClickTime = Calendar.getInstance().getTimeInMillis();
                x1 = event.getX();
                break;
            case MotionEvent.ACTION_UP:
                long clickDuration = Calendar.getInstance().getTimeInMillis() - startClickTime;
                x2 = event.getX();
                float deltaX = x2 - x1;
                if (Math.abs(deltaX) > MIN_DISTANCE && clickDuration < MAX_SWIPE_TIME)
                {
                    Toast.makeText(this, "left2right swipe", Toast.LENGTH_SHORT).show ();
                }
                else
                {
                    // consider as something else - a screen tap for example
                }
                break;
        }
        return super.onTouchEvent(event);
    }

3

Myślę, że to, czego chcesz, nazywa się romansem. MotionEvents można wykorzystać do określenia kierunku wyrzutu.

public class MainActivity extends Activity implements  GestureDetector.OnGestureListener {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.stellar_layout);
        mDetector = new GestureDetectorCompat(this, this);
    }

    @Override
    public boolean onFling(MotionEvent event1, MotionEvent event2,
                           float velocityX, float velocityY) {
        Log.d(tag, "onFling:\n " + event1.toString()+ "\n " + event2.toString());
        /* prints the following
            MotionEvent { action=ACTION_DOWN, id[0]=0, x[0]=297.0, y[0]=672.0, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=488341979, downTime=488341979, deviceId=6, source=0x1002 }
            MotionEvent { action=ACTION_UP, id[0]=0, x[0]=560.0, y[0]=583.0, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=488342047, downTime=488341979, deviceId=6, source=0x1002 }
        */
        return true;
    }

}

http://developer.android.com/training/gestures/detector.html


2

Wykryj przesunięcie w czterech kierunkach

private float x1,x2,y1,y2;
static final int MIN_DISTANCE = 70;

i

switch(pSceneTouchEvent.getAction())
     {
       case MotionEvent.ACTION_DOWN:
           x1 = pSceneTouchEvent.getX();     
           y1 = pSceneTouchEvent.getY();
       break;         
       case MotionEvent.ACTION_UP:
           x2 = pSceneTouchEvent.getX();
           y2 = pSceneTouchEvent.getY();
           float deltaX = x2 - x1;
           float deltaY = y2 - y1;
           if (deltaX > MIN_DISTANCE)
           {
               swipeLeftToRight();
           }
           else if( Math.abs(deltaX) > MIN_DISTANCE)
           {
               swipeRightToLeft();
           } 
           else if(deltaY > MIN_DISTANCE){
               swipeTopToBottom();
           } 
           else if( Math.abs(deltaY) > MIN_DISTANCE){
               swipeBottopmToTop();
           }

       break;   
     }          

2

Po całym dniu pracy nad tą funkcją w końcu udało się uzyskać właściwą odpowiedź.

Najpierw utwórz następujące klasy:

import android.util.Log;
import android.view.MotionEvent;
import android.view.View;

/**
 * Created by hoshyar on 1/19/17.
 */

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 = "Swipe";
    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;

            case MotionEvent.ACTION_MOVE:
                upX = event.getX();
                upY = event.getY();

                float deltaX = downX - upX;
                float deltaY = downY - upY;
                Log.i(logTag,String.valueOf(deltaX));
                Log.i(logTag,String.valueOf(deltaX));

                if (deltaY>0 && deltaY<10 && deltaX<0 || deltaY==0 && deltaX>-15 && deltaX<0){
                    Log.i(logTag,"to right");
                }if (deltaY>=0 && deltaY<10 && deltaX>0 || deltaY<0 && deltaX>15 && deltaX<40){
                Log.i(logTag,"to left");
            }





                if (Math.abs(deltaX) > MIN_DISTANCE) {
                    // left or right
                    if (deltaX < 0) {
                        mSwipeDetected = Action.LR;
                        return false;
                    }
                    if (deltaX > 0) {


                        mSwipeDetected = Action.RL;
                        return false;
                    }
                } else if (Math.abs(deltaY) > MIN_DISTANCE) {


                    if (deltaY < 0) {
                        Log.i(logTag,"to bottom");
                        mSwipeDetected = Action.TB;
                        return false;
                    }
                    if (deltaY > 0) {
                        Log.i(logTag,"to up");
                        mSwipeDetected = Action.BT;
                        return false;
                    }
                }
                return true;
        }
        return false;
    }
}

Wreszcie na przedmiocie, który chcesz zastosować. Mój przykład:

SwipeDetector swipeDetector = new SwipeDetector();
listView.setOnTouchListener(swipeDetector);

Powodzenia .


ale jak zwrócić wydarzenie klasie?
Vivek

1

Jeśli chcesz złapać zdarzenie od początku machnięcia, możesz użyć MotionEvent.ACTION_MOVE i zapisać pierwszą wartość do porównania

private float upX1;
private float upX2;
private float upY1;
private float upY2;
private boolean isTouchCaptured = false;
static final int min_distance = 100;


        viewObject.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                switch (event.getAction()) {
                    case MotionEvent.ACTION_MOVE: {
                        downX = event.getX();
                        downY = event.getY();

                        if (!isTouchCaptured) {
                            upX1 = event.getX();
                            upY1 = event.getY();
                            isTouchCaptured = true;
                        } else {
                            upX2 = event.getX();
                            upY2 = event.getY();

                            float deltaX = upX1 - upX2;
                            float deltaY = upY1 - upY2;
                            //HORIZONTAL SCROLL
                            if (Math.abs(deltaX) > Math.abs(deltaY)) {
                                if (Math.abs(deltaX) > min_distance) {
                                    // left or right
                                    if (deltaX < 0) {

                                        return true;
                                    }
                                    if (deltaX > 0) {
                                        return true;
                                    }
                                } else {
                                    //not long enough swipe...
                                    return false;
                                }
                            }
                            //VERTICAL SCROLL
                            else {
                                if (Math.abs(deltaY) > min_distance) {
                                    // top or down
                                    if (deltaY < 0) {

                                        return false;
                                    }
                                    if (deltaY > 0) {

                                        return false;
                                    }
                                } else {
                                    //not long enough swipe...
                                    return false;
                                }
                            }
                        }
                        return false;
                    }
                    case MotionEvent.ACTION_UP: {
                        isTouchCaptured = false;
                    }
                }
                return false;

            }
        });

powiedzmy, że mam Toast jak Toast.makeText(MainAcivity.this, "top to down" + increaseValue, Toast.LENGTH_SHORT).show();ona, jak zrobić jedno przesunięcie, aby dodać wartości min = 0 i max = 10.
sanoj lawrence

1

to może ci pomóc ...

private final GestureDetector.SimpleOnGestureListener onGestureListener = new GestureDetector.SimpleOnGestureListener() {
    @Override
    public boolean onDoubleTap(MotionEvent e) {
        Log.i("gestureDebug333", "doubleTapped:" + e);
        return super.onDoubleTap(e);
    }

    @Override
    public boolean onDoubleTapEvent(MotionEvent e) {
        Log.i("gestureDebug333", "doubleTappedEvent:" + e);

        return super.onDoubleTapEvent(e);
    }

    @Override
    public boolean onDown(MotionEvent e) {
        Log.i("gestureDebug333", "onDown:" + e);


        return super.onDown(e);

    }

    @Override
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {


        Log.i("gestureDebug333", "flinged:" + e1 + "---" + e2);
        Log.i("gestureDebug333", "fling velocity:" + velocityX + "---" + velocityY);
        if (e1.getAction() == MotionEvent.ACTION_DOWN && e1.getX() > (e2.getX() + 300)){
           // Toast.makeText(context, "flinged right to left", Toast.LENGTH_SHORT).show();
            goForward();
        }
        if (e1.getAction() == MotionEvent.ACTION_DOWN && e2.getX() > (e1.getX() + 300)){
            //Toast.makeText(context, "flinged left to right", Toast.LENGTH_SHORT).show();
            goBack();
        }
        return super.onFling(e1, e2, velocityX, velocityY);
    }

    @Override
    public void onLongPress(MotionEvent e) {
        super.onLongPress(e);
    }

    @Override
    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
        return super.onScroll(e1, e2, distanceX, distanceY);
    }

    @Override
    public void onShowPress(MotionEvent e) {
        super.onShowPress(e);
    }

    @Override
    public boolean onSingleTapConfirmed(MotionEvent e) {
        return super.onSingleTapConfirmed(e);
    }

    @Override
    public boolean onSingleTapUp(MotionEvent e) {
        return super.onSingleTapUp(e);
    }
};

1

Krótka i łatwa wersja:

1. Najpierw utwórz tę klasę abstrakcyjną

public abstract class HorizontalSwipeListener implements View.OnTouchListener {

    private float firstX;
    private int minDistance;

    HorizontalSwipeListener(int minDistance) {
        this.minDistance = minDistance;
    }

    abstract void onSwipeRight();

    abstract void onSwipeLeft();

    @Override
    public boolean onTouch(View view, MotionEvent event) {

        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                firstX = event.getX();
                return true;
            case MotionEvent.ACTION_UP:
                float secondX = event.getX();
                if (Math.abs(secondX - firstX) > minDistance) {
                    if (secondX > firstX) {
                        onSwipeLeft();
                    } else {
                        onSwipeRight();
                    }
                }
                return true;
        }
        return view.performClick();
    }

}

2.Następnie utwórz konkretną klasę implementującą to, czego potrzebujesz:

public class SwipeListener extends HorizontalSwipeListener {

    public SwipeListener() {
        super(200);
    }

    @Override
    void onSwipeRight() {
        System.out.println("right");
    }

    @Override
    void onSwipeLeft() {
        System.out.println("left");
    }

}

1

tutaj jest ogólny detektor przesunięcia w lewo dla dowolnego widoku w kotlinie przy użyciu wiązania danych

@BindingAdapter("onSwipeLeft")
fun View.setOnSwipeLeft(runnable: Runnable) {
    setOnTouchListener(object : View.OnTouchListener {
        var x0 = 0F; var y0 = 0F; var t0 = 0L
        val defaultClickDuration = 200

        override fun onTouch(v: View?, motionEvent: MotionEvent?): Boolean {
            motionEvent?.let { event ->
                when(event.action) {
                    MotionEvent.ACTION_DOWN -> {
                        x0 = event.x; y0 = event.y; t0 = System.currentTimeMillis()
                    }
                    MotionEvent.ACTION_UP -> {
                        val x1 = event.x; val y1 = event.y; val t1 = System.currentTimeMillis()

                        if (x0 == x1 && y0 == y1 && (t1 - t0) < defaultClickDuration) {
                            performClick()
                            return false
                        }
                        if (x0 > x1) { runnable.run() }
                    }
                    else -> {}
                }
            }
            return true
        }
    })
}

a następnie użyć go w swoim układzie:

app:onSwipeLeft="@{() -> viewModel.swipeLeftHandler()}"

0
public class TransferMarket extends Activity {

    float x1,x2;
    float y1, y2;

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_transfer_market);
    }

    // onTouchEvent () method gets called when User performs any touch event on screen

    // Method to handle touch event like left to right swap and right to left swap

    public boolean onTouchEvent(MotionEvent touchevent)
    {
        switch (touchevent.getAction())
        {
            // when user first touches the screen we get x and y coordinate
            case MotionEvent.ACTION_DOWN:
            {
                x1 = touchevent.getX();
                y1 = touchevent.getY();
                break;
            }
            case MotionEvent.ACTION_UP:
            {
                x2 = touchevent.getX();
                y2 = touchevent.getY();

                //if left to right sweep event on screen
                if (x1 < x2)
                {
                    Toast.makeText(this, "Left to Right Swap Performed", Toast.LENGTH_LONG).show();
                }

                // if right to left sweep event on screen
                if (x1 > x2)
                {
                    Toast.makeText(this, "Right to Left Swap Performed", Toast.LENGTH_LONG).show();
                }

                // if UP to Down sweep event on screen
                if (y1 < y2)
                {
                    Toast.makeText(this, "UP to Down Swap Performed", Toast.LENGTH_LONG).show();
                }

                //if Down to UP sweep event on screen
                if (y1 > y2)
                {
                    Toast.makeText(this, "Down to UP Swap Performed", Toast.LENGTH_LONG).show();
                }
                break;
            }
        }
        return false;
    }

Użyj tylko współrzędnych x, które są wystarczające dla lewej do prawej i odwrotnie
Abhishek

0

najlepszą odpowiedzią jest @Gal Rom's. więcej informacji na ten temat: zdarzenie dotykowe wraca najpierw do widoków potomnych. a jeśli zdefiniujesz dla nich odbiornik onClick lub onTouch, widok parnt (na przykład fragment) nie otrzyma żadnego nasłuchującego dotyku. Więc jeśli chcesz zdefiniować odbiornik przesuwu dla fragmentu w tej sytuacji, musisz zaimplementować go w nowej klasie:

    package com.neganet.QRelations.fragments;

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.FrameLayout;

public class SwipeListenerFragment extends FrameLayout {
    private float x1,x2;
    static final int MIN_DISTANCE=150;
    private onSwipeEventDetected mSwipeDetectedListener;


    public SwipeListenerFragment(Context context) {
        super(context);
    }

    public SwipeListenerFragment(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public SwipeListenerFragment(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        boolean result=false;
        switch(ev.getAction())
        {
            case MotionEvent.ACTION_DOWN:
                x1 = ev.getX();
                break;
            case MotionEvent.ACTION_UP:
                x2 = ev.getX();
                float deltaX = x2 - x1;
                if (Math.abs(deltaX) > MIN_DISTANCE)
                {
                    if(deltaX<0)
                    {
                        result=true;
                        if(mSwipeDetectedListener!=null)
                            mSwipeDetectedListener.swipeLeftDetected();

                    }else if(deltaX>0){
                        result=true;
                        if(mSwipeDetectedListener!=null)
                            mSwipeDetectedListener.swipeRightDetected();
                    }
                }
                break;
        }
        return result;
    }

    public interface onSwipeEventDetected
    {
        public void swipeLeftDetected();
        public void swipeRightDetected();

    }

    public void registerToSwipeEvents(onSwipeEventDetected listener)
    {
        this.mSwipeDetectedListener=listener;
    }
}

Zmieniłem klasę @Gal Rom. Dzięki temu może wykryć przesunięcie w prawo i w lewo, a szczególnie zwraca wartość onInterceptTouchEvent true po wykryciu. jest to ważne, ponieważ jeśli nie zrobimy tego czasami, widoki potomne mogą otrzymać zdarzenie, a zarówno Swipe dla fragmentu, jak i onClick dla widoku potomnego (na przykład) działają i powodują pewne problemy. po utworzeniu tej klasy musisz zmienić plik xml fragmentu:

    <com.neganet.QRelations.fragments.SwipeListenerFragment xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
    android:id="@+id/main_list_layout"
    android:clickable="true"
    android:focusable="true"
    android:focusableInTouchMode="true"
    android:layout_height="match_parent" tools:context="com.neganet.QRelations.fragments.mainList"
    android:background="@color/main_frag_back">

    <!-- TODO: Update blank fragment layout -->
    <android.support.v7.widget.RecyclerView
        android:id="@+id/farazList"
        android:scrollbars="horizontal"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="left|center_vertical" />
</com.neganet.QRelations.fragments.SwipeListenerFragment>

widzisz, że tag początkowy to klasa, którą stworzyliśmy. teraz w klasie fragmentów:

            View view=inflater.inflate(R.layout.fragment_main_list, container, false);
        SwipeListenerFragment tdView=(SwipeListenerFragment) view;
        tdView.registerToSwipeEvents(this);


and then Implement SwipeListenerFragment.onSwipeEventDetected in it:

        @Override
    public void swipeLeftDetected() {
        Toast.makeText(getActivity(), "left", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void swipeRightDetected() {
        Toast.makeText(getActivity(), "right", Toast.LENGTH_SHORT).show();
    }

To trochę skomplikowane, ale działa idealnie :)


0

Należy rozszerzyć klasę zi View.OnTouchListenerobsłużyć onTouchmetodę, zastępując ją.

interface SwipeListener {
    fun onSwipeLeft()
    fun onSwipeRight()
}

class SwipeGestureListener internal constructor(
    private val listener: SwipeListener,
    private val minDistance: Int = DEFAULT_SWIPE_MIN_DISTANCE
) : View.OnTouchListener {
    companion object {
        const val DEFAULT_SWIPE_MIN_DISTANCE = 200
    }

    private var anchorX = 0F

    override fun onTouch(view: View, event: MotionEvent): Boolean {
        when (event.action) {
            MotionEvent.ACTION_DOWN -> {
                anchorX = event.x
                return true
            }
            MotionEvent.ACTION_UP -> {
                if (abs(event.x - anchorX) > minDistance) {
                    if (event.x > anchorX) {
                        listener.onSwipeRight()
                    } else {
                        listener.onSwipeLeft()
                    }
                }
                return true
            }
        }
        return view.performClick()
    }
}

Możesz po prostu łatwo zaimplementować to w ten sposób w swoim Activitylub Fragment.

class MainActivity : AppCompatActivity(), SwipeListener {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        viewGroup.setOnTouchListener(SwipeGestureListener(this))
    }

    override fun onSwipeLeft() {
        Toast.makeText(this, "Swipe Left", Toast.LENGTH_SHORT).show()
    }

    override fun onSwipeRight() {
        Toast.makeText(this, "Swipe Right", Toast.LENGTH_SHORT).show()
    }
}
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.