zoukankan      html  css  js  c++  java
  • android ListView 可缩放,支持左右上下手势

    public class ZoomListView extends ListView implements SwipeListener {
        
        public static enum Action {
            LeftToRight, 
            RightToLeft, 
            TopToBottom, 
            BottomToTop, 
            None
        }
        
        private List<SwipeListener> actionListeners = new ArrayList<SwipeListener>();
        private boolean SwipeFlag = false;
        
        private static final int HORIZONTAL_MIN_DISTANCE = 30; // The minimum
        private static final int VERTICAL_MIN_DISTANCE = 80; // The minimum distance
        private float downX, downY, upX, upY; // Coordinates
        
        private static final int INVALID_POINTER_ID = -1;
        private int mActivePointerId = INVALID_POINTER_ID;
        private ScaleGestureDetector mScaleDetector;
    
        private float mScaleFactor = 1.f;
        private float maxWidth = 0.0f;
        private float maxHeight = 0.0f;
        private float mLastTouchX;
        private float mLastTouchY;
        private float mPosX;
        private float mPosY;
        private float width;
        private float height;
    
    
        public ZoomListView(Context context) {
            super(context);
            mScaleDetector = new ScaleGestureDetector(getContext(), new ScaleListener());
        }
    
        public ZoomListView(Context context, AttributeSet attrs) {
            super(context, attrs);
            mScaleDetector = new ScaleGestureDetector(getContext(), new ScaleListener());
        }
    
        public ZoomListView(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            mScaleDetector = new ScaleGestureDetector(getContext(), new ScaleListener());
        }
    
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            width = MeasureSpec.getSize(widthMeasureSpec);
            height = MeasureSpec.getSize(heightMeasureSpec);
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        }
    
        @Override
        public boolean onTouchEvent(@NonNull MotionEvent ev) {
            super.onTouchEvent(ev);
            final int action = ev.getAction();
            mScaleDetector.onTouchEvent(ev);
            switch (action & MotionEvent.ACTION_MASK) {
                case MotionEvent.ACTION_DOWN: {
                    final float x = ev.getX();
                    final float y = ev.getY();
    
                    mLastTouchX = x;
                    mLastTouchY = y;
    
                    mActivePointerId = ev.getPointerId(0);
                    
                    downX = ev.getX();
                    downY = ev.getY();
                    
                    SwipeFlag = true;
                    
                    break;
                }
    
                case MotionEvent.ACTION_MOVE: {
                    final int pointerIndex = ev.findPointerIndex(mActivePointerId);
                    final float x = ev.getX(pointerIndex);
                    final float y = ev.getY(pointerIndex);
                    final float dx = x - mLastTouchX;
                    final float dy = y - mLastTouchY;
    
                    float leftMargin = Math.abs(mPosX) / mScaleFactor;
                    float rightMargin = this.getMeasuredWidth() - Math.abs(mPosX) / mScaleFactor;
                    rightMargin -= this.getResources().getDisplayMetrics().widthPixels / mScaleFactor ;
                    
                    mPosX += dx;
                    mPosY += dy;
                    
                    if (mPosX > 0.0f)
                        mPosX = 0.0f;
                    else if (mPosX < maxWidth)
                        mPosX = maxWidth;
                    
                    if (mPosY > 0.0f)
                        mPosY = 0.0f;
                    else if (mPosY < maxHeight)
                        mPosY = maxHeight;
    
                    mLastTouchX = x;
                    mLastTouchY = y;
    
                    invalidate();
                    
                    upX = ev.getX();
                    upY = ev.getY();
                    
                    float deltaX = downX - upX;
                    float deltaY = downY - upY;
                    // horizontal swipe detection
                    if (Math.abs(deltaX) > HORIZONTAL_MIN_DISTANCE) {
                        // left or right
                        if (deltaX < 0 && SwipeFlag && leftMargin < 10) {
                            SwipeFlag = false;
                            OnAction(Action.LeftToRight);
                            break;
                        }
                        if (deltaX > 0 && SwipeFlag && rightMargin < 10) {
                            SwipeFlag = false;
                            OnAction(Action.RightToLeft);
                            break;
                        }
                    } else
                    {
                        // vertical swipe detection
                        if (Math.abs(deltaY) > VERTICAL_MIN_DISTANCE) {
                            // top or down
                            if (deltaY < 0 && SwipeFlag) {
                                SwipeFlag = false;
                                OnAction(Action.TopToBottom);
                                break;
                            }
                            if (deltaY > 0 && SwipeFlag) {
                                SwipeFlag = false;
                                OnAction(Action.BottomToTop);
                                break;
                            }
                        }
                    }
                    
                    break;
                }
    
                case MotionEvent.ACTION_UP: {
                    mActivePointerId = INVALID_POINTER_ID;
                    break;
                }
    
                case MotionEvent.ACTION_CANCEL: {
                    mActivePointerId = INVALID_POINTER_ID;
                    break;
                }
    
                case MotionEvent.ACTION_POINTER_UP: {
                    final int pointerIndex = (action & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
                    final int pointerId = ev.getPointerId(pointerIndex);
                    if (pointerId == mActivePointerId) {
                        final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
                        mLastTouchX = ev.getX(newPointerIndex);
                        mLastTouchY = ev.getY(newPointerIndex);
                        mActivePointerId = ev.getPointerId(newPointerIndex);
                    }
                    break;
                }
            }
    
            return true;
        }
    
        @Override
        public void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            canvas.save(Canvas.MATRIX_SAVE_FLAG);
            canvas.translate(mPosX, mPosY);
            canvas.scale(mScaleFactor, mScaleFactor);
            canvas.restore();
        }
    
        @Override
        protected void dispatchDraw(@NonNull Canvas canvas) {
            canvas.save(Canvas.MATRIX_SAVE_FLAG);
            if (mScaleFactor == 1.0f) {
                mPosX = 0.0f;
                mPosY = 0.0f;
            }
            canvas.translate(mPosX, mPosY);
            canvas.scale(mScaleFactor, mScaleFactor);
            super.dispatchDraw(canvas);
            canvas.restore();
            invalidate();
        }
    
        private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
            @Override
            public boolean onScale(ScaleGestureDetector detector) {
                mScaleFactor *= detector.getScaleFactor();
                mScaleFactor = Math.max(1.0f, Math.min(mScaleFactor, 3.0f));
                maxWidth = width - (width * mScaleFactor);
                maxHeight = height - (height * mScaleFactor);
                invalidate();
                return true;
            }
        }
        
        @Override
        public void OnAction(Action action) {
            for(SwipeListener listener : actionListeners){
                listener.OnAction(action);
            }
        }
        
        public void addActionListener(SwipeListener listener)
        {
            actionListeners.add(listener);
        }
    }
    public interface SwipeListener extends EventListener {
        public void OnAction(Action action);
    }

     如果想ListView中显示图片且自适应,需要设置 android:adjustViewBounds="true"

  • 相关阅读:
    href="#" 是什么意思?
    JavaScript匿名自执行函数~function(){}
    var $this = $(this)是什么意思?
    .Ajax
    myeclipse 的Customize Perspective 没有反应
    JS中的this指向问题
    JS中$含义和用法
    JS中sessionstorage的getItem/setItem/removeItem/clear
    JS中的top是什么?
    CAD常用命令大全
  • 原文地址:https://www.cnblogs.com/nanfei/p/8675813.html
Copyright © 2011-2022 走看看