将 Fling 手势添加到图像视图 - Android

Posted

技术标签:

【中文标题】将 Fling 手势添加到图像视图 - Android【英文标题】:Adding Fling Gesture to an image view - Android 【发布时间】:2011-05-05 03:13:38 【问题描述】:

好的,我一直在这里引用代码:Fling gesture detection on grid layout

但就是不能让它工作。在我的主要活动中,我定义了一个简单的图像。我想检测图像上的一扔。下面是我的代码。底部的 onclick 方法是空的。是不是因为这个?我将其留空,因为在其他代码示例中它不是我想要的。我只想弹出一个简单的吐司,说向右或向左。

public class GestureRightLeft extends Activity implements OnClickListener  

    ImageView peek;

    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
    public void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        peek =(ImageView) findViewById(R.id.peek);
        peek.setImageResource(R.drawable.bluestrip);

        gestureDetector = new GestureDetector(new MyGestureDetector());
        gestureListener = new View.OnTouchListener() 
            public boolean onTouch(View v, MotionEvent event) 
                if (gestureDetector.onTouchEvent(event)) 
                    return true;
                
                return false;
            
        ;
    

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

    @Override
    public void onClick(View v) 

【问题讨论】:

另见How to add a gesture detector to a view in android 【参考方案1】:

这是我能想到的最简单的 flinger 工作版本。 实际上,您可以将它绑定到任何组件,而不仅仅是 ImageView。

public class MyActivity extends Activity 
    private void onCreate() 
        final GestureDetector gdt = new GestureDetector(new GestureListener());
        final ImageView imageView  = (ImageView) findViewById(R.id.image_view);
        imageView.setOnTouchListener(new OnTouchListener() 
            @Override
            public boolean onTouch(final View view, final MotionEvent event) 
                gdt.onTouchEvent(event);
                return true;
            
        );
                   

    private static final int SWIPE_MIN_DISTANCE = 120;
    private static final int SWIPE_THRESHOLD_VELOCITY = 200;

    private class GestureListener extends SimpleOnGestureListener 
        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) 
            if(e1.getX() - e2.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) 
                return false; // Right to left
              else if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) 
                return false; // Left to right
            

            if(e1.getY() - e2.getY() > SWIPE_MIN_DISTANCE && Math.abs(velocityY) > SWIPE_THRESHOLD_VELOCITY) 
                return false; // Bottom to top
              else if (e2.getY() - e1.getY() > SWIPE_MIN_DISTANCE && Math.abs(velocityY) > SWIPE_THRESHOLD_VELOCITY) 
                return false; // Top to bottom
            
            return false;
        
    

虽然 onClickListener 没有活动(如果您不需要捕获任何 onclick 操作) 它不仅可以捕获水平,还可以捕获垂直(如果不需要,只需删除垂直部分),并且水平滑动具有优先级,如您所见。 在方法返回的地方(我的 cmets 所在的地方)只需调用您的方法或其他任何方法 :)

【讨论】:

改用final GestureDetector gdt = GestureDetector(this, new GestureListener());,根据developer.android.com/reference/android/view/… 这更像是分页。可以在这里找到一个很好的示例:developer.android.com/training/custom-views/… @Radu,阅读@Snicolas 提供的链接。您必须覆盖 onDown 并返回 true。 我不完全理解代码,但 IMO 这不可能是正确的,因为 onFling 在所有执行路径中都返回 false【参考方案2】:

试试这个

imageView.setOnTouchListener(new View.OnTouchListener() 

        @Override
        public boolean onTouch(View v, MotionEvent event) 
            if (gestureDetector.onTouchEvent(event)) 
                return false;
            
            return true;
        
  );

【讨论】:

+1 谢谢老兄它对我有用.. 我返回 true 而不是 false 。现在我的问题解决了 @contactmeandroid 里面如果条件我也返回 true;它对我有用。 @Ganapathy 它有效,但在滑动时我想拖动图像但我无法做到 android 中的拖放框架可能会对您有所帮助。developer.android.com/guide/topics/ui/drag-drop.html 简化返回 !mGestureDetector.onTouchEvent(motionEvent);【参考方案3】:
imageView.setOnTouchListener(new View.OnTouchListener() 

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

【讨论】:

【参考方案4】:

一些前置条件

1) setonClick 方法

