programing

오른쪽에서 왼쪽으로 스와이프 제스처를 처리하는 방법

kingscode 2023. 6. 10. 16:18
반응형

Android:오른쪽에서 왼쪽으로 스와이프 제스처를 처리하는 방법

나는 사용자가 전화 화면에서 오른쪽에서 왼쪽으로 스와이프할 때 내 앱이 인식하기를 원합니다.

어떻게 하는 거지?

SwipeTouchListener.java에서:

import android.content.Context;
import android.view.GestureDetector;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;

public class OnSwipeTouchListener implements OnTouchListener {

    private final GestureDetector gestureDetector;

    public OnSwipeTouchListener (Context ctx){
        gestureDetector = new GestureDetector(ctx, new GestureListener());
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        return gestureDetector.onTouchEvent(event);
    }

    private final class GestureListener extends SimpleOnGestureListener {

        private static final int SWIPE_THRESHOLD = 100;
        private static final int SWIPE_VELOCITY_THRESHOLD = 100;

        @Override
        public boolean onDown(MotionEvent e) {
            return true;
        }

        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
            boolean result = false;
            try {
                float diffY = e2.getY() - e1.getY();
                float diffX = e2.getX() - e1.getX();
                if (Math.abs(diffX) > Math.abs(diffY)) {
                    if (Math.abs(diffX) > SWIPE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
                        if (diffX > 0) {
                            onSwipeRight();
                        } else {
                            onSwipeLeft();
                        }
                        result = true;
                    }
                }
                else if (Math.abs(diffY) > SWIPE_THRESHOLD && Math.abs(velocityY) > SWIPE_VELOCITY_THRESHOLD) {
                    if (diffY > 0) {
                        onSwipeBottom();
                    } else {
                        onSwipeTop();
                    }
                    result = true;
                }
            } catch (Exception exception) {
                exception.printStackTrace();
            }
            return result;
        }
    }

    public void onSwipeRight() {
    }

    public void onSwipeLeft() {
    }

    public void onSwipeTop() {
    }

    public void onSwipeBottom() {
    }
}

용도:

imageView.setOnTouchListener(new OnSwipeTouchListener(MyActivity.this) {
    public void onSwipeTop() {
        Toast.makeText(MyActivity.this, "top", Toast.LENGTH_SHORT).show();
    }
    public void onSwipeRight() {
        Toast.makeText(MyActivity.this, "right", Toast.LENGTH_SHORT).show();
    }
    public void onSwipeLeft() {
        Toast.makeText(MyActivity.this, "left", Toast.LENGTH_SHORT).show();
    }
    public void onSwipeBottom() {
        Toast.makeText(MyActivity.this, "bottom", Toast.LENGTH_SHORT).show();
    }

});

이 코드는 왼쪽 및 오른쪽 스와이프를 감지하고, 더 이상 사용되지 않는 API 호출을 방지하며, 이전 답변에 비해 다른 개선 사항이 있습니다.

/**
 * Detects left and right swipes across a view.
 */
public class OnSwipeTouchListener implements OnTouchListener {

    private final GestureDetector gestureDetector;

    public OnSwipeTouchListener(Context context) {
        gestureDetector = new GestureDetector(context, new GestureListener());
    }
Android:오른쪽에서 왼쪽으로 스와이프 제스처를 처리하는 방법
    public void onSwipeLeft() {
    }

    public void onSwipeRight() {
    }

    public boolean onTouch(View v, MotionEvent event) {
        return gestureDetector.onTouchEvent(event);
    }

    private final class GestureListener extends SimpleOnGestureListener {

        private static final int SWIPE_DISTANCE_THRESHOLD = 100;
        private static final int SWIPE_VELOCITY_THRESHOLD = 100;

        @Override
        public boolean onDown(MotionEvent e) {
            return true;
        }

        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
            float distanceX = e2.getX() - e1.getX();
            float distanceY = e2.getY() - e1.getY();
            if (Math.abs(distanceX) > Math.abs(distanceY) && Math.abs(distanceX) > SWIPE_DISTANCE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
                if (distanceX > 0)
                    onSwipeRight();
                else
                    onSwipeLeft();
                return true;
            }
            return false;
        }
    }
}

다음과 같이 사용합니다.

view.setOnTouchListener(new OnSwipeTouchListener(context) {
    @Override
    public void onSwipeLeft() {
        // Whatever
    }
});

클릭 이벤트도 처리해야 하는 경우 몇 가지 수정 사항:

public class OnSwipeTouchListener implements OnTouchListener {

    private final GestureDetector gestureDetector = new GestureDetector(new GestureListener());

    public boolean onTouch(final View v, final MotionEvent event) {
        return gestureDetector.onTouchEvent(event);
    }

    private final class GestureListener extends SimpleOnGestureListener {

        private static final int SWIPE_THRESHOLD = 100;
        private static final int SWIPE_VELOCITY_THRESHOLD = 100;


        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
            boolean result = false;
            try {
                float diffY = e2.getY() - e1.getY();
                float diffX = e2.getX() - e1.getX();
                if (Math.abs(diffX) > Math.abs(diffY)) {
                    if (Math.abs(diffX) > SWIPE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
                        if (diffX > 0) {
                            result = onSwipeRight();
                        } else {
                            result = onSwipeLeft();
                        }
                    }
                } else {
                    if (Math.abs(diffY) > SWIPE_THRESHOLD && Math.abs(velocityY) > SWIPE_VELOCITY_THRESHOLD) {
                        if (diffY > 0) {
                            result = onSwipeBottom();
                        } else {
                            result = onSwipeTop();
                        }
                    }
                }
            } catch (Exception exception) {
                exception.printStackTrace();
            }
            return result;
        }
    }

    public boolean onSwipeRight() {
        return false;
    }

    public boolean onSwipeLeft() {
        return false;
    }

    public boolean onSwipeTop() {
        return false;
    }

    public boolean onSwipeBottom() {
        return false;
    }
}

