0

我在我的应用程序中使用 ViewPager 来创建滑动图像的滑块。一切工作正常,除了我必须双击缩放图像。但是双击不适用于 ViewPager。我尝试了许多解决方案但无济于事。任何帮助表示赞赏。

谢谢

4

5 回答 5

4

使用此类进行图像捏合缩放和双击缩放

import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.graphics.PointF;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.ImageView;

public class TouchImageView extends ImageView {
Matrix matrix = new Matrix();

// We can be in one of these 3 states
static final int NONE = 0;
static final int DRAG = 1;
static final int ZOOM = 2;
int mode = NONE;
//static  NonSwipeableViewPager PagerLeft;
// Remember some things for zooming
PointF last = new PointF();
PointF start = new PointF();
float minScale = 1f;
float maxScale = 3f;
float[] m;
static boolean b =false, c= false;
float redundantXSpace, redundantYSpace;

float width, height;
static final int CLICK = 3;
float saveScale = 1f;
float right, bottom, origWidth, origHeight, bmWidth, bmHeight;

ScaleGestureDetector mScaleDetector;

Context context;
ViewGroup vp;

public TouchImageView(Context context) {
    super(context);
    sharedConstructing(context);
}

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

public void setChild(ViewGroup vp) {
    this.vp = vp;
}

private void sharedConstructing(Context context) {
    super.setClickable(true);
    this.context = context;
    mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());
    matrix.setTranslate(1f, 1f);
    m = new float[9];
    setImageMatrix(matrix);
    setScaleType(ScaleType.MATRIX);
    setOnTouchListener(new OnTouchListener() {
        @SuppressWarnings("deprecation")
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            mScaleDetector.onTouchEvent(event);
            matrix.getValues(m);
            float x = m[Matrix.MTRANS_X];
            float y = m[Matrix.MTRANS_Y];
            /*Log.v("log_tag",  event.getX()+" matrix "
                    + x);*/
            PointF curr = new PointF(event.getX(), event.getY());
            switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                TouchImageView.b = false;
                Log.v("event","ACTION_DOWN");
                last.set(event.getX(), event.getY());
                start.set(last);
                mode = DRAG;
                break;
            case MotionEvent.ACTION_MOVE:
                if (mode == DRAG) {
                    float deltaX = curr.x - last.x;
                    float deltaY = curr.y - last.y;
                    float scaleWidth = Math.round(origWidth * saveScale);
                    float scaleHeight = Math.round(origHeight * saveScale);
                    if (scaleWidth < width) {
                        deltaX = 0;
                        if (y + deltaY > 0){
                            TouchImageView.b = true;
                            Log.v("event","ACTION_MOVE  scaleWidth < width   y + deltaY > 0");
                            deltaY = -y;
                        }
                        else if (y + deltaY < -bottom){
                            TouchImageView.b = false;
                            Log.v("event","else ACTION_MOVE  scaleWidth < width   y + deltaY < -bottom");
                            deltaY = -(y + bottom);
                        }else{
                            TouchImageView.b = false;
                        }
                    } else if (scaleHeight < height) {
                        deltaY = 0;
                        if (x + deltaX > 0){
                            TouchImageView.b = true;
                            Log.v("event","ACTION_MOVE  scaleWidth < height x + deltaX > 0");
                            deltaX = -x;
                        }
                        else if (x + deltaX < -right){
                            TouchImageView.b = true;
                            Log.v("event","ACTION_MOVE  scaleWidth < height x + deltaX < -right");
                            deltaX = -(x + right);
                        }else{
                            TouchImageView.b = false;
                        }
                    }else {
                        if (x + deltaX > 0){
                            TouchImageView.b = true;
                            Log.v("event","scaleWidth > width");
                            deltaX = -x;
                        }
                        else if (x + deltaX < -right){
                            TouchImageView.b = true;
                            Log.v("event","else scaleWidth > width");
                            deltaX = -(x + right);
                        }
                        else{
                            TouchImageView.b = true;
                        }
                        if (y + deltaY > 0){
                            TouchImageView.b = true;
                            Log.v("event","y + deltaY");
                            deltaY = -y;
                        }
                        else if (y + deltaY < -bottom){
                            TouchImageView.b = true;
                            Log.v("event","y + deltaY < -bottom");
                            deltaY = -(y + bottom);
                        }else{
                            TouchImageView.b = false;
                        }
                    }
                    /*Log.v("log_tag",height + " matrix "
                            + (int) getHeightFromMatrix(matrix, TouchImageView.this));*/
                    matrix.postTranslate(deltaX, deltaY);
                    last.set(curr.x, curr.y);
                }
                break;

            case MotionEvent.ACTION_UP:
                Log.v("event","ACTION_UP");
                TouchImageView.b = true;
                mode = NONE;
                int xDiff = (int) Math.abs(curr.x - start.x);
                int yDiff = (int) Math.abs(curr.y - start.y);
                if (xDiff < CLICK && yDiff < CLICK){
                    Log.v("event","ACTION_UP  xDiff < CLICK && yDiff < CLICK");
                    performClick();
                }
                break;

            case MotionEvent.ACTION_POINTER_UP:
                //TouchImageView.b = false;
                Log.v("event","ACTION_POINTER_UP");
                mode = NONE;
                break;
            case MotionEvent.ACTION_POINTER_3_DOWN:
                Log.v("event","ACTION_HOVER_MOVE");
                break;
            }
            /*getLayoutParams().height = (int) getWidthFromMatrix(matrix,
                    TouchImageView.this);
            getLayoutParams().width = (int) getHeightFromMatrix(matrix,
                    TouchImageView.this);*/
            setImageMatrix(matrix);
            invalidate();
            return true;
        }
    });
}
@Override
public void setImageBitmap(Bitmap bm) {
    super.setImageBitmap(bm);
    if (bm != null) {
        bmWidth = bm.getWidth();
        bmHeight = bm.getHeight();
    }
}