image.setOnClickListener(this);

2) 在 onTouch() 中设置手势检测

image.setOnTouchListener(new OnTouchListener() 
    GestureDetector gestureDetector = new GestureDetector(new SwingGestureDetection((mContext),image,a));
    @Override
    public boolean onTouch(View v, MotionEvent event) 
        return gestureDetector.onTouchEvent(event);
    
);

3) 创建 SwingGestureDetection 类并实现所有方法

@Override
public boolean onFling(MotionEvent start, MotionEvent finish, float arg2,float arg3) 
    if (start.getRawX() < finish.getRawX()) 
        System.out.println("next...swing");
     else 
        System.out.println("previois...swing");
    

4) 在构造函数中传递您的图像视图

public SwingGestureDetection(Context con,ImageView image,int pos) 
    mContext = con;
    this.image = image;
    this.position = pos;

这对我来说是完美的工作。如果有任何疑问,请发表评论。

【讨论】:

【参考方案5】:

尝试阅读: http://illusionsandroid.blogspot.com/2011/05/adding-fling-gesture-listener-to-view.html

它允许您将活动实现与自定义侦听器分开。这只是对 Alex Orlov 报告的解决方案的重构

【讨论】:

【参考方案6】:

如果您不喜欢创建单独的类或使代码复杂, 你可以在 OnTouchListener 中创建一个 GestureDetector 变量,让你的代码更简单

namVyuVar 可以是任何需要设置listner的View的名字

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

【讨论】:

【参考方案7】:

如果您正在寻找像 ImageView.setOnGestureListener 这样的方法,则没有。你可以去看看Android源代码。您最好的选择是在 View 对象的 onTouch() 中处理它。

这是我能做的最简单的 GestureDetector。

我有一个名为 GenesMotionDetector.java 的类。这是它的代码:

package gene.com.motioneventssample;

import android.app.Activity;
import android.os.Bundle;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

public class GenesMotionDetector extends Activity implements GestureDetector.OnGestureListener 
    private GestureDetector gestureScanner;

    @Override
    public void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.nothing);
        gestureScanner= new GestureDetector(getBaseContext(),this);
    

    @Override
    public boolean onTouchEvent(MotionEvent me) 
        System.out.println("Inside onTouchEvent() of GenesMotionDetector.java");
        return gestureScanner.onTouchEvent(me);
    

    @Override
    public boolean onDown(MotionEvent e) 
        System.out.println("Inside onDown() of GenesMotionDetector.java");
        return true;
    

    @Override
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) 
        System.out.println("Inside onFling() of GenesMotionDetector.java");
        return true;
    

    @Override
    public void onLongPress(MotionEvent e) 
        System.out.println("Inside onLongPress() of GenesMotionDetector.java");
    

    @Override
    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) 
        System.out.println("Inside onScroll() of GenesMotionDetector.java");
        return true;
    

    @Override
    public void onShowPress(MotionEvent e) 
        System.out.println("Inside onShowPress() of GenesMotionDetector.java");
    

    @Override
    public boolean onSingleTapUp(MotionEvent e) 
        System.out.println("Inside onSingleTapUp() of GenesMotionDetector.java");
        return true;
    

该类对应的 XML 布局文件是 nothing.xml。这是它的代码:

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/screen"
    android:orientation="vertical" android:layout_
    android:layout_>

    <TextView
        android:id="@+id/text"
        android:background="#17528c"
        android:text="testing"
        android:layout_
        android:layout_ />

    <ImageView
        android:id="@+id/image"
        android:background="#f8af20"
        android:layout_
        android:layout_ />
</LinearLayout>

现在,使用我可以(从上面)制作的最简单的 GestureDetector 并根据您的需要对其进行修改,我得到了:

package gene.com.motioneventssample;

import android.app.Activity;
import android.os.Bundle;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.widget.ImageView;

