android لتعليم الكشف عن حركة قذف على تخطيط الشبكة




سلمان خان تربوي (15)

أرغب في الحصول على كشف الإيماءة في العمل في تطبيق Android.

ما لدي هو GridLayout التي تحتوي على 9 ImageView الصورة. يمكن العثور على المصدر هنا: تخطيط شبكة Romain Guys .

هذا الملف الذي ألتقطه هو من تطبيق Romain Guy's Photostream وقد تم تكييفه قليلاً.

في حالة النقر البسيطة ، أحتاج فقط إلى تعيين onClickListener لكل ImageView أقوم بإضافته ليكون activity الرئيسي الذي يطبق View.OnClickListener . يبدو أكثر تعقيدًا لتنفيذ شيء يعترف fling . أفترض هذا لأنه قد تمتد views ؟

  • إذا كان نشاطي يطبق OnGestureListener لا أعرف كيفية تعيين ذلك كمستمع لفتة Grid أو طريقة عرض Image التي أقوم بإضافتها.

    public class SelectFilterActivity extends Activity implements
       View.OnClickListener, OnGestureListener { ...
    
  • إذا كان نشاطي ينفذ OnTouchListener فليس لدي طريقة onFling (يوجد به حدثان كمعلمات يسمحان لي بتحديد ما إذا كان القذف جدير بالملاحظة).

    public class SelectFilterActivity extends Activity implements
        View.OnClickListener, OnTouchListener { ...
    
  • إذا قمت بإنشاء View مخصصة ، مثل GestureImageView التي تمتد إلى ImageView لا أعرف كيفية معرفة النشاط الذي حدث fling من العرض. في أي حال ، حاولت ذلك ولم يتم استدعاء الأساليب عندما لمست الشاشة.

أنا حقا بحاجة فقط إلى مثال ملموس لهذا العمل عبر وجهات النظر. ماذا ومتى وكيف أعلق هذا 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;
        }
    }
});

هل من الممكن وضع عرض شفاف أعلى الشاشة لالتقاط الصور؟

إذا اخترت عدم inflate مشاهدات صورة طفلي من XML ، هل يمكنني تمرير GestureDetector كمعلمة منشئ إلى فئة فرعية جديدة من ImageView أقوم بإنشائها؟

هذا هو النشاط البسيط للغاية الذي أحاول الحصول عليه من أجل الكشف عن fling : من SelectFilterActivity (مقتبس من فوتوستريم) .

لقد كنت أبحث في هذه المصادر:

لم ينجح شيء بالنسبة لي حتى الآن وكنت آمل في بعض المؤشرات.


هناك الكثير من المعلومات الممتازة هنا. لسوء الحظ ، فإن الكثير من شفرة معالجة fling هذه مبعثرة في مواقع مختلفة في حالات إكمال مختلفة ، على الرغم من أن المرء يعتقد أن هذا ضروري للعديد من التطبيقات.

لقد استغرقت الوقت لإنشاء مستمع قارنة يتحقق من استيفاء الشروط المناسبة. لقد قمت بإضافة صفحة مستمع يضيء يضيف المزيد من الشيكات للتأكد من أن الفلاتر تستوفي الحد الأقصى لصفحات الصفحة. يسمح لك كل من هؤلاء المستمعين بتقييد الصواعق بسهولة على المحور الأفقي أو الرأسي. يمكنك معرفة كيفية استخدامه في عرض الصور المنزلقة . أقر بأن الناس هنا قاموا بمعظم الأبحاث - لقد قمت بتجميعها في مكتبة قابلة للاستخدام.

تمثل هذه الأيام القليلة الماضية طعمي الأول في الترميز على Android ؛ نتوقع المزيد في المستقبل.


أفعل ذلك مختلفة قليلا ، وكتب فئة كشف إضافية التي تنفذ View.onTouchListener

onCreate هو ببساطة إضافته إلى تخطيط أدنى مثل هذا:

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

حيث id.lowestLayout هو id.xxx لأقل عرض في التسلسل الهرمي للتخطيط ويتم تعريف lessLayout على أنه 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;
}

}

يعمل جيد حقا بالنسبة لي!


شكراً لـ 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' المنشور أمر اختياري ولكن يتم تشجيعه.


يمكنك استخدام مكتبة droidQuery للتعامل مع 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 onTouch كيفية تجاوز View onTouch طريقة العرض للسماح بكل من أحداث التمرير وغيرها من الأحداث التي تم اكتشافها (مثل النقرات أو النقرات الطويلة).

SwipeDetector

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 .com,
 * with adaptations by other authors (see link).
 * @author Phil Brown
 * @see <a href="http://.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;
    }
}