public void setMaxZoom(float x) {
    maxScale = x;
}

private class ScaleListener extends
        ScaleGestureDetector.SimpleOnScaleGestureListener {
    @Override
    public boolean onScaleBegin(ScaleGestureDetector detector) {
        mode = ZOOM;
        return true;
    }

    @SuppressLint("NewApi")
    @TargetApi(8)
    @Override
    public boolean onScale(ScaleGestureDetector detector) {
        float mScaleFactor = (float) Math.min(
                Math.max(.95f, detector.getScaleFactor()), 1.05);
        float origScale = saveScale;
        saveScale *= mScaleFactor;
        if (saveScale > maxScale) {
            saveScale = maxScale;
            mScaleFactor = maxScale / origScale;
        } else if (saveScale < minScale) {
            saveScale = minScale;
            mScaleFactor = minScale / origScale;
        }
        right = width * saveScale - width
                - (2 * redundantXSpace * saveScale);
        bottom = height * saveScale - height
                - (2 * redundantYSpace * saveScale);
        if (origWidth * saveScale <= width
                || origHeight * saveScale <= height) {
            matrix.postScale(mScaleFactor, mScaleFactor, width / 2,
                    height / 2);
            if (mScaleFactor < 1) {
                matrix.getValues(m);
                float x = m[Matrix.MTRANS_X];
                float y = m[Matrix.MTRANS_Y];
                if (mScaleFactor < 1) {
                    if (Math.round(origWidth * saveScale) < width) {
                        if (y < -bottom)
                            matrix.postTranslate(0, -(y + bottom));
                        else if (y > 0)
                            matrix.postTranslate(0, -y);
                    } else {
                        if (x < -right)
                            matrix.postTranslate(-(x + right), 0);
                        else if (x > 0)
                            matrix.postTranslate(-x, 0);
                    }
                }
            }
        } else {
            matrix.postScale(mScaleFactor, mScaleFactor,
                    detector.getFocusX(), detector.getFocusY());
            matrix.getValues(m);
            float x = m[Matrix.MTRANS_X];
            float y = m[Matrix.MTRANS_Y];
            if (mScaleFactor < 1) {
                if (x < -right)
                    matrix.postTranslate(-(x + right), 0);
                else if (x > 0)
                    matrix.postTranslate(-x, 0);
                if (y < -bottom)
                    matrix.postTranslate(0, -(y + bottom));
                else if (y > 0)
                    matrix.postTranslate(0, -y);
            }
        }
        return true;
    }
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    width = MeasureSpec.getSize(widthMeasureSpec);
    height = MeasureSpec.getSize(heightMeasureSpec);
    // Fit to screen.
    float scale;
    float scaleX = (float) width / (float) bmWidth;
    float scaleY = (float) height / (float) bmHeight;
    scale = Math.min(scaleX, scaleY);
    matrix.setScale(scale, scale);
    setImageMatrix(matrix);
    saveScale = 1f;

    // Center the image
    redundantYSpace = (float) height - (scale * (float) bmHeight);
    redundantXSpace = (float) width - (scale * (float) bmWidth);
    redundantYSpace /= (float) 2;
    redundantXSpace /= (float) 2;

    matrix.postTranslate(redundantXSpace, redundantYSpace);

    origWidth = width - 2 * redundantXSpace;
    origHeight = height - 2 * redundantYSpace;
    right = width * saveScale - width - (2 * redundantXSpace * saveScale);
    bottom = height * saveScale - height
            - (2 * redundantYSpace * saveScale);
    setImageMatrix(matrix);
}

/*public static void setPager(NonSwipeableViewPager pagerLeft) {
    PagerLeft = pagerLeft;
}*/



  }

在您的寻呼机适配器中执行此操作

TouchImageView image_view=(TouchImageView)findViewById(R.id.your_image);
于 2013-09-27T07:15:49.610 回答
3

它很棘手,但您也可以这样做:

  1. 为您的视图实现 onTouch 侦听器
  2. 当前时间戳取一个长变量=0
  3. 在 onTouch 方法中检查时间差 ((variable-system.currentTimeinMili)<1000) 如果为真,则执行您想要的操作并使用当前时间更新变量。
于 2013-09-27T07:15:04.120 回答
1

这个解决方案非常适合我。将这些行 (interfaceonTouchEvent) 添加到您CustomViewPager喜欢的行中:

