그리드 레이아웃에서 제스처 감지 감지


1105

fling내 Android 응용 프로그램에서 동작 감지를 원합니다 .

내가 가진 것은 GridLayout9 ImageView초 를 포함 하는 것 입니다 . 소스는 여기에서 찾을 수 있습니다 : Romain Guys 's Grid Layout .

내가 가져간 파일은 Romain Guy의 Photostream 응용 프로그램 에서 가져온 것으로 약간만 조정되었습니다.

간단한 클릭 상황에서는 내가 추가하는 onClickListener각각 을 구현 ImageView하는 기본으로 설정하면 됩니다 . 를 인식하는 것을 구현하는 것은 무한히 더 복잡해 보입니다 . 나는 이것이 스팬 될 수 있기 때문이라고 생각 합니까?activityView.OnClickListenerflingviews

  • 내 활동이 구현되면 내가 추가 한보 기 또는 보기 OnGestureListener의 제스처 리스너로 설정하는 방법을 모르겠습니다 .GridImage

    public class SelectFilterActivity extends Activity implements
       View.OnClickListener, OnGestureListener { ...
    
  • 내 활동이 구현되면 메소드 OnTouchListener가 없습니다 (플링이 주목할 만한지를 결정할 수있는 매개 변수로 두 가지 이벤트가 있습니다).onFlingoverride

    public class SelectFilterActivity extends Activity implements
        View.OnClickListener, OnTouchListener { ...
    
  • 내가 확장 View과 같이 custom을 만들면 활동이 뷰에서 발생 했음을 알리는 방법을 모르겠습니다 . 어쨌든, 나는 이것을 시도했지만 화면을 터치했을 때 메소드가 호출되지 않았습니다.GestureImageViewImageViewfling

나는 실제로 여러 관점에서 작동하는 구체적인 예가 필요합니다. 무엇을 언제 어떻게해야 listener합니까? 클릭 한 번도 감지 할 수 있어야합니다.

// Gesture detection
mGestureDetector = new GestureDetector(this, new GestureDetector.SimpleOnGestureListener() {

    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
        int dx = (int) (e2.getX() - e1.getX());
        // don't accept the fling if it's too short
        // as it may conflict with a button push
        if (Math.abs(dx) > MAJOR_MOVE && Math.abs(velocityX) > Math.absvelocityY)) {
            if (velocityX > 0) {
                moveRight();
            } else {
                moveLeft();
            }
            return true;
        } else {
            return false;
        }
    }
});

플링을 캡처하기 위해 화면 상단에 투명 뷰를 배치 할 수 있습니까?

inflateXML에서 내 자식 이미지 뷰를 선택하지 않으면 GestureDetector생성자의 새 하위 클래스에 생성자 매개 변수를 전달할 ImageView수 있습니까?

이것은 SelectFilterActivity (Adapted from photostream)fling 감지 기능을 작동 시키려는 매우 간단한 활동입니다 .

나는이 소스를보고있다 :

지금까지 아무것도 효과가 없었으며 포인터를 원했습니다.


이 문제를 해결하는 방법? stackoverflow.com/questions/60464912/…에
Bishwash

답변:


818

Code Shogun 덕분에 코드 가 내 상황에 맞게 조정되었습니다.

OnClickListener평소와 같이 활동을 구현하십시오 .

public class SelectFilterActivity extends Activity implements OnClickListener {

  private static final int SWIPE_MIN_DISTANCE = 120;
  private static final int SWIPE_MAX_OFF_PATH = 250;
  private static final int SWIPE_THRESHOLD_VELOCITY = 200;
  private GestureDetector gestureDetector;
  View.OnTouchListener gestureListener;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    /* ... */

    // Gesture detection
    gestureDetector = new GestureDetector(this, new MyGestureDetector());
    gestureListener = new View.OnTouchListener() {
      public boolean onTouch(View v, MotionEvent event) {
        return gestureDetector.onTouchEvent(event);
      }
    };

  }

  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) {
          Toast.makeText(SelectFilterActivity.this, "Left Swipe", Toast.LENGTH_SHORT).show();
        } else if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
          Toast.makeText(SelectFilterActivity.this, "Right Swipe", Toast.LENGTH_SHORT).show();
        }
      } catch (Exception e) {
         // nothing
      }
      return false;
    }

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

기본 레이아웃에 추가 한 모든보기에 제스처 리스너를 연결하십시오.

// Do this for each view added to the grid
imageView.setOnClickListener(SelectFilterActivity.this); 
imageView.setOnTouchListener(gestureListener);

onClick(View v)활동과 onFling제스처 리스너 모두에서 재정의 된 메소드에 도달하면 경외심을 가지십시오 .

public void onClick(View v) {
  Filter f = (Filter) v.getTag();
  FilterFullscreenActivity.show(this, input, f);
}

포스트 'fling'댄스는 선택 사항이지만 권장됩니다.


109
이 코드에 감사드립니다! 매우 도움이되었습니다. 그러나 나는 제스처를 작동시키는 동안 매우 실망스러운 캐치를 만났습니다. SimpleOnGestureListener에서 제스처를 등록하려면 onDown을 재정의해야합니다. 그냥 true를 반환 할 수 있지만 정의해야합니다. 추신 : 내 API 개정판인지 하드웨어인지 모르겠지만 HTC Droid Eris에서 1.5를 사용하고 있습니다.
Cdsboy 2009

코드를 시도했지만 스 와이프하거나 클릭하면 (마우스로 에뮬레이터에서 작동하게 함) 항상 onClick 메서드에 정의 된 토스트를 얻으므로 에뮬레이터는 스 와이프없이 클릭 만 감지합니다. 왜 그래야만하지?
lomza

이 코드를 시도했지만 작동하지 않았습니다. 내 갤러리 뷰 내의 자식 뷰 중 하나에 onClick 리스너를 적용해도 여전히 스크롤 할 수 없습니다.
Jonathan