샘플 사용량:

    background.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View arg0) {
            toggleSomething();
        }
    });
    background.setOnTouchListener(new OnSwipeTouchListener() {
        public boolean onSwipeTop() {
            Toast.makeText(MainActivity.this, "top", Toast.LENGTH_SHORT).show();
            return true;
        }
        public boolean onSwipeRight() {
            Toast.makeText(MainActivity.this, "right", Toast.LENGTH_SHORT).show();
            return true;
        }
        public boolean onSwipeLeft() {
            Toast.makeText(MainActivity.this, "left", Toast.LENGTH_SHORT).show();
            return true;
        }
        public boolean onSwipeBottom() {
            Toast.makeText(MainActivity.this, "bottom", Toast.LENGTH_SHORT).show();
            return true;
        }
    });

스크롤 뷰 내에서 스와이프 제스처를 사용하려는 경우를 위해 Mirek의 답변을 확장합니다.기본적으로 스크롤 보기의 터치 수신기는 비활성화되므로 스크롤 작업은 수행되지 않습니다.이 문제를 해결하려면 다음을 재정의해야 합니다.dispatchTouchEventActivity수신기를 사용한 후 이 메서드의 상속된 버전을 반환합니다.

미렉의 코드를 몇 가지 수정하기 위해:에 게터를 추가합니다.gestureDetector에 시대에OnSwipeTouchListener.

public GestureDetector getGestureDetector(){
    return  gestureDetector;
}

을 합니다.OnSwipeTouchListener클래스 전체 필드로 활동 내부.

OnSwipeTouchListener onSwipeTouchListener;

그에 따라 사용 코드를 수정합니다.

onSwipeTouchListener = new OnSwipeTouchListener(MyActivity.this) {
    public void onSwipeTop() {
        Toast.makeText(MyActivity.this, "top", Toast.LENGTH_SHORT).show();
    }
    public void onSwipeRight() {
        Toast.makeText(MyActivity.this, "right", Toast.LENGTH_SHORT).show();
    }
    public void onSwipeLeft() {
        Toast.makeText(MyActivity.this, "left", Toast.LENGTH_SHORT).show();
    }
    public void onSwipeBottom() {
        Toast.makeText(MyActivity.this, "bottom", Toast.LENGTH_SHORT).show();
    }
});

imageView.setOnTouchListener(onSwipeTouchListener);

그리고 다음을 무시합니다.dispatchTouchEvent inside 내법방의Activity:

@Override
    public boolean dispatchTouchEvent(MotionEvent ev){
        swipeListener.getGestureDetector().onTouchEvent(ev); 
            return super.dispatchTouchEvent(ev);   
    }

이제 스크롤 및 스와이프 작업이 모두 작동합니다.

을 .Click Listener,DoubleClick Listener,OnLongPress Listener,Swipe Left,Swipe Right,Swipe Up,Swipe Down 글로싱에View할 필요가 있습니다.setOnTouchListener를 들어 예를 들어,

view.setOnTouchListener(new OnSwipeTouchListener(MainActivity.this) {

            @Override
            public void onClick() {
                super.onClick();
                // your on click here
            }

            @Override
            public void onDoubleClick() {
                super.onDoubleClick();
                // your on onDoubleClick here
            }

            @Override
            public void onLongClick() {
                super.onLongClick();
                // your on onLongClick here
            }

            @Override
            public void onSwipeUp() {
                super.onSwipeUp();
                // your swipe up here
            }

            @Override
            public void onSwipeDown() {
                super.onSwipeDown();
                // your swipe down here.
            }

            @Override
            public void onSwipeLeft() {
                super.onSwipeLeft();
                // your swipe left here.
            }

            @Override
            public void onSwipeRight() {
                super.onSwipeRight();
                // your swipe right here.
            }
        });

}

는 이를위필니다합요가 필요합니다.OnSwipeTouchListener를 하는 클래스OnTouchListener.

public class OnSwipeTouchListener implements View.OnTouchListener {

private GestureDetector gestureDetector;

public OnSwipeTouchListener(Context c) {
    gestureDetector = new GestureDetector(c, new GestureListener());
}

public boolean onTouch(final View view, final MotionEvent motionEvent) {
    return gestureDetector.onTouchEvent(motionEvent);
}

private final class GestureListener extends GestureDetector.SimpleOnGestureListener {

    private static final int SWIPE_THRESHOLD = 100;
    private static final int SWIPE_VELOCITY_THRESHOLD = 100;

    @Override
    public boolean onDown(MotionEvent e) {
        return true;
    }

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

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

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