أيضا كتحسين طفيف.

السبب الرئيسي لكتلة try / catch هو أن e1 قد تكون فارغة للحركة الأولية. بالإضافة إلى المحاولة / المصيد ، قم بتضمين اختبار للقيمة والعودة. على غرار ما يلي

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

If you dont like to create a separate class or make code complex,
You can just create a GestureDetector variable inside OnTouchListener and make your code more easier

namVyuVar can be any name of the View on which you need to set the listner

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

Gestures are those subtle motions to trigger interactions between the touch screen and the user. It lasts for the time between the first touch on the screen to the point when the last finger leaves the surface.

Android provides us with a class called GestureDetector using which we can detect common gestures like tapping down and up, swiping vertically and horizontally (fling), long and short press, double taps, etc . and attach listeners to them.

Make our Activity class implement GestureDetector.OnDoubleTapListener (for double tap gesture detection) and GestureDetector.OnGestureListener interfaces and implement all the abstract methods.For more info. you may visit https://developer.android.com/training/gestures/detector.html . Courtesy

For Demo Test. GestureDetectorDemo


To all: don't forget about case MotionEvent.ACTION_CANCEL:

it calls in 30% swipes without ACTION_UP

and its equal to ACTION_UP in this case


روايتي من الحل الذي اقترحه توماس فانكهاوزر وماريك سيبيرا (لا يتعامل مع الضربات الرأسية):

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

}

هناك بعض العروض على الويب (وهذه الصفحة) لاستخدام ViewConfiguration. getScaledTouchSlop () للحصول على قيمة SWIPE_MIN_DISTANCE الجهاز لـ SWIPE_MIN_DISTANCE .

getScaledTouchSlop() أجل "عتبة التمرير " المسافة لا swipe. يجب أن تكون مسافة عتبة التمرير أصغر من مسافة عتبة "التأرجح بين الصفحة". على سبيل المثال ، تقوم هذه الدالة بإرجاع 12 بكسل على Samsung GS2 الخاص بي ، والأمثلة المعروضة في هذه الصفحة حوالي 100 بكسل.

باستخدام API Level 8 (Android 2.2، Froyo) ، يمكنك الحصول على getScaledPagingTouchSlop() ، الذي يهدف إلى getScaledPagingTouchSlop() الصفحة. على جهازي ، تقوم بإرجاع 24 (بكسل). لذلك إذا كنت على مستوى API <8 ، فأعتقد أن "2 * getScaledTouchSlop() " يجب أن يكون حد التمرير "القياسي". لكن مستخدمي تطبيقي مع الشاشات الصغيرة أخبروني أنه كان عددًا قليلاً جدًا ... كما في طلبي ، يمكنك التمرير رأسيًا وتغيير الصفحة أفقيًا. باستخدام القيمة المقترحة ، يقومون أحيانًا بتغيير الصفحة بدلاً من التمرير.


أحد الإجابات المذكورة أعلاه يشير إلى التعامل مع كثافة البكسل المختلفة لكنه يشير إلى حساب معلمات التمرير يدويًا. تجدر الإشارة إلى أنه يمكنك بالفعل الحصول على قيم ViewConfiguration ومعقولة من النظام باستخدام فئة ViewConfiguration :

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)

لاحظت أن استخدام هذه القيم يؤدي إلى "شعور" fling ليكون أكثر تناسقًا بين التطبيق وبقية النظام.


هذه هي الإجابة المدمجة للإجابتين في الأعلى ، إذا كان أي شخص يريد تطبيقًا عمليًا.

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://.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() {}
}

رمز الكاشف لفتة التمرير أعلاه مفيد جدًا! ومع ذلك ، قد ترغب في جعل كثافة الحل هذه (REL_SWIPE) باستخدام القيم النسبية التالية (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);

هذا السؤال قديم نوعًا ما وفي يوليو 2011 أصدرت Google حزمة التوافق ، المراجعة 3) والتي تتضمن ViewPager الذي يعمل مع Android 1.6 إلى الأعلى. لا GestureListener إجابات GestureListener المنشورة لهذا السؤال أنيقة للغاية على Android. إذا كنت تبحث عن الرمز المستخدم في التبديل بين الصور في Android Gallery أو تبديل طرق العرض في تطبيق Play Market الجديد ، فمن المؤكد أنه ViewPager .

إليك بعض الروابط لمزيد من المعلومات:


هناك واجهة مدمجة يمكنك استخدامها مباشرة لجميع الإيماءات:
هذا توضيح لمستخدم المستوى الأساسي: هناك 2 الواردات كن حذرا في اختيار أن كلاهما مختلفة







gesture-recognition