Iomza : Break 문을 작성하고 코드를 단계별로 실행하려고 했습니까?
IgorGanapolsky

내부 클래스를 사용하기위한 좋은! 매우 깨끗한 접근법.
IgorGanapolsky

211

위의 답변 중 하나는 다른 픽셀 밀도를 다루는 것을 언급하지만 손으로 ​​스 와이프 매개 변수를 계산할 것을 제안합니다. ViewConfigurationclass를 사용하여 시스템에서 실제로 스케일되고 합리적인 값을 얻을 수 있습니다 .

final ViewConfiguration vc = ViewConfiguration.get(getContext());
final int swipeMinDistance = vc.getScaledPagingTouchSlop();
final int swipeThresholdVelocity = vc.getScaledMinimumFlingVelocity();
final int swipeMaxOffPath = vc.getScaledTouchSlop();
// (there is also vc.getScaledMaximumFlingVelocity() one could check against)

이 값을 사용하면 응용 프로그램과 나머지 시스템간에 "느낌"느낌이 더 일관된 것으로 나타났습니다.


11
내가 사용 swipeMinDistance = vc.getScaledPagingTouchSlop()하고 swipeMaxOffPath = vc.getScaledTouchSlop().
Thomas Ahle

8
getScaledTouchSlop어색하게 오프셋 결과가 거의 없습니다. 예를 들어 540 개의 높은 화면에서 24 픽셀 만 있으면 손가락으로 범위를 유지하기가 매우 어렵습니다. : S
WonderCsabo

148

나는 그것을 조금 다르게하고 구현하는 추가 검출기 클래스를 작성했습니다. View.onTouchListener

onCreate간단히 다음과 같이 가장 낮은 레이아웃에 추가하십시오.

ActivitySwipeDetector activitySwipeDetector = new ActivitySwipeDetector(this);
lowestLayout = (RelativeLayout)this.findViewById(R.id.lowestLayout);
lowestLayout.setOnTouchListener(activitySwipeDetector);

여기서 id.lowestLayout은 레이아웃 계층 구조에서 가장 낮은 뷰의 id.xxx이고 가장 낮은 레이아웃은 RelativeLayout으로 선언됩니다.

그리고 실제 활동 스 와이프 탐지기 클래스가 있습니다.

public class ActivitySwipeDetector implements View.OnTouchListener {

static final String logTag = "ActivitySwipeDetector";
private Activity activity;
static final int MIN_DISTANCE = 100;
private float downX, downY, upX, upY;

public ActivitySwipeDetector(Activity activity){
    this.activity = activity;
}

public void onRightSwipe(){
    Log.i(logTag, "RightToLeftSwipe!");
    activity.doSomething();
}

public void onLeftSwipe(){
    Log.i(logTag, "LeftToRightSwipe!");
    activity.doSomething();
}

public void onDownSwipe(){
    Log.i(logTag, "onTopToBottomSwipe!");
    activity.doSomething();
}

public void onUpSwipe(){
    Log.i(logTag, "onBottomToTopSwipe!");
    activity.doSomething();
}

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;

       // swipe horizontal?
        if(Math.abs(deltaX) > Math.abs(deltaY))
        {
            if(Math.abs(deltaX) > MIN_DISTANCE){
                // left or right
                if(deltaX > 0) { this.onRightSwipe(); return true; }
                if(deltaX < 0) { this.onLeftSwipe(); return true; }
            }
            else {
                    Log.i(logTag, "Horizontal Swipe was only " + Math.abs(deltaX) + " long, need at least " + MIN_DISTANCE);
                    return false; // We don't consume the event
            }
        }
        // swipe vertical?
        else 
        {
            if(Math.abs(deltaY) > MIN_DISTANCE){
                // top or down
                if(deltaY < 0) { this.onDownSwipe(); return true; }
                if(deltaY > 0) { this.onUpSwipe(); return true; }
            }
            else {
                    Log.i(logTag, "Vertical Swipe was only " + Math.abs(deltaX) + " long, need at least " + MIN_DISTANCE);
                    return false; // We don't consume the event
            }
        }

            return true;
        }
    }
    return false;
}

}

정말 잘 작동합니다!


1
이것은 실제로 나 제스처 기능을 적용하는 것이 훨씬 더 쉽게 만들고, "덜"배선 필요합니다 : D 감사 @Thomas
nemesisfixx을

5
깔끔한 유틸리티 클래스 등이 보이는 -하지만 난 당신에 ... 슬쩍 네 () 메소드는 인터페이스해야한다고 생각
누군가 어딘가에

2
이 리턴은 존재하지 않아야합니다 ( "이벤트를 소비하지 않습니다")? 세로 스크롤 기능을 비활성화합니다.
Marek Sebera

5
특히 onTouch () 메소드입니다. 첫째, 델타 X가 충분히 크지 않으면 델타 Y를 확인하지 않고 반환합니다. 결과는 왼쪽 오른쪽 스 와이프를 감지하지 못합니다. 둘째, 스 와이프를 찾지 못해도 true를 반환해서는 안됩니다. 셋째, 조치가 중단되면 true를 반환해서는 안됩니다. 이것은 onClick과 같은 다른 리스너가 작동하지 못하게합니다.
Jeffrey Blattman

1
@Piotr 참조를 보유한 객체가 활동 자체와 동일한 범위에있는 한 문제가되지 않습니다. 예를 들어 정적 멤버와 같이 활동보다 범위가 더 넓은 장소에서 활동에 대한 참조를 유지하면 문제가 발생합니다.
Jeffrey Blattman

94

Thomas Fankhauser의 솔루션을 약간 수정하고 수리했습니다.

전체 시스템은 SwipeInterfaceActivitySwipeDetector의 두 파일로 구성됩니다.


SwipeInterface.java

import android.view.View;

public interface SwipeInterface {

    public void bottom2top(View v);

