【Android开发小记--9】触摸事件---实现双指缩放图片

关于触摸事件


覆写 onTouchEvent(MotionEvent event) 方法:

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                break;
            case MotionEvent.ACTION_MOVE:
                break;
            case MotionEvent.ACTION_UP:
                break;
        }
        //以下三种效果都是一样的
        System.out.println(event.getAction()); /*老写法*/
        System.out.println(event.getActionMasked());/*API 8 以后,Google推荐*/
        System.out.println(MotionEventCompat.getActionMasked(event)); /*兼容写法*/
        //获取屏幕上的手指数
        System.out.println(MotionEventCompat.getPointerCount(event));
        //触点坐标
        int actionIndex = MotionEventCompat.getActionIndex(event);
        //多点触摸
        if (MotionEventCompat.getPointerCount(event) > 1) {
            float touchX_1 = MotionEventCompat.getX(event, 0);
            float touchY_1 = MotionEventCompat.getY(event, 0);
            float touchX_2 = MotionEventCompat.getX(event, 1);
            float touchY_2 = MotionEventCompat.getY(event, 1);
            System.out.println(String.format("touchX_1:%f,touchY_1:%f,touchX_2:%f,touchY_2:%f\n", touchX_1, touchY_1, touchX_2, touchY_2));
        } else {
            //单点触摸
            float touchX = MotionEventCompat.getX(event, actionIndex);
            float touchY = MotionEventCompat.getY(event, actionIndex);
            System.out.println(touchX + "\t" + touchY);
        }
        return super.onTouchEvent(event);
    }


getAction、getActionMask、getActionIndex区别:

Android用一个32位的整型值表示一次TouchEvent事件,低8位表示touch事件的具体动作,比如按下,抬起,滑动,还有多点触控时的按下,抬起,这个和单点是区分开的,下面看具体的方法:
1 getAction:触摸动作的原始32位信息,包括事件的动作,触控点信息
2 getActionMask:触摸的动作,按下,抬起,滑动,多点按下,多点抬起
3 getActionIndex:触控点信息


Matrix 中的post 和pre 和set 方法的区别 以及Canvas中的方法:

post pre set 其实代表了Matrix 中方法变换的次序,pre是向前加入队列执行,post从后面加入队列执行, 而matrix的set方法则会对先前的pre和post操作进行清除,而后再设置它的值。


双指缩放图片,并且带拖动回弹居中的效果


这里是使用 Matrix +Bitmap 来进行图片缩放的。


首先,要对布局文件中的 ImageView 设置:

android:scaleType="matrix"

在 MainActivity.java 中,调用 Matrix 的 setScale()、postTranslate()、postScale() 方法来设置图片的移动方式,再调用 ImageView 的 setImageMatrix():

public class MainActivity extends AppCompatActivity {
    private ImageView imageView;
    private int screenWidth, screenHeight;//屏幕宽高
    private Bitmap bitmap;
    private Matrix matrix = new Matrix();
    private Matrix savedMatrix = new Matrix();
    private int mode = 0;
    private float distance;
    private float preDistance;
    private PointF mid = new PointF();//两指中点
    Context context;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        context = MainActivity.this;
        imageView = (ImageView) findViewById(R.id.imageView);
        bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.image);
        matrix.setScale(0.5f, 0.5f); //显示先缩小一些
        center();//缩小后居中
        imageView.setImageMatrix(matrix);
        imageView.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                ImageView view = (ImageView) v;
                switch (event.getAction() & MotionEvent.ACTION_MASK) {
                    //单个手指触摸
                    case MotionEvent.ACTION_DOWN:
                        mode = 1;
                        break;
                    //两指触摸
                    case MotionEvent.ACTION_POINTER_DOWN:
                        preDistance = getDistance(event);
                        //当两指间距大于10时,计算两指中心点
                        if (preDistance > 10f) {
                            mid = getMid(event);
                            savedMatrix.set(matrix);
                            mode = 2;
                        }
                        break;
                    case MotionEvent.ACTION_UP:
                        mode = 0;
                        break;
                    case MotionEvent.ACTION_POINTER_UP:
                        mode = 0;
                        break;
                    case MotionEvent.ACTION_MOVE:
                        //当两指缩放,计算缩放比例
                        if (mode == 2) {
                            distance = getDistance(event);
                            if (distance > 10f) {
                                matrix.set(savedMatrix);
                                float scale = distance / preDistance;
                                matrix.postScale(scale, scale, mid.x, mid.y);//缩放比例和中心点坐标
                            }
                        }
                        break;
                }
                view.setImageMatrix(matrix);
                center();  //回弹,令图片居中
                return true;
            }
        });
    }
    /*获取两指之间的距离*/
    private float getDistance(MotionEvent event) {
        float x = event.getX(1) - event.getX(0);
        float y = event.getY(1) - event.getY(0);
        float distance = (float) Math.sqrt(x * x + y * y);//两点间的距离
        return distance;
    }
    /*使图片居中*/
    private void center() {
        Matrix m = new Matrix();
        m.set(matrix);
        //绘制图片矩形
        //这样rect.left,rect.right,rect.top,rect.bottom分别就就是当前屏幕离图片的边界的距离
        RectF rect = new RectF(0, 0, bitmap.getWidth(), bitmap.getHeight());
        m.mapRect(rect);
        float height = rect.height();
        float width = rect.width();
        float deltaX = 0, deltaY = 0;
        //屏幕的宽高
        DisplayMetrics dm = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(dm); //获取屏幕分辨率
        screenWidth = dm.widthPixels;  //屏幕宽度
        screenHeight = dm.heightPixels;  //屏幕高度
        //获取ActionBar的高度
        int actionBarHeight = 0;
        TypedValue tv = new TypedValue();
        if (context.getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true)) {
            actionBarHeight = TypedValue.complexToDimensionPixelSize(tv.data, context.getResources().getDisplayMetrics());
        }
        //计算Y到中心的距离
        if (height < screenHeight) {
            deltaY = (screenHeight - height) / 2 - rect.top - actionBarHeight;
        } else if (rect.top > 0) {
            deltaY = -rect.top;
        } else if (rect.bottom < screenHeight) {
            deltaY = imageView.getHeight() - rect.bottom;
        }
        //计算X到中心的距离
        if (width < screenWidth) {
            deltaX = (screenWidth - width) / 2 - rect.left;
        } else if (rect.left > 0) {
            deltaX = -rect.left;
        } else if (rect.right < screenWidth) {
            deltaX = screenWidth - rect.right;
        }
        matrix.postTranslate(deltaX, deltaY);
    }
    /*取两指的中心点坐标*/
    public static PointF getMid(MotionEvent event) {
        float midX = (event.getX(1) + event.getX(0)) / 2;
        float midY = (event.getY(1) + event.getY(0)) / 2;
        return new PointF(midX, midY);
    }
}

这里,令图片居中的 center() 方法:
1.使用Bitmap来获取图片的宽高,再使用矩形 RectF ,以及 Matrix 的 mapRect()方法来得到当前图片的位置;
2.获取屏幕宽高,以及Actionbar的高度;
3.再计算图片中心点到屏幕中心点的距离,进行平移;


具体代码点击


【Android开发小记--9】触摸事件---实现双指缩放图片_第1张图片




你可能感兴趣的:(Android)