public class CustomViewPager extends ViewPager {

    //your variables

    private long previousClickTime = -1;
    private float x1 = -100, y1 = -100;
    private VPDoubleClickListener vpDoubleClickListener;

    //default build methods

    public interface VPDoubleClickListener{
        void onVPDoubleClicked();
    }

    public void setVPDoubleClickListener(VPDoubleClickListener vpDoubleClickListener){
        this.vpDoubleClickListener = vpDoubleClickListener;
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        long nowClick = System.currentTimeMillis();
        float x2, y2;
        int action = ev.getAction();
        switch (action) {
            case MotionEvent.ACTION_DOWN:{
                x1 = ev.getX();
                y1 = ev.getY();
                break;
            }
            case MotionEvent.ACTION_UP:{
                x2 = ev.getX();
                y2 = ev.getY();
                double space = Math.hypot(x2 - x1, y2 - y1);
                //if distance of move < 25 -> ignore double tap
                //300 milliseconds - double tap time threshold
                if(space < 25 & nowClick - lastClick < 300){
                    if (vpDoubleClickListener != null) {
                        vpDoubleClickListener.onVPDoubleClicked();
                    }
                    Log.i("viewpager", "double tap");
                }
                lastClick = nowClick;
                break;
            }
            default:break;
        }
        return super.onTouchEvent(ev);
    }

    //your custom methods

}

然后VPDoubleClickListener在父类中实现并在此处设置setVPDoubleClickListener为您的CustomViewPager喜欢:

public class CustomActivity implements CustomViewPager.VPDoubleClickListener {

    //...
    VPDoubleClickListener vpDoubleClickListener = this;

    @Override
    public void onVPDoubleClicked() {
        // Handle double tap event here!
        // Handle double tap event here!
        // Handle double tap event here!
        // Handle double tap event here!
        Log.d("TEST", "CustomViewPager double tap test.");
    }

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

    private void initCustomViewPager(){
        CustomViewPager customViewPager = (CustomViewPager) findViewById(R.id.customViewPager);
        //...
        customViewPager.setVPDoubleClickListener(vpDoubleClickListener);
    }

    //your custom methods

}

然后在layout.xmlactivity_custom.xml在这种情况下)文件中使用<com.your_username.your_app.your_package.CustomViewPager>.

抱歉有错别字。

于 2017-02-07T12:19:01.223 回答
0

我来不及回答这个问题,但如果有人仍在寻找解决方案:

像这样创建一个类,只需复制粘贴代码并导入文件:

点击这里

在您的 XML 中,您将 Pageradapter 的 imageview 设置为执行以下操作:

 <your_package_name.TouchImageView
    android:id="@+id/imageView"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:adjustViewBounds="true"
    android:visibility="visible"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent">


 </your_package_name.TouchImageView>

并且在您的 PagerAdapter 中不要忘记使用:

 TouchImageView imageView = view.findViewById(R.id.imageView);

所有功劳归于https://github.com/MikeOrtiz/TouchImageView

于 2020-03-03T12:06:22.460 回答
0

我结合了 doubleTapIsLocked 变量、dispatchTouchEvent 和 GestureDetector。这可以检测双击和滑动。

public class MainActivity extends AppCompatActivity {

    private static final String TAG = "MainActivity";
    private Boolean doubleTapIsLocked = false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
        setContentView(R.layout.activity_main);

        ViewPager myViewPager = (ViewPager) findViewById(R.id.pager);
        MyPagerAdapter myPagerAdapter = new MyPagerAdapter();
        myViewPager.setAdapter(myPagerAdapter);

    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {

        if(!doubleTapIsLocked){gestureDetector.onTouchEvent(ev);}
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN://finger touching to the screen
                break;
            case MotionEvent.ACTION_MOVE://finger moving on the screen

                break;
            case MotionEvent.ACTION_UP://finger not touching to the screen
                doubleTapIsLocked = false; //opens the lock
                break;
        }
        return super.dispatchTouchEvent(ev);
    }

    //dedects the double tap and swipe
    //////////////////////////////Gesture started///////////////////////////////////////////////////
    GestureDetector.SimpleOnGestureListener simpleOnGestureListener = new GestureDetector.SimpleOnGestureListener() {

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

            float sensitvity = 50;//50;
            float distanceX = e1.getX() - e2.getX();//horizontal distance
            float distanceY = e1.getY() - e2.getY();//vertical distance

            if (Math.abs(distanceY) < Math.abs(distanceX)) {//finger moving horizontaly

                Log.i(TAG, "horizontal move");
                doubleTapIsLocked = true;//locks double tap

            }

            return super.onFling(e1, e2, velocityX, velocityY);
        }


        @Override
        public boolean onDoubleTap(MotionEvent e) {//double tap

            Log.i(TAG, "onDoubleTap");

            return super.onDoubleTap(e);
        }
    };
    GestureDetector gestureDetector = new GestureDetector(simpleOnGestureListener);
    //////////////////////////////Gesture end/////////////////////////////////////////////////////
于 2016-01-12T19:45:37.213 回答