    public void left2right(View v);

    public void right2left(View v);

    public void top2bottom(View v);

}

탐지기

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

public class ActivitySwipeDetector implements View.OnTouchListener {

    static final String logTag = "ActivitySwipeDetector";
    private SwipeInterface activity;
    static final int MIN_DISTANCE = 100;
    private float downX, downY, upX, upY;

    public ActivitySwipeDetector(SwipeInterface activity){
        this.activity = activity;
    }

    public void onRightToLeftSwipe(View v){
        Log.i(logTag, "RightToLeftSwipe!");
        activity.right2left(v);
    }

    public void onLeftToRightSwipe(View v){
        Log.i(logTag, "LeftToRightSwipe!");
        activity.left2right(v);
    }

    public void onTopToBottomSwipe(View v){
        Log.i(logTag, "onTopToBottomSwipe!");
        activity.top2bottom(v);
    }

    public void onBottomToTopSwipe(View v){
        Log.i(logTag, "onBottomToTopSwipe!");
        activity.bottom2top(v);
    }

    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;

            // swipe horizontal?
            if(Math.abs(deltaX) > MIN_DISTANCE){
                // left or right
                if(deltaX < 0) { this.onLeftToRightSwipe(v); return true; }
                if(deltaX > 0) { this.onRightToLeftSwipe(v); return true; }
            }
            else {
                Log.i(logTag, "Swipe was only " + Math.abs(deltaX) + " long, need at least " + MIN_DISTANCE);
            }

            // swipe vertical?
            if(Math.abs(deltaY) > MIN_DISTANCE){
                // top or down
                if(deltaY < 0) { this.onTopToBottomSwipe(v); return true; }
                if(deltaY > 0) { this.onBottomToTopSwipe(v); return true; }
            }
            else {
                Log.i(logTag, "Swipe was only " + Math.abs(deltaX) + " long, need at least " + MIN_DISTANCE);
                v.performClick();
            }
        }
        }
        return false;
    }

}

다음과 같이 사용됩니다.

ActivitySwipeDetector swipe = new ActivitySwipeDetector(this);
LinearLayout swipe_layout = (LinearLayout) findViewById(R.id.swipe_layout);
swipe_layout.setOnTouchListener(swipe);

그리고 구현시 SwipeInterface의Activity 메소드를 구현해야 하며 Swipe 이벤트 가 호출 된 뷰를 찾을 수 있습니다 .

@Override
public void left2right(View v) {
    switch(v.getId()){
        case R.id.swipe_layout:
            // do your stuff here
        break;
    }       
}

나는 약간 다시는 볼 수정 v.performClick();하지 동일한 뷰에 설정하면, OnClickListener를 이벤트를 소비에 사용되는,
마렉 Sebera

안녕하세요, 저는 초보자입니다.이 질문은 분명하거나 사소한 것이지만 대답 해주세요. 작성한 부분은 다음과 같이 사용됩니다. ActivitySwipeDetector swipe = new ActivitySwipeDetector (this); 이 진술은 MainActivity의 일부가 될 것입니다. 맞습니까? 그런 다음 "this"는 MainActivity의 활동이됩니다. 생성자는 SwipeInterface의 인스턴스를 가져옵니다. 친절하게 도와주세요. 고마워
Chocolava

@ Chocolava는 새로운 질문을 만듭니다. 댓글은 이와 같은 질문을하기에 좋은 장소가 아닙니다.
Marek Sebera

@MarekSebera 이것은 ScrollView & ListView에서 작동하지 않습니까? 그들을 처리하는 방법?
Duc Tran

@silentbang 다시, ​​이것은 그런 질문을 할 곳이 아닙니다. 새로운 질문 스레드를 만드십시오.
Marek Sebera

65

위의 스 와이프 동작 탐지기 코드는 매우 유용합니다! 그러나 (REL_SWIPE)절대 값이 아닌 다음 상대 값을 사용하여이 솔루션 밀도를 불가지론 적으로 만들 수 있습니다.(SWIPE_)

DisplayMetrics dm = getResources().getDisplayMetrics();

int REL_SWIPE_MIN_DISTANCE = (int)(SWIPE_MIN_DISTANCE * dm.densityDpi / 160.0f);
int REL_SWIPE_MAX_OFF_PATH = (int)(SWIPE_MAX_OFF_PATH * dm.densityDpi / 160.0f);
int REL_SWIPE_THRESHOLD_VELOCITY = (int)(SWIPE_THRESHOLD_VELOCITY * dm.densityDpi / 160.0f);

8
이것을 키우기 위해 +1. DensityMetrics.densityDpi는 API 4에 도입되었습니다. API 1과의 역 호환성을 위해서는 DensityMetrics.density를 대신 사용하십시오. 그러면 계산이 SWIPE_MIN_DISTANCE * dm.density로 변경됩니다.
Thane Anthem

160.0f는 어디서 얻었습니까?
IgorGanapolsky

developer.android.com/guide/practices/screens_support.html 밀도 독립 픽셀 (dp) dp 단위를 화면 픽셀로 변환하는 것은 간단합니다. px = dp * (dpi / 160)
paiego

나는 이것을 온통 찾고 있었다. 인터넷에있는 onFling ()의 예는 없습니다. 이로 인해 UX가 저하 될 수 있습니다. 감사!
Sandy

160.0f는 DP (밀도 독립 픽셀)의 기반이되는 표준 밀도 인 160 DPI에서 비롯된 것입니다. public static final int DENSITY_MEDIUM API 레벨 4에 추가됨 중간 밀도 화면을위한 표준 양자화 된 DPI. 상수 값 : 160 (0x000000a0)
paiego

35

Thomas FankhauserMarek Sebera가 제안한 내 솔루션 버전 (수직 스 와이프는 처리하지 않음) :

SwipeInterface.java

import android.view.View;

public interface SwipeInterface {