    // Determines the fling velocity and then fires the appropriate swipe event accordingly
    @Override
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
        boolean result = false;
        try {
            float diffY = e2.getY() - e1.getY();
            float diffX = e2.getX() - e1.getX();
            if (Math.abs(diffX) > Math.abs(diffY)) {
                if (Math.abs(diffX) > SWIPE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
                    if (diffX > 0) {
                        onSwipeRight();
                    } else {
                        onSwipeLeft();
                    }
                }
            } else {
                if (Math.abs(diffY) > SWIPE_THRESHOLD && Math.abs(velocityY) > SWIPE_VELOCITY_THRESHOLD) {
                    if (diffY > 0) {
                        onSwipeDown();
                    } else {
                        onSwipeUp();
                    }
                }
            }
        } catch (Exception exception) {
            exception.printStackTrace();
        }
        return result;
    }
}

public void onSwipeRight() {
}

public void onSwipeLeft() {
}

public void onSwipeUp() {
}

public void onSwipeDown() {
}

public void onClick() {

}

public void onDoubleClick() {

}

public void onLongClick() {

}
}

@Myrek Rusin의 Kotlin 버전은 다음과 같습니다.

OnSwipTouchListener.kt:

open class OnSwipeTouchListener(ctx: Context) : OnTouchListener {

    private val gestureDetector: GestureDetector

    companion object {

        private val SWIPE_THRESHOLD = 100
        private val SWIPE_VELOCITY_THRESHOLD = 100
    }

    init {
        gestureDetector = GestureDetector(ctx, GestureListener())
    }

    override fun onTouch(v: View, event: MotionEvent): Boolean {
        return gestureDetector.onTouchEvent(event)
    }

    private inner class GestureListener : SimpleOnGestureListener() {


        override fun onDown(e: MotionEvent): Boolean {
            return true
        }

        override fun onFling(e1: MotionEvent, e2: MotionEvent, velocityX: Float, velocityY: Float): Boolean {
            var result = false
            try {
                val diffY = e2.y - e1.y
                val diffX = e2.x - e1.x
                if (Math.abs(diffX) > Math.abs(diffY)) {
                    if (Math.abs(diffX) > SWIPE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
                        if (diffX > 0) {
                            onSwipeRight()
                        } else {
                            onSwipeLeft()
                        }
                        result = true
                    }
                } else if (Math.abs(diffY) > SWIPE_THRESHOLD && Math.abs(velocityY) > SWIPE_VELOCITY_THRESHOLD) {
                    if (diffY > 0) {
                        onSwipeBottom()
                    } else {
                        onSwipeTop()
                    }
                    result = true
                }
            } catch (exception: Exception) {
                exception.printStackTrace()
            }

            return result
        }


    }

    open fun onSwipeRight() {}

    open fun onSwipeLeft() {}

    open fun onSwipeTop() {}

    open fun onSwipeBottom() {}
}

용도:

view.setOnTouchListener(object : OnSwipeTouchListener(context) {

    override fun onSwipeTop() {
        super.onSwipeTop()
    }

    override fun onSwipeBottom() {
        super.onSwipeBottom()
    }

    override fun onSwipeLeft() {
        super.onSwipeLeft()
    }

    override fun onSwipeRight() {
        super.onSwipeRight()
    }
})

그자리의 open키워드가 제게 중요한 포인트였어요...

복잡한 계산은 필요 없습니다.를 사용하는 것만으로 가능합니다.OnGestureListener로부터의 인터페이스.GestureDetector학생들

에 안에.onFling방법은 다음과 같이 네 방향 모두를 감지할 수 있습니다.

MyGestureListener.java:

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

public class MyGestureListener implements GestureDetector.OnGestureListener{

    private static final long VELOCITY_THRESHOLD = 3000;

    @Override
    public boolean onDown(final MotionEvent e){ return false; }

    @Override
    public void onShowPress(final MotionEvent e){ }

    @Override
    public boolean onSingleTapUp(final MotionEvent e){ return false; }

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

    @Override
    public void onLongPress(final MotionEvent e){ }

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

        if(Math.abs(velocityX) < VELOCITY_THRESHOLD 
                    && Math.abs(velocityY) < VELOCITY_THRESHOLD){
            return false;//if the fling is not fast enough then it's just like drag
        }

        //if velocity in X direction is higher than velocity in Y direction,
        //then the fling is horizontal, else->vertical
        if(Math.abs(velocityX) > Math.abs(velocityY)){
            if(velocityX >= 0){
                Log.i("TAG", "swipe right");
            }else{//if velocityX is negative, then it's towards left
                Log.i("TAG", "swipe left");
            }
        }else{
            if(velocityY >= 0){
                Log.i("TAG", "swipe down");
            }else{
                Log.i("TAG", "swipe up");
            }
        }

        return true;
    }
}

용도:

GestureDetector mDetector = new GestureDetector(MainActivity.this, new MyGestureListener());

view.setOnTouchListener(new View.OnTouchListener(){
    @Override
    public boolean onTouch(final View v, final MotionEvent event){
        return mDetector.onTouchEvent(event);
    }
});

SwipListView를 사용하여 제스처 감지를 처리할 수 있습니다.

스크린샷

onClick을 추가하기 위해, 제가 한 일은 다음과 같습니다.

....
// in OnSwipeTouchListener class

private final class GestureListener extends SimpleOnGestureListener {

    .... // normal GestureListener  code

   @Override
    public boolean onSingleTapConfirmed(MotionEvent e) {
        onClick(); // my method
        return super.onSingleTapConfirmed(e);
    }

} // end GestureListener class

    public void onSwipeRight() {
    }

    public void onSwipeLeft() {
    }

    public void onSwipeTop() {
    }

    public void onSwipeBottom() {
    }

    public void onClick(){ 
    }


    // as normal
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        return gestureDetector.onTouchEvent(event);
}

} // end OnSwipeTouchListener class

