How to fix pinch zoom focal point in a custom view?

前端 未结 1 964
轻奢々
轻奢々 2021-02-15 18:04

For my question I have prepared a very simple test app at Github.

For simplicity I have removed flinging, scroll constraints and edge effects (which actually work well i

1条回答
  •  野趣味
    野趣味 (楼主)
    2021-02-15 18:50

    Using Matrix is a really better idea - the code is much more simple and you dont have to prove your math skills ;-), see how Matrix#postTranslate and Matrix#postScale methods are used:

    class MyView extends View {
        private static final String TAG = "MyView";
    
        private final ScaleGestureDetector mScaleDetector;
        private final GestureDetector mGestureDetector;
    
        private final Drawable mBoard;
        private final float mBoardWidth;
        private final float mBoardHeight;
        private Matrix mMatrix;
    
        public MyView(Context context) {
            this(context, null, 0);
        }
    
        public MyView(Context context, AttributeSet attrs) {
            this(context, attrs, 0);
        }
    
        public MyView(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
    
            mBoard = ResourcesCompat.getDrawable(context.getResources(), R.drawable.chrome, null);
            mBoardWidth = mBoard.getIntrinsicWidth();
            mBoardHeight = mBoard.getIntrinsicHeight();
            mBoard.setBounds(0, 0, (int) mBoardWidth, (int) mBoardHeight);
    
            mMatrix = new Matrix();
    
            mScaleDetector = new ScaleGestureDetector(context, scaleListener);
            mGestureDetector = new GestureDetector(context, listener);
        }
    
        ScaleGestureDetector.OnScaleGestureListener scaleListener = new ScaleGestureDetector.SimpleOnScaleGestureListener() {
            @Override
            public boolean onScale(ScaleGestureDetector scaleDetector) {
                float factor = scaleDetector.getScaleFactor();
                mMatrix.postScale(factor, factor, getWidth() / 2f, getHeight() / 2f);
                ViewCompat.postInvalidateOnAnimation(MyView.this);
                return true;
            }
        };
    
        GestureDetector.OnGestureListener listener = new GestureDetector.SimpleOnGestureListener() {
            @Override
            public boolean onScroll(MotionEvent e1, MotionEvent e2, float dX, float dY) {
                mMatrix.postTranslate(-dX, -dY);
                ViewCompat.postInvalidateOnAnimation(MyView.this);
                return true;
            }
        };
    
        @Override
        protected void onSizeChanged(int w, int h, int oldw, int oldh) {
            float scale = Math.max(w / mBoardWidth, h / mBoardHeight);
            mMatrix.setScale(scale, scale);
            mMatrix.postTranslate((w - scale * mBoardWidth) / 2f, (h - scale * mBoardHeight) / 2f);
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
            canvas.save();
            canvas.concat(mMatrix);
            mBoard.draw(canvas);
            canvas.restore();
        }
    
        @Override
        @SuppressLint("ClickableViewAccessibility")
        public boolean onTouchEvent(MotionEvent e) {
            mGestureDetector.onTouchEvent(e);
            mScaleDetector.onTouchEvent(e);
            return true;
        }
    }
    

    0 讨论(0)
提交回复
热议问题