    public void onLeftToRight(View v);

    public void onRightToLeft(View v);
}

ActivitySwipeDetector.java

import android.content.Context;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;

public class ActivitySwipeDetector implements View.OnTouchListener {

    static final String logTag = "ActivitySwipeDetector";
    private SwipeInterface activity;
    private float downX, downY;
    private long timeDown;
    private final float MIN_DISTANCE;
    private final int VELOCITY;
    private final float MAX_OFF_PATH;

    public ActivitySwipeDetector(Context context, SwipeInterface activity){
        this.activity = activity;
        final ViewConfiguration vc = ViewConfiguration.get(context);
        DisplayMetrics dm = context.getResources().getDisplayMetrics();
        MIN_DISTANCE = vc.getScaledPagingTouchSlop() * dm.density;
        VELOCITY = vc.getScaledMinimumFlingVelocity();
        MAX_OFF_PATH = MIN_DISTANCE * 2;            
    }

    public void onRightToLeftSwipe(View v){
        Log.i(logTag, "RightToLeftSwipe!");
        activity.onRightToLeft(v);
    }

    public void onLeftToRightSwipe(View v){
        Log.i(logTag, "LeftToRightSwipe!");
        activity.onLeftToRight(v);
    }

    public boolean onTouch(View v, MotionEvent event) {
        switch(event.getAction()){
        case MotionEvent.ACTION_DOWN: {
            Log.d("onTouch", "ACTION_DOWN");
            timeDown = System.currentTimeMillis();
            downX = event.getX();
            downY = event.getY();
            return true;
        }
        case MotionEvent.ACTION_UP: {
            Log.d("onTouch", "ACTION_UP");
            long timeUp = System.currentTimeMillis();
            float upX = event.getX();
            float upY = event.getY();

            float deltaX = downX - upX;
            float absDeltaX = Math.abs(deltaX); 
            float deltaY = downY - upY;
            float absDeltaY = Math.abs(deltaY);

            long time = timeUp - timeDown;

            if (absDeltaY > MAX_OFF_PATH) {
                Log.i(logTag, String.format("absDeltaY=%.2f, MAX_OFF_PATH=%.2f", absDeltaY, MAX_OFF_PATH));
                return v.performClick();
            }

            final long M_SEC = 1000;
            if (absDeltaX > MIN_DISTANCE && absDeltaX > time * VELOCITY / M_SEC) {
                if(deltaX < 0) { this.onLeftToRightSwipe(v); return true; }
                if(deltaX > 0) { this.onRightToLeftSwipe(v); return true; }
            } else {
                Log.i(logTag, String.format("absDeltaX=%.2f, MIN_DISTANCE=%.2f, absDeltaX > MIN_DISTANCE=%b", absDeltaX, MIN_DISTANCE, (absDeltaX > MIN_DISTANCE)));
                Log.i(logTag, String.format("absDeltaX=%.2f, time=%d, VELOCITY=%d, time*VELOCITY/M_SEC=%d, absDeltaX > time * VELOCITY / M_SEC=%b", absDeltaX, time, VELOCITY, time * VELOCITY / M_SEC, (absDeltaX > time * VELOCITY / M_SEC)));
            }

        }
        }
        return false;
    }

}

누구든지 수업에 전화하는 방법을 알려주십시오. ActivitySwipeDetector 스 와이프 = 새 ActivitySwipeDetector (this); 분명히 그러한 생성자가 없으므로 오류가 발생합니다. ActivitySwipeDetector swipe = new ActivitySwipeDetector (this, null);
abdfahim

@AbdullahFahim ActivitySwipeDetector (this, YourActivity.this);
Anton Kashpor

25

이 질문은 일종의 구식이며 2011 년 7 월 Google 은 Android 1.6 이상에서 작동 하는 호환성 패키지 개정 3) 을 발표했습니다 ViewPager. 이 GestureListener질문에 대한 답변은 Android에서 매우 우아하지 않습니다. Android 갤러리에서 사진을 전환하거나 새로운 Play Market 앱에서보기를 전환하는 데 사용되는 코드를 찾고 있다면 분명히 코드 ViewPager입니다.

자세한 내용은 다음 링크를 참조하십시오.


ViewPager의 한 가지 문제점은 플링 제스처에 대한 거리 및 속도 매개 변수를 제어 할 수 없다는 것입니다.
almalkawi

갤러리에서는 ViewPager를 사용하지 않습니다.
Anthony

18

모든 제스처에 직접 사용할 수있는 내장 인터페이스가 있습니다
. 기본 레벨 사용자에 대한 설명은 다음과 같습니다. 여기에 이미지 설명을 입력하십시오 둘 다 다른 것을 선택하는 데 2 ​​가지 수입품이 있습니다. 여기에 이미지 설명을 입력하십시오 여기에 이미지 설명을 입력하십시오


1
그리고 다음 단계는 무엇입니까? 해당 수신기를 특정보기로 설정하는 방법은 무엇입니까? 이 견해가 단편의 일부라면 어떨까요?
Stan

16

ViewConfiguration을 사용할 웹과이 페이지에 대한 제안이 있습니다. getScaledTouchSlop () 에 대한 장치 스케일 값을 갖습니다 SWIPE_MIN_DISTANCE.

getScaledTouchSlop()스 와이프하지 않고 " 스크롤 임계 값"거리를 위한 것입니다 . 스크롤 임계 값 거리는 "페이지 간 스윙"임계 값 거리보다 작아야합니다. 예를 들어이 함수는 Samsung GS2에서 12 픽셀을 반환하며이 페이지에 인용 된 예제는 약 100 픽셀입니다.