public class GenesMotionDetector3 extends Activity implements GestureDetector.OnGestureListener 
    private GestureDetector gestureScanner;
    ImageView mView3;

    View.OnTouchListener gestureListener;
    MotionEvent initialME, finalME;
    private VelocityTracker mVelocityTracker = null;

    @Override
    public void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.nothing);


        mView3 = (ImageView) findViewById(R.id.image);

        // Gesture detection
        gestureScanner = new GestureDetector(getBaseContext(), this);

        gestureListener = new View.OnTouchListener() 
            @Override
            public boolean onTouch(View v, MotionEvent event) 
                switch(event.getAction())
                    case MotionEvent.ACTION_DOWN:
                        initialME= event;

                        if(mVelocityTracker == null) 
                            // Retrieve a new VelocityTracker object to watch the velocity of a motion.
                            mVelocityTracker = VelocityTracker.obtain();
                        
                        else 
                            // Reset the velocity tracker back to its initial state.
                            mVelocityTracker.clear();
                        
                        // Add a user's movement to the tracker.
                        mVelocityTracker.addMovement(event);

                        break;
                    case MotionEvent.ACTION_MOVE:
                        mVelocityTracker.addMovement(event);
                        // When you want to determine the velocity, call
                        // computeCurrentVelocity(). Then call getXVelocity()
                        // and getYVelocity() to retrieve the velocity for each pointer ID.
                        mVelocityTracker.computeCurrentVelocity(1000);
                        break;
                    case MotionEvent.ACTION_UP:
                        finalME=event;
                        break;
                    case MotionEvent.ACTION_CANCEL:
                        // Return a VelocityTracker object back to be re-used by others.
                        mVelocityTracker.recycle();
                        break;
                
                return onFling(initialME, finalME, mVelocityTracker.getXVelocity(), mVelocityTracker.getYVelocity());
                //return false;
            
        ;

        mView3.setOnTouchListener(gestureListener);
    

    @Override
    public boolean onTouchEvent(MotionEvent me) 
        System.out.println("Inside onTouchEvent() of GenesMotionDetector.java");

        return gestureScanner.onTouchEvent(me);
    

    @Override
    public boolean onDown(MotionEvent e) 
        System.out.println("Inside onDown() of GenesMotionDetector.java");
        return true;
    

    @Override
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) 
        System.out.println("Inside onFling() of GenesMotionDetector.java");
        System.out.println("e1= "+ e1);
        System.out.println("e2= "+ e2);
        System.out.println("velocityX= "+ velocityX);
        System.out.println("velocityY= "+ velocityY);
        return true;
    

    @Override
    public void onLongPress(MotionEvent e) 
        System.out.println("Inside onLongPress() of GenesMotionDetector.java");
    

    @Override
    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) 
        System.out.println("Inside onScroll() of GenesMotionDetector.java");
        return true;
    

    @Override
    public void onShowPress(MotionEvent e) 
        System.out.println("Inside onShowPress() of GenesMotionDetector.java");
    

    @Override
    public boolean onSingleTapUp(MotionEvent e) 
        System.out.println("Inside onSingleTapUp() of GenesMotionDetector.java");
        return true;
    

你还不如在 onTouch() 中处理所有事情。我基本上是在 onTouch 中获取手势并将其传递给 onFling()。

【讨论】:

【参考方案8】:

使用 ImageView 设计您的布局。 将setOnTouchListener添加到imageView.imageview.setOnTouchListener(this).添加未实现的方法View.OnTouchListener。然后onTouch方法您可以实现您的客座逻辑。这个示例告诉您从左到右和从右到左客座,

float x1,x2;
float y1, y2;

@Override
public boolean onTouch(View view, MotionEvent event) 
    switch ( event.getAction() )

        case MotionEvent.ACTION_DOWN:
            x1 = event.getX();
            y1 = event.getY();
            break;
        

        case MotionEvent.ACTION_UP:
            x2 = event.getX();
            y2 = event.getY();

            if ( x1<x2 ) 
                //implement what you need to do here
            
            if ( x1>x2 ) 
                //implement what you need to do here
            
            break;
        
    
    return false;

【讨论】:

答案不提供投掷逻辑,OP正在寻找。

以上是关于将 Fling 手势添加到图像视图 - Android的主要内容,如果未能解决你的问题,请参考以下文章

如何将手势识别器添加到一系列子视图中?

缩放时,UIScrollview 子视图无法识别手势

UIScrollview 子视图在缩放后无法识别平移手势

iOS - 在图像视图上点击手势问题

在旋转视图上调整拖动手势

视图未检测到滑动图像库的手势识别器