fragments를 사용하고 있으므로 getActivity()를 컨텍스트에 사용합니다.이것이 제가 구현한 방법입니다. 그리고 작동합니다.


myLayout.setOnTouchListener(new OnSwipeTouchListener(getActivity()) {
            public void onSwipeTop() {
                Toast.makeText(getActivity(), "top", Toast.LENGTH_SHORT).show();
            }
            public void onSwipeRight() {
                Toast.makeText(getActivity(), "right", Toast.LENGTH_SHORT).show();
            }
            public void onSwipeLeft() {
                Toast.makeText(getActivity(), "left", Toast.LENGTH_SHORT).show();
            }
            public void onSwipeBottom() {
                Toast.makeText(getActivity(), "bottom", Toast.LENGTH_SHORT).show();
            }

            public void onClick(){
                Toast.makeText(getActivity(), "clicked", Toast.LENGTH_SHORT).show();
            }
        });

@Edward Brey의 방법은 잘 작동합니다.다른 사용자가 가져오기를 복사하여 붙여넣을 경우OnSwipeTouchListener다음과 같습니다.

 import android.content.Context;
 import android.view.GestureDetector;
 import android.view.GestureDetector.SimpleOnGestureListener;
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.View.OnTouchListener;

했습니다.OnGestureRegisterListener.java여기에는 스와이프, 클릭 및 긴 클릭 제스처가 포함됩니다.

OnGestureRegisterListener.java

public abstract class OnGestureRegisterListener implements View.OnTouchListener {

    private final GestureDetector gestureDetector;
    private View view;

    public OnGestureRegisterListener(Context context) {
        gestureDetector = new GestureDetector(context, new GestureListener());
    }

    @Override
    public boolean onTouch(View view, MotionEvent event) {
        this.view = view;
        return gestureDetector.onTouchEvent(event);
    }

    public abstract void onSwipeRight(View view);
    public abstract void onSwipeLeft(View view);
    public abstract void onSwipeBottom(View view);
    public abstract void onSwipeTop(View view);
    public abstract void onClick(View view);
    public abstract boolean onLongClick(View view);

    private final class GestureListener extends GestureDetector.SimpleOnGestureListener {

        private static final int SWIPE_THRESHOLD = 100;
        private static final int SWIPE_VELOCITY_THRESHOLD = 100;

        @Override
        public boolean onDown(MotionEvent e) {
            return true;
        }

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

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

        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
            boolean result = false;
            try {
                float diffY = e2.getY() - e1.getY();
                float diffX = e2.getX() - e1.getX();
                if (Math.abs(diffX) > Math.abs(diffY)) {
                    if (Math.abs(diffX) > SWIPE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
                        if (diffX > 0) {
                            onSwipeRight(view);
                        } else {
                            onSwipeLeft(view);
                        }
                        result = true;
                    }
                }
                else if (Math.abs(diffY) > SWIPE_THRESHOLD && Math.abs(velocityY) > SWIPE_VELOCITY_THRESHOLD) {
                    if (diffY > 0) {
                        onSwipeBottom(view);
                    } else {
                        onSwipeTop(view);
                    }
                    result = true;
                }
            } catch (Exception exception) {
                exception.printStackTrace();
            }
            return result;
        }

    }
}

이렇게 사용하시면 됩니다.또한 쉽게 전달할 수 있습니다.View매개 변수

OnGestureRegisterListener onGestureRegisterListener = new OnGestureRegisterListener(this) {
    public void onSwipeRight(View view) {
        // Do something
    }
    public void onSwipeLeft(View view) {
        // Do something
    }
    public void onSwipeBottom(View view) {
        // Do something
    }
    public void onSwipeTop(View view) {
        // Do something
    }
    public void onClick(View view) {
        // Do something
    }
    public boolean onLongClick(View view) { 
        // Do something
        return true;
    }
};

Button button = findViewById(R.id.my_button);
button.setOnTouchListener(onGestureRegisterListener);

저도 비슷한 일을 하고 있습니다만, 수평 스위프만을 위한 것입니다.

import android.content.Context
import android.view.GestureDetector
import android.view.MotionEvent
import android.view.View

abstract class OnHorizontalSwipeListener(val context: Context) : View.OnTouchListener {    

    companion object {
         const val SWIPE_MIN = 50
         const val SWIPE_VELOCITY_MIN = 100
    }

    private val detector = GestureDetector(context, GestureListener())

    override fun onTouch(view: View, event: MotionEvent) = detector.onTouchEvent(event)    

    abstract fun onRightSwipe()

    abstract fun onLeftSwipe()

    private inner class GestureListener : GestureDetector.SimpleOnGestureListener() {    

        override fun onDown(e: MotionEvent) = true

        override fun onFling(e1: MotionEvent, e2: MotionEvent, velocityX: Float, velocityY: Float)
            : Boolean {

            val deltaY = e2.y - e1.y
            val deltaX = e2.x - e1.x

            if (Math.abs(deltaX) < Math.abs(deltaY)) return false

            if (Math.abs(deltaX) < SWIPE_MIN
                    && Math.abs(velocityX) < SWIPE_VELOCITY_MIN) return false

            if (deltaX > 0) onRightSwipe() else onLeftSwipe()

            return true
        }
    }
}

그런 다음 뷰 구성요소에 사용할 수 있습니다.