API 레벨 8 (Android 2.2, Froyo)을 사용하면 getScaledPagingTouchSlop()페이지를 스 와이프 할 수 있습니다. 내 장치에서는 24 (픽셀)를 반환합니다. API 레벨 <8 인 경우 "2 * getScaledTouchSlop()"가 "표준"스 와이프 임계 값이어야한다고 생각합니다. 그러나 작은 화면을 가진 내 응용 프로그램 사용자는 너무 적 었다고 말했습니다 ... 내 응용 프로그램에서와 같이 세로로 스크롤하고 가로로 페이지를 변경할 수 있습니다. 제안 된 값을 사용하면 때때로 스크롤하는 대신 페이지가 변경됩니다.


13

또한 사소한 향상으로.

try / catch 블록의 주된 이유는 초기 이동시 e1이 null 일 수 있기 때문입니다. try / catch 외에도 null 및 return 테스트를 포함시킵니다. 다음과 유사

if (e1 == null || e2 == null) return false;
try {
...
} catch (Exception e) {}
return false;

12

여기에는 훌륭한 정보가 많이 있습니다. 불행히도이 많은 플링 처리 코드는 여러 응용 프로그램에 필수적이라고 생각할지라도 다양한 완료 상태의 여러 사이트에 흩어져 있습니다.

적절한 조건이 충족되는지 확인 하는 플링 리스너 를 만드는 데 시간이 걸렸습니다 . 플링이 페이지 플링의 임계 값을 충족하는지 확인하기 위해 더 많은 검사를 추가하는 페이지 플링 리스너 를 추가했습니다. 이 두 리스너를 사용하면 플링을 가로 또는 세로 축으로 쉽게 제한 할 수 있습니다. 이미지 슬라이딩보기 에서 사용되는 방식을 확인할 수 있습니다 . 저는 이곳 사람들이 대부분의 연구를 수행했음을 인정합니다.

이 마지막 며칠은 Android 코딩에 대한 나의 첫 찌르기를 나타냅니다. 앞으로 더 많은 것을 기대하십시오 .


두 손가락으로 스 와이프 제스처를 구현하고 싶습니다. 도와주세요!
Gaurav Arora

12

누군가가 실제 구현을 원한다면 맨 위에 두 가지 답변을 결합한 답변입니다.

package com.yourapplication;

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

public abstract class OnSwipeListener implements View.OnTouchListener {

    private final GestureDetector gestureDetector;

    public OnSwipeListener(Context context){
        gestureDetector = new GestureDetector(context, new OnSwipeGestureListener(context));
        gestureDetector.setIsLongpressEnabled(false);
    }

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

    private final class OnSwipeGestureListener extends GestureDetector.SimpleOnGestureListener {

        private final int minSwipeDelta;
        private final int minSwipeVelocity;
        private final int maxSwipeVelocity;

        private OnSwipeGestureListener(Context context) {
            ViewConfiguration configuration = ViewConfiguration.get(context);
            // We think a swipe scrolls a full page.
            //minSwipeDelta = configuration.getScaledTouchSlop();
            minSwipeDelta = configuration.getScaledPagingTouchSlop();
            minSwipeVelocity = configuration.getScaledMinimumFlingVelocity();
            maxSwipeVelocity = configuration.getScaledMaximumFlingVelocity();
        }

        @Override
        public boolean onDown(MotionEvent event) {
            // Return true because we want system to report subsequent events to us.
            return true;
        }

        // NOTE: see http://stackoverflow.com/questions/937313/android-basic-gesture-detection
        @Override
        public boolean onFling(MotionEvent event1, MotionEvent event2, float velocityX,
                               float velocityY) {

            boolean result = false;
            try {
                float deltaX = event2.getX() - event1.getX();
                float deltaY = event2.getY() - event1.getY();
                float absVelocityX = Math.abs(velocityX);
                float absVelocityY = Math.abs(velocityY);
                float absDeltaX = Math.abs(deltaX);
                float absDeltaY = Math.abs(deltaY);
                if (absDeltaX > absDeltaY) {
                    if (absDeltaX > minSwipeDelta && absVelocityX > minSwipeVelocity
                            && absVelocityX < maxSwipeVelocity) {
                        if (deltaX < 0) {
                            onSwipeLeft();
                        } else {
                            onSwipeRight();
                        }
                    }
                    result = true;
                } else if (absDeltaY > minSwipeDelta && absVelocityY > minSwipeVelocity
                        && absVelocityY < maxSwipeVelocity) {
                    if (deltaY < 0) {
                        onSwipeTop();
                    } else {
                        onSwipeBottom();
                    }
                }
                result = true;
            } catch (Exception e) {
                e.printStackTrace();
            }
            return result;
        }
    }

    public void onSwipeLeft() {}

    public void onSwipeRight() {}

    public void onSwipeTop() {}

    public void onSwipeBottom() {}
}

정말 좋은 구현 감사합니다. 또한 내가 확인하는 것이 좋습니다 것 absDeltaY > minSwipeDelta, absVelocityY > minSwipeVelocity, absVelocityY < maxSwipeVelocity경우에만 경우 minSwipeDelta ! = getScaledTouchSlop , minSwipeVelocity ! = getScaledMinimumFlingVelocity , maxSwipeVelocity ! = getScaledMaximumFlingVelocity , 즉 확인하는 경우에만 이러한 소위 "기본"(나는 getScaledTouchSlop, getScaledMinimumFlingVelocity, getScaledMaximumFlingVelocity을 의미) 값에 따라 크기를 조절하거나 변경하여 자신의 소원.
Elia12345

요점은에 따른 것입니다 소스 코드 , 언급 된 "기본"값이 이미 GestureDetector에 의해 확인되어, 그들은이 확인되는 경우 OnFling가 트리거 만의 경우에 발생하는 방식으로 (만 트리거 ACTION_UP하지, ACTION_MOVEACTION_POINTER_UP, 즉에만 완전히 실현 된 제스처의 결과). (다른 API 버전을 확인하지 않았으므로 의견을 보내 주셔서 감사합니다).
Elia12345

11

droidQuery 라이브러리를 사용하여 플링 , 클릭, 긴 클릭 및 사용자 정의 이벤트를 처리 할 수 있습니다 . 구현은 아래의 이전 답변을 기반으로하지만 droidQuery 는 매끄럽고 간단한 구문을 제공합니다.

//global variables    private boolean isSwiping = false;
private SwipeDetector.Direction swipeDirection = null;
private View v;//must be instantiated before next call.

//swipe-handling code
$.with(v).swipe(new Function() {
    @Override
    public void invoke($ droidQuery, Object... params) {
        if (params[0] == SwipeDetector.Direction.START)
            isSwiping = true;
        else if (params[0] == SwipeDetector.Direction.STOP) {
            if (isSwiping) {                    isSwiping = false;
                if (swipeDirection != null) {
                    switch(swipeDirection) {
                        case DOWN :                                //TODO: Down swipe complete, so do something
                            break;
                        case UP :
                            //TODO: Up swipe complete, so do something
                            break;
                        case LEFT :
                            //TODO: Left swipe complete, so do something
                            break;
                        case RIGHT :
                            //TODO: Right swipe complete, so do something
                            break;
                        default :                                break;
                    }
                }                }
        }
        else {
            swipeDirection = (SwipeDetector.Direction) params[0];
        }
    }
});

원래 답변

이 답변은 다른 답변의 구성 요소 조합을 사용합니다. SwipeDetector이벤트를 수신하기위한 내부 인터페이스가있는 클래스 로 구성됩니다 . 또한 스 와이프 이벤트와 감지 된 다른 이벤트 (예 : 클릭 또는 긴 클릭)를 허용하기 위해 의 방법 RelativeLayout을 재정의하는 방법을 보여줍니다 .ViewonTouch

스 와이프 검출기

package self.philbrown;

import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;

/**
 * Detect Swipes on a per-view basis. Based on original code by Thomas Fankhauser on StackOverflow.com,
 * with adaptations by other authors (see link).
 * @author Phil Brown
 * @see <a href="http://stackoverflow.com/questions/937313/android-basic-gesture-detection">android-basic-gesture-detection</a>
 */
public class SwipeDetector implements View.OnTouchListener
{
    /**
     * The minimum distance a finger must travel in order to register a swipe event.
     */
    private int minSwipeDistance;

    /** Maintains a reference to the first detected down touch event. */
    private float downX, downY;

    /** Maintains a reference to the first detected up touch event. */
    private float upX, upY;

    /** provides access to size and dimension contants */
    private ViewConfiguration config;

    /**
     * provides callbacks to a listener class for various swipe gestures.
     */
    private SwipeListener listener;

    public SwipeDetector(SwipeListener listener)
    {
        this.listener = listener;
    }


    /**
     * {@inheritDoc}
     */
    public boolean onTouch(View v, MotionEvent event)
    {
        if (config == null)
        {
                config = ViewConfiguration.get(v.getContext());
                minSwipeDistance = config.getScaledTouchSlop();
        }

        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;

            // swipe horizontal?
            if(Math.abs(deltaX) > minSwipeDistance)
            {
                // left or right
                if (deltaX < 0)
                {
                        if (listener != null)
                        {
                                listener.onRightSwipe(v);
                                return true;
                        }
                }
                if (deltaX > 0)
                {
                        if (listener != null)
                        {
                                listener.onLeftSwipe(v);
                                return true;
                        }
                }
            }

            // swipe vertical?
            if(Math.abs(deltaY) > minSwipeDistance)
            {
                // top or down
                if (deltaY < 0)
                {
                        if (listener != null)
                        {
                                listener.onDownSwipe(v);
                                return true;
                        }
                }
                if (deltaY > 0)
                {
                        if (listener != null)
                        {
                                listener.onUpSwipe(v);
                                return true;
                        }
                }
            }
        }
        return false;
    }

    /**
     * Provides callbacks to a registered listener for swipe events in {@link SwipeDetector}
     * @author Phil Brown
     */
    public interface SwipeListener
    {
        /** Callback for registering a new swipe motion from the bottom of the view toward its top. */
        public void onUpSwipe(View v);
        /** Callback for registering a new swipe motion from the left of the view toward its right. */
        public void onRightSwipe(View v);
        /** Callback for registering a new swipe motion from the right of the view toward its left. */
        public void onLeftSwipe(View v);
        /** Callback for registering a new swipe motion from the top of the view toward its bottom. */
        public void onDownSwipe(View v);
    }
}

스 와이프 인터셉터보기

package self.philbrown;

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

import com.npeinc.module_NPECore.model.SwipeDetector;
import com.npeinc.module_NPECore.model.SwipeDetector.SwipeListener;

/**
 * View subclass used for handling all touches (swipes and others)
 * @author Phil Brown
 */
public class SwipeInterceptorView extends RelativeLayout
{
    private SwipeDetector swiper = null;

    public void setSwipeListener(SwipeListener listener)
    {
        if (swiper == null)
            swiper = new SwipeDetector(listener);
    }

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

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

    public SwipeInterceptorView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    public boolean onTouchEvent(MotionEvent e)
    {
        boolean swipe = false, touch = false;
        if (swiper != null)
            swipe = swiper.onTouch(this, e);
        touch = super.onTouchEvent(e);
        return swipe || touch;
    }
}

1
클릭 가능한 요소가 포함 된보기에서 이것을 구현하려고했습니다. 스 와이프가 클릭 가능한 요소 (예 : onItemClick 리스너가 등록 된 목록보기)를 시작하면 onTouchEvent가 호출되지 않습니다. 따라서 사용자가 클릭 가능한 요소를 스 와이프하면 시작할 수 없으며 불행히도 클릭 가능한 요소는 약간의 시야 공간을 차지하고 여전히 스 와이프 지원을 원 하므로이 문제를 해결하는 방법을 찾으려고 노력하고 있습니다. 전체보기. 스 와이프가 클릭 가능한 요소를 시작하지 않으면 완벽하게 작동합니다.
Lo-Tan