private fun listenHorizontalSwipe(view: View) {
    view.setOnTouchListener(object : OnHorizontalSwipeListener(context!!) {
            override fun onRightSwipe() {
                Log.d(TAG, "Swipe right")
            }

            override fun onLeftSwipe() {
                Log.d(TAG, "Swipe left")
            }

        }
    )
}

이 질문은 다소 오래된 질문이고 매우 인기가 있기 때문에 답변을 업데이트하고 답변과 댓글에 여러 제안을 결합하여 개선하려고 했습니다.

  • Java에서 Kotlin으로 전환하고 일부 Kotlin 구문 아이캔디(주관적)를 사용했습니다.
  • Made on Swip-funcitons는 이벤트를 소비했는지 여부를 반환합니다(ruX
  • if 문에서 결과 할당을 해제하고 변수를 제거함(직접 반환)
  • 수직 및 수평 스위프만 감지할 수 있는 대안
  • 위쪽, 아래쪽, 오른쪽 및 왼쪽만 탐지할 수 있는 대안입니다.
  • 일관성을 위해 위쪽과 아래쪽이 위쪽과 아래쪽으로 이름이 변경되었습니다(위치가 아닌 방향).

네 방향 모두를 문지릅니다.

open class OnSwipeTouchListener(val context: Context?) : OnTouchListener {
    companion object {
        private const val SwipeThreshold = 100
        private const val SwipeVelocityThreshold = 100
    }

    private val gestureDetector = GestureDetector(context, GestureListener())

    override fun onTouch(v: View, event: MotionEvent): Boolean {
        return gestureDetector.onTouchEvent(event)
    }

    open fun onSwipeRight(): Boolean { return false }
    open fun onSwipeLeft(): Boolean { return false }
    open fun onSwipeUp(): Boolean { return false }
    open fun onSwipeDown(): Boolean { return false }

    private inner class GestureListener : SimpleOnGestureListener() {
        override fun onDown(e: MotionEvent): Boolean {
            return true
        }

        override fun onFling(
            e1: MotionEvent,
            e2: MotionEvent,
            velocityX: Float,
            velocityY: Float,
        ): Boolean {
            try {
                val diffY = e2.y - e1.y
                val diffX = e2.x - e1.x

                if (abs(diffX) > abs(diffY)) {
                    if (abs(diffX) > SwipeThreshold && abs(velocityX) > SwipeVelocityThreshold) {
                        return when {
                            diffX > 0 -> onSwipeRight()
                            else -> onSwipeLeft()
                        }
                    }
                } else if (abs(diffY) > SwipeThreshold && abs(velocityY) > SwipeVelocityThreshold) {
                    return when {
                        diffY > 0 -> onSwipeDown()
                        else -> onSwipeUp()
                    }
                }
            } catch (exception: Exception) {
                exception.printStackTrace()
            }
            return false
        }
    }
}

용도:

myView.setOnTouchListener(object : OnSwipeTouchListener(context) {
            // Implement any function you need:
            override fun onSwipeUp(): Boolean {
                Toast.makeText(context, "UP", Toast.LENGTH_SHORT).show()
                return true
            }

            override fun onSwipeLeft(): Boolean {
                Toast.makeText(context, "LEFT", Toast.LENGTH_SHORT).show()
                return true
            }
        })

온플링()에 대한 대안

다른 방법으로는 코드를 조금 더 제거하고 검사를 다시 정렬할 수 있습니다.재주문은 필요없지만 조금 깔끔하고 이해하기 쉬운 것 같습니다.는 코는다음넣것다니입을에 넣을 입니다.try하고, 실행하세요.onSwipe

수평

val diffY = e2.y - e1.y

return if (abs(velocityY) > SwipeVelocityThreshold) {
    when {
        diffY > SwipeThreshold -> onSwipeDown()
        diffY < -SwipeThreshold -> onSwipeUp()
        else -> false
    }
} else false

수직

val diffX = e2.x - e1.x

return if (abs(velocityX) > SwipeVelocityThreshold) {
    when {
        diffX > SwipeThreshold -> onSwipeRight()
        diffX < -SwipeThreshold -> onSwipeLeft()
        else -> false
    }
} else false

한 방향

"up" 예제

val diffY = e2.y - e1.y

return when {
    diffY < -SwipeThreshold -> onSwipeUp()
    else -> false
}

추가 참고 사항:(ruX 답변)에서 그들은 제거에 대해 논의했습니다.onDown또한 감지하기 위해onClickListener같은 견해로하지만, 제가 제거했을 때onDown그 수업은 더 이상 작동하지 않았습니다.왜 그런지는 정확히 모르겠습니다.는 나는코조습다니사했를의 코드를 .GestureDetector하지만 그것은 매우 복잡하고 수익 가치의 결과입니다.onDown몇 가지 의미가 있는 것 같습니다.그래서 그냥 두고 왔어요.또한, 당신은 그냥 사용할 수 있습니다.SimpleOnGestureListener.onSingleTapUp()이 그랬던 처럼.onFling다음을 생성하기onClick()함수를 호출합니다.

버전 정보:

  • compileSdkVersion 31
  • minSdk 버전 24
  • targetSdkVersion 31

@Myrek Rusin 응답을 약간 수정하면 멀티터치 스위프를 감지할 수 있습니다.이 코드는 코틀린에 있습니다.

class OnSwipeTouchListener(ctx: Context, val onGesture: (gestureCode: Int) -> Unit) : OnTouchListener {

private val SWIPE_THRESHOLD = 200
private val SWIPE_VELOCITY_THRESHOLD = 200

private val gestureDetector: GestureDetector

var fingersCount = 0

fun resetFingers() {
    fingersCount = 0
}

init {
    gestureDetector = GestureDetector(ctx, GestureListener())
}

override fun onTouch(v: View, event: MotionEvent): Boolean {
    if (event.pointerCount > fingersCount) {
        fingersCount = event.pointerCount
    }
    return gestureDetector.onTouchEvent(event)
}

private inner class GestureListener : SimpleOnGestureListener() {

    override fun onDown(e: MotionEvent): Boolean {
        return true
    }

    override fun onFling(e1: MotionEvent, e2: MotionEvent, velocityX: Float, velocityY: Float): Boolean {
        var result = false
        try {
            val diffY = e2.y - e1.y
            val diffX = e2.x - e1.x
            if (Math.abs(diffX) > Math.abs(diffY)) {
                if (Math.abs(diffX) > SWIPE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
                    if (diffX > 0) {
                        val gesture = when (fingersCount) {
                            1 -> Gesture.SWIPE_RIGHT
                            2 -> Gesture.TWO_FINGER_SWIPE_RIGHT
                            3 -> Gesture.THREE_FINGER_SWIPE_RIGHT
                            else -> -1
                        }
                        if (gesture > 0) {
                            onGesture.invoke(gesture)
                        }
                    } else {
                        val gesture = when (fingersCount) {
                            1 -> Gesture.SWIPE_LEFT
                            2 -> Gesture.TWO_FINGER_SWIPE_LEFT
                            3 -> Gesture.THREE_FINGER_SWIPE_LEFT
                            else -> -1
                        }
                        if (gesture > 0) {
                            onGesture.invoke(gesture)
                        }
                    }
                    resetFingers()
                }
            } else if (Math.abs(diffY) > SWIPE_THRESHOLD && Math.abs(velocityY) > SWIPE_VELOCITY_THRESHOLD) {
                if (diffY > 0) {
                    val gesture = when (fingersCount) {
                        1 ->  Gesture.SWIPE_DOWN
                        2 -> Gesture.TWO_FINGER_SWIPE_DOWN
                        3 -> Gesture.THREE_FINGER_SWIPE_DOWN
                        else -> -1
                    }
                    if (gesture > 0) {
                        onGesture.invoke(gesture)
                    }
                } else {
                    val gesture = when (fingersCount) {
                        1 ->  Gesture.SWIPE_UP
                        2 -> Gesture.TWO_FINGER_SWIPE_UP
                        3 -> Gesture.THREE_FINGER_SWIPE_UP
                        else -> -1
                    }
                    if (gesture > 0) {
                        onGesture.invoke(gesture)
                    }
                }
                resetFingers()
            }
            result = true

        } catch (exception: Exception) {
            exception.printStackTrace()
        }

        return result
    }
}}

여기서 Gesture.SWIPE_RIGHT 등은 활동 후반에 제스처 종류를 감지하는 데 사용하는 고유한 제스처 정수 식별자입니다.

rootView?.setOnTouchListener(OnSwipeTouchListener(this, {
    gesture -> log(Gesture.parseName(this, gesture))
}))

보시다시피 제스처는 제가 이전에 전달한 값을 포함하는 정수 변수입니다.

이 질문은 수년 전에 던져진 것입니다.이제 더 나은 솔루션이 있습니다. SmartSwip: https://github.com/luckybilly/SmartSwipe

코드는 다음과 같습니다.

SmartSwipe.wrap(contentView)
        .addConsumer(new StayConsumer()) //contentView stay while swiping with StayConsumer
        .enableAllDirections() //enable directions as needed
        .addListener(new SimpleSwipeListener() {
            @Override
            public void onSwipeOpened(SmartSwipeWrapper wrapper, SwipeConsumer consumer, int direction) {
                //direction: 
                //  1: left
                //  2: right
                //  4: top
                //  8: bottom
            }
        })
;

@Mirek Rusin answier는 매우 좋습니다.하지만 작은 버그가 있어 수정이 필요합니다.

public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
            boolean result = false;
            try {
                float diffY = e2.getY() - e1.getY();
                float diffX = e2.getX() - e1.getX();
                if (Math.abs(diffX) > Math.abs(diffY)) {
                    if (Math.abs(diffX) > SWIPE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
                        if (diffX > 0) {
                            if (getOnSwipeListener() != null) {
                                getOnSwipeListener().onSwipeRight();
                            }
                        } else {
                            if (getOnSwipeListener() != null) {
                                getOnSwipeListener().onSwipeLeft();
                            }
                        }
                        result = true;
                    }
                }
                else if (Math.abs(diffY) > SWIPE_THRESHOLD && Math.abs(velocityY) > SWIPE_VELOCITY_THRESHOLD) {
                    if (diffY > 0) {
                        if (getOnSwipeListener() != null) {
                            getOnSwipeListener().onSwipeBottom();
                        }
                    } else {
                        if (getOnSwipeListener() != null) {
                            getOnSwipeListener().onSwipeTop();
                        }
                    }
                    result = true;
                }

뭐가 달라요?모든 요구 사항(SWIFT_THRESHOLD 및 SWIFT_VELOCY_THRESHOLD 모두 OK)을 확인한 경우에만 결과 =를 true로 설정합니다.이는 일부 요구 사항이 충족되지 않은 경우 스와이프를 폐기할 때 중요하며 OnSwip의 OnTouchEvent 방법을 사용해야 합니다.청취자 터치!

다음은 제스처 방향을 감지하는 간단한 Android 코드입니다.

MainActivity.java그리고.activity_main.xml다음 코드를 작성합니다.

기본 활동.java

import java.util.ArrayList;

import android.app.Activity;
import android.gesture.Gesture;
import android.gesture.GestureLibraries;
import android.gesture.GestureLibrary;
import android.gesture.GestureOverlayView;
import android.gesture.GestureOverlayView.OnGesturePerformedListener;
import android.gesture.GestureStroke;
import android.gesture.Prediction;
import android.os.Bundle;
import android.widget.Toast;

public class MainActivity extends Activity implements
        OnGesturePerformedListener {

    GestureOverlayView gesture;
    GestureLibrary lib;
    ArrayList<Prediction> prediction;

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

        lib = GestureLibraries.fromRawResource(MainActivity.this,
                R.id.gestureOverlayView1);
        gesture = (GestureOverlayView) findViewById(R.id.gestureOverlayView1);
        gesture.addOnGesturePerformedListener(this);
    }

    @Override
    public void onGesturePerformed(GestureOverlayView overlay, Gesture gesture) {
        ArrayList<GestureStroke> strokeList = gesture.getStrokes();
        // prediction = lib.recognize(gesture);
        float f[] = strokeList.get(0).points;
        String str = "";

        if (f[0] < f[f.length - 2]) {
            str = "Right gesture";
        } else if (f[0] > f[f.length - 2]) {
            str = "Left gesture";
        } else {
            str = "no direction";
        }
        Toast.makeText(getApplicationContext(), str, Toast.LENGTH_LONG).show();

    }

}

activity_main.xml

<android.gesture.GestureOverlayView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:android1="http://schemas.android.com/apk/res/android"
    xmlns:android2="http://schemas.android.com/apk/res/android"
    android:id="@+id/gestureOverlayView1"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android1:orientation="vertical" >

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Draw gesture"
        android:textAppearance="?android:attr/textAppearanceMedium" />

</android.gesture.GestureOverlayView>

코틀린에서의 에드워드 브레이의 대답의 용법.

 view.setOnTouchListener(object: OnSwipeTouchListener(this) {
      override fun onSwipeLeft() {
        super.onSwipeLeft()
      }
      override fun onSwipeRight() {
        super.onSwipeRight()
      }
    }
 )

이 문제는 여전히 존재합니다.다음 클래스를 추가합니다.

private class SwipeFirstTouchListener implements View.OnTouchListener {

    private final DirtyOnSwipeTouchListener swipe;
    private final View.OnTouchListener delegate;

    private SwipeFirstTouchListener(DirtyOnSwipeTouchListener swipe, View.OnTouchListener delegate) {
        this.swipe = swipe;
        this.delegate = delegate;
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        if (!swipe.onTouch(v, event)) {
            // no a swipe, so lets try with the rest of the events
            return delegate.onTouch(v, event);
        }
        return false;
    }
}

그리고.

private class DirtyOnSwipeTouchListener extends OnSwipeTouchListener {
    private boolean dirty = false;
    private OnSwipeTouchListener delegate;

    public DirtyOnSwipeTouchListener(Context ctx, OnSwipeTouchListener delegate) {
        super(ctx);

        this.delegate = delegate;
    }

    private void reset() {
        dirty = false;
    }

    public void onSwipeTop() {
        dirty = true;

        delegate.onSwipeTop();
    }

    public void onSwipeRight() {
        dirty = true;
        delegate.onSwipeRight();
    }

    public void onSwipeLeft() {
        dirty = true;
        delegate.onSwipeLeft();
    }

    public void onSwipeBottom() {
        dirty = true;
        delegate.onSwipeBottom();
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        try {
            super.onTouch(v, event);

            return dirty;
        } finally {
            dirty = false;
        }

    }
};

클래스는 인터넷에서 찾을 수 있습니다.

public class OnSwipeTouchListener implements OnTouchListener {
    
    private static final String TAG = OnSwipeTouchListener.class.getName();

    private final GestureDetector gestureDetector;

    public OnSwipeTouchListener(Context ctx) {
        gestureDetector = new GestureDetector(ctx, new GestureListener());
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        return gestureDetector.onTouchEvent(event);
    }

    private final class GestureListener extends GestureDetector.SimpleOnGestureListener {

        private static final int SWIPE_THRESHOLD = 100;
        private static final int SWIPE_VELOCITY_THRESHOLD = 100;

        @Override
        public boolean onDown(MotionEvent e) {
            return true;
        }

        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
            boolean result = false;
            try {
                float diffY = e2.getY() - e1.getY();
                float diffX = e2.getX() - e1.getX();
                if (Math.abs(diffX) > Math.abs(diffY)) {
                    if (Math.abs(diffX) > SWIPE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
                        if (diffX > 0) {
                            onSwipeRight();
                        } else {
                            onSwipeLeft();
                        }
                        result = true;
                    }
                } else if (Math.abs(diffY) > SWIPE_THRESHOLD && Math.abs(velocityY) > SWIPE_VELOCITY_THRESHOLD) {
                    if (diffY > 0) {
                        onSwipeBottom();
                    } else {
                        onSwipeTop();
                    }
                    result = true;
                }
            } catch (Exception exception) {
                Log.d(TAG, "Unexpected problem handling swipes, ignoring.", exception);
            }
            return result;
        }
    }

    public void onSwipeRight() {
        // Do nothing
    }

    public void onSwipeLeft() {
        // Do nothing
    }

    public void onSwipeTop() {
        // Do nothing
    }

    public void onSwipeBottom() {
        // Do nothing
    }
}