당신의 클릭 가능한 항목이 아이 뷰, 따라서 있기 때문에 소호 - 탄 @이 발생 위에SwipeInterceptorView의 클릭이 먼저 처리되도록. 을 구현하여 고유 한 클릭 메커니즘을 구현하여이 문제를 해결 onTouchListener하거나, 해결 방법으로 클릭 대신 긴 클릭을들을 수 있습니다 (참조 View.setOnLongClickListener).
Phil

나는 실제로 그 순간에 그것을 시도하고 있습니다. 또는 드래그를 시작하면 클릭 이벤트를 취소 할 수 있습니다. 감사합니다.
Lo-Tan

한 가지 해결책은 스 와이프 감지기를 앱의 모든보기에 연결하는 것입니다. 또 다른 구현하는 것입니다 onInterceptTouchEvent을 당신의 SwipeInterceptorView에.
Edward Falk

7

답변이 너무 늦다는 것을 알고 있지만 여전히 ListView대한 스 와이프 감지를 ListView 항목에 스 와이프 터치 리스너 를 사용하는 방법으로 게시 하고 있습니다 .

굴절 : 해충 구제 13 (이 페이지의 답변 중 하나)

하나의 ActivitySwipeDetector.class를 작성하십시오.

package com.example.wocketapp;

import android.content.Context;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;

public class ActivitySwipeDetector implements View.OnTouchListener 
{
    static final String logTag = "SwipeDetector";
    private SwipeInterface activity;
    private float downX, downY;
    private long timeDown;
    private final float MIN_DISTANCE;
    private final int VELOCITY;
    private final float MAX_OFF_PATH;

    public ActivitySwipeDetector(Context context, SwipeInterface activity)
    {
        this.activity = activity;
        final ViewConfiguration vc = ViewConfiguration.get(context);
        DisplayMetrics dm = context.getResources().getDisplayMetrics();
        MIN_DISTANCE = vc.getScaledPagingTouchSlop() * dm.density;
        VELOCITY = vc.getScaledMinimumFlingVelocity();
        MAX_OFF_PATH = MIN_DISTANCE * 2;
    }

    public void onRightToLeftSwipe(View v) 
    {
        Log.i(logTag, "RightToLeftSwipe!");
        activity.onRightToLeft(v);
    }

    public void onLeftToRightSwipe(View v) 
    {
        Log.i(logTag, "LeftToRightSwipe!");
        activity.onLeftToRight(v);
    }

    public boolean onTouch(View v, MotionEvent event) 
    {
        switch (event.getAction()) 
        {
            case MotionEvent.ACTION_DOWN:
            {
                Log.d("onTouch", "ACTION_DOWN");
                timeDown = System.currentTimeMillis();
                downX = event.getX();
                downY = event.getY();
                v.getParent().requestDisallowInterceptTouchEvent(false);
                return true;
            }

        case MotionEvent.ACTION_MOVE:
            {
                float y_up = event.getY();
                float deltaY = y_up - downY;
                float absDeltaYMove = Math.abs(deltaY);

                if (absDeltaYMove > 60) 
                {
                    v.getParent().requestDisallowInterceptTouchEvent(false);
                } 
                else
                {
                    v.getParent().requestDisallowInterceptTouchEvent(true);
                }
            }

            break;

            case MotionEvent.ACTION_UP: 
            {
                Log.d("onTouch", "ACTION_UP");
                long timeUp = System.currentTimeMillis();
                float upX = event.getX();
                float upY = event.getY();

                float deltaX = downX - upX;
                float absDeltaX = Math.abs(deltaX);
                float deltaY = downY - upY;
                float absDeltaY = Math.abs(deltaY);

                long time = timeUp - timeDown;

                if (absDeltaY > MAX_OFF_PATH) 
                {
                    Log.e(logTag, String.format(
                            "absDeltaY=%.2f, MAX_OFF_PATH=%.2f", absDeltaY,
                            MAX_OFF_PATH));
                    return v.performClick();
                }

                final long M_SEC = 1000;
                if (absDeltaX > MIN_DISTANCE && absDeltaX > time * VELOCITY / M_SEC) 
                {
                     v.getParent().requestDisallowInterceptTouchEvent(true);
                    if (deltaX < 0) 
                    {
                        this.onLeftToRightSwipe(v);
                        return true;
                    }
                    if (deltaX > 0) 
                    {
                        this.onRightToLeftSwipe(v);
                        return true;
                    }
                }
                else 
                {
                    Log.i(logTag,
                            String.format(
                                    "absDeltaX=%.2f, MIN_DISTANCE=%.2f, absDeltaX > MIN_DISTANCE=%b",
                                    absDeltaX, MIN_DISTANCE,
                                    (absDeltaX > MIN_DISTANCE)));
                    Log.i(logTag,
                            String.format(
                                    "absDeltaX=%.2f, time=%d, VELOCITY=%d, time*VELOCITY/M_SEC=%d, absDeltaX > time * VELOCITY / M_SEC=%b",
                                    absDeltaX, time, VELOCITY, time * VELOCITY
                                            / M_SEC, (absDeltaX > time * VELOCITY
                                            / M_SEC)));
                }

                 v.getParent().requestDisallowInterceptTouchEvent(false);

            }
        }
        return false;
    }
    public interface SwipeInterface 
    {

        public void onLeftToRight(View v);

        public void onRightToLeft(View v);
    }

}

다음과 같이 활동 클래스에서 호출하십시오.

yourLayout.setOnTouchListener(new ActivitySwipeDetector(this, your_activity.this));

그리고 두 개의 @override 메소드를 제공 하는 SwipeInterface구현 하는 것을 잊지 마십시오 .

    @Override
    public void onLeftToRight(View v) 
    {
        Log.e("TAG", "L to R");
    }

    @Override
    public void onRightToLeft(View v) 
    {
        Log.e("TAG", "R to L");
    }

나는 MAX_OFF_PATH = 5 * vc.getScaledPagingTouchSlop()약간의 호에서 자연스럽게 움직이는 엄지 손가락으로 더 편안 하다는 것을 알았습니다 .
qix

4

제스처는 터치 스크린과 사용자 간의 상호 작용을 유발하는 미묘한 동작입니다. 화면에서 첫 번째 터치와 마지막 손가락이 표면을 떠날 때까지의 시간 동안 지속됩니다.

Android는 GestureDetector 라는 클래스를 제공합니다.이 제스처를 사용 하면 아래로 누르고 위로 올리거나, 세로로 가로로 스 와이프하거나 (fling), 길게 짧게 누르거나, 두 번 누르는 등의 일반적인 제스처를 감지 할 수 있습니다 . 청취자를 첨부하십시오.

Activity 클래스가 GestureDetector.OnDoubleTapListener (더블 탭 제스처 감지 용) 및 GestureDetector.OnGestureListener 인터페이스 를 구현하고 모든 추상 메서드 를 구현하도록합니다. https://developer.android.com/training/gestures/detector.html을 방문 하십시오 . 예의

데모 테스트 용. 제스처 탐지기


4

별도의 클래스를 만들거나 코드를 복잡하게
만들지 않으려면 OnTouchListener 내에 GestureDetector 변수를 만들고 코드를 더 쉽게 만들 수 있습니다.

namVyuVar는 리스터를 설정해야하는보기의 이름 일 수 있습니다.

namVyuVar.setOnTouchListener(new View.OnTouchListener()
{
    @Override
    public boolean onTouch(View view, MotionEvent MsnEvtPsgVal)
    {
        flingActionVar.onTouchEvent(MsnEvtPsgVal);
        return true;
    }

    GestureDetector flingActionVar = new GestureDetector(getApplicationContext(), new GestureDetector.SimpleOnGestureListener()
    {
        private static final int flingActionMinDstVac = 120;
        private static final int flingActionMinSpdVac = 200;

        @Override
        public boolean onFling(MotionEvent fstMsnEvtPsgVal, MotionEvent lstMsnEvtPsgVal, float flingActionXcoSpdPsgVal, float flingActionYcoSpdPsgVal)
        {
            if(fstMsnEvtPsgVal.getX() - lstMsnEvtPsgVal.getX() > flingActionMinDstVac && Math.abs(flingActionXcoSpdPsgVal) > flingActionMinSpdVac)
            {
                // TskTdo :=> On Right to Left fling

                return false;
            }
            else if (lstMsnEvtPsgVal.getX() - fstMsnEvtPsgVal.getX() > flingActionMinDstVac && Math.abs(flingActionXcoSpdPsgVal) > flingActionMinSpdVac)
            {
                // TskTdo :=> On Left to Right fling

                return false;
            }

            if(fstMsnEvtPsgVal.getY() - lstMsnEvtPsgVal.getY() > flingActionMinDstVac && Math.abs(flingActionYcoSpdPsgVal) > flingActionMinSpdVac)
            {
                // TskTdo :=> On Bottom to Top fling

                return false;
            }
            else if (lstMsnEvtPsgVal.getY() - fstMsnEvtPsgVal.getY() > flingActionMinDstVac && Math.abs(flingActionYcoSpdPsgVal) > flingActionMinSpdVac)
            {
                // TskTdo :=> On Top to Bottom fling

                return false;
            }
            return false;
        }
    });
});

3

모두에게 : MotionEvent.ACTION_CANCEL 사례를 잊지 마십시오 .

ACTION_UP없이 30 % 스 와이프하여 호출합니다.

이 경우 ACTION_UP과 같습니다.


2

좀 더 일반적인 Class를 만들었고 Tomas 클래스를 가져 와서 Activity 또는 Fragment에 이벤트를 보내는 인터페이스를 추가했습니다. 생성자에 리스너를 등록하므로 인터페이스를 구현하지 않으면 ClassCastException이 발생합니다. 인터페이스는 클래스에 정의 된 4 개의 최종 int 중 하나를 반환하고 활성화 된 뷰를 반환합니다.

import android.app.Activity;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;

public class SwipeDetector implements View.OnTouchListener{

    static final int MIN_DISTANCE = 100;
    private float downX, downY, upX, upY;
    public final static int RIGHT_TO_LEFT=1;
    public final static int LEFT_TO_RIGHT=2;
    public final static int TOP_TO_BOTTOM=3;
    public final static int BOTTOM_TO_TOP=4;
    private View v;

    private onSwipeEvent swipeEventListener;


    public SwipeDetector(Activity activity,View v){
        try{
            swipeEventListener=(onSwipeEvent)activity;
        }
        catch(ClassCastException e)
        {
            Log.e("ClassCastException",activity.toString()+" must implement SwipeDetector.onSwipeEvent");
        } 
        this.v=v;
    }
    public SwipeDetector(Fragment fragment,View v){
        try{
            swipeEventListener=(onSwipeEvent)fragment;
        }
        catch(ClassCastException e)
        {
            Log.e("ClassCastException",fragment.toString()+" must implement SwipeDetector.onSwipeEvent");
        } 
        this.v=v;
    }


    public void onRightToLeftSwipe(){   
        swipeEventListener.SwipeEventDetected(v,RIGHT_TO_LEFT);
    }

    public void onLeftToRightSwipe(){   
        swipeEventListener.SwipeEventDetected(v,LEFT_TO_RIGHT);
    }

    public void onTopToBottomSwipe(){   
        swipeEventListener.SwipeEventDetected(v,TOP_TO_BOTTOM);
    }

    public void onBottomToTopSwipe(){
        swipeEventListener.SwipeEventDetected(v,BOTTOM_TO_TOP);
    }

    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 , int SwipeType);
    }

}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.