그런 다음 자신의 것을 추가합니다.OnTouchListener그리고.OnSwipeTouchListener이와 같이:

    DirtyOnSwipeTouchListener swipe = new DirtyOnSwipeTouchListener(this, new OnSwipeTouchListener(this) {
        public void onSwipeTop() {
            // your code here
        }

        public void onSwipeRight() {
            // your code here
        }

        public void onSwipeLeft() {
            // your code here
        }

        public void onSwipeBottom() {
            // your code here
        }
    });


    View.OnTouchListener toggleListener = new View.OnTouchListener() {
        public boolean onTouch(View v, MotionEvent event) {
            if (event.getAction() == MotionEvent.ACTION_UP) {
                // your code here

                return true;
            } else if (event.getAction() == MotionEvent.ACTION_DOWN) {
                // your code here

                return true;
            }
            return false;
        }
    };

    SwipeFirstTouchListener swipeFirstTouchListener = new SwipeFirstTouchListener(swipe, toggleListener);

    myView.setOnTouchListener(swipeFirstTouchListener);

목록 항목을 스와이프할 때 수행이 포함된 단추를 표시하려면 인터넷에 이러한 동작이 있는 많은 라이브러리가 있습니다.저는 인터넷에서 찾은 도서관을 구현했고 매우 만족합니다.그것은 매우 사용하기 쉽고 매우 빠릅니다.원래 라이브러리를 개선하고 항목 클릭 청취자를 새로 추가했습니다.또한 저는 폰트 어썸 라이브러리(http://fortawesome.github.io/Font-Awesome/) 를 추가했습니다. 이제 새로운 아이템 제목을 추가하고 폰트 어썸에서 아이콘 이름을 지정하기만 하면 됩니다.

여기에 깃허브 링크가 있습니다.

import android.content.Context
import android.view.GestureDetector
import android.view.GestureDetector.SimpleOnGestureListener
import android.view.MotionEvent
import android.view.View
import android.view.View.OnTouchListener

/**
 * Detects left and right swipes across a view.
 */
class OnSwipeTouchListener(context: Context, onSwipeCallBack: OnSwipeCallBack?) : OnTouchListener {

    private var gestureDetector : GestureDetector
    private var onSwipeCallBack: OnSwipeCallBack?=null

    init {

        gestureDetector = GestureDetector(context, GestureListener())
        this.onSwipeCallBack = onSwipeCallBack!!
    }
    companion object {

        private val SWIPE_DISTANCE_THRESHOLD = 100
        private val SWIPE_VELOCITY_THRESHOLD = 100
    }

   /* fun onSwipeLeft() {}

    fun onSwipeRight() {}*/

    override fun onTouch(v: View, event: MotionEvent): Boolean {


        return gestureDetector.onTouchEvent(event)
    }

    private inner class GestureListener : SimpleOnGestureListener() {

        override fun onDown(e: MotionEvent): Boolean {
            return true
        }

        override fun onFling(eve1: MotionEvent?, eve2: MotionEvent?, velocityX: Float, velocityY: Float): Boolean {
            try {
                if(eve1 != null&& eve2!= null) {
                    val distanceX = eve2?.x - eve1?.x
                    val distanceY = eve2?.y - eve1?.y
                    if (Math.abs(distanceX) > Math.abs(distanceY) && Math.abs(distanceX) > SWIPE_DISTANCE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
                        if (distanceX > 0)
                            onSwipeCallBack!!.onSwipeLeftCallback()
                        else
                            onSwipeCallBack!!.onSwipeRightCallback()
                        return true
                    }
                }
            }catch (exception:Exception){
                exception.printStackTrace()
            }

            return false
        }


    }
}

2012년 이후로 조금 늦은 것은 알지만 대부분의 답변보다 짧고 깨끗한 코드라고 생각하기 때문에 누군가에게 도움이 되길 바랍니다.

view.setOnTouchListener((v, event) -> {
        
int action = MotionEventCompat.getActionMasked(event);

switch(action) {
    case (MotionEvent.ACTION_DOWN) :
        Log.d(DEBUG_TAG,"Action was DOWN");
        return true;

    case (MotionEvent.ACTION_MOVE) :
        Log.d(DEBUG_TAG,"Action was MOVE");
        return true;

    case (MotionEvent.ACTION_UP) :
        Log.d(DEBUG_TAG,"Action was UP");
        return true;

    case (MotionEvent.ACTION_CANCEL) :
        Log.d(DEBUG_TAG,"Action was CANCEL");
        return true;

    case (MotionEvent.ACTION_OUTSIDE) :
        Log.d(DEBUG_TAG,"Movement occurred outside bounds " +
                "of current screen element");
        return true;

    default :
        return super.onTouchEvent(event);
}
    });

물론 당신은 관련된 제스처만 당신에게 남길 수 있습니다.

src: https://developer.android.com/training/gestures/detector

언급URL : https://stackoverflow.com/questions/4139288/android-how-to-handle-right-to-left-swipe-gestures

반응형