android通用縮放滾動(dòng)容器——ZoomScrollLayout

ZoomScrollLayout是一個(gè)可以對(duì)任意子view進(jìn)行縮放、滾動(dòng)查看的控件。類似于圖片查看器,支持任何類型的view。

先看效果:


222.gif

上代碼:


import android.content.Context;

import android.util.AttributeSet;

import android.view.*;

import android.widget.RelativeLayout;

import com.orhanobut.logger.Logger;

/**

* Created by wg on 2017/4/21.

*/

public class ZoomScrollLayout extends RelativeLayout implements ScaleGestureDetector.OnScaleGestureListener {

    private ScaleGestureDetector mScaleDetector;

    private GestureDetector mGestureDetector;

    private static final float MIN_ZOOM = 0.3f;

    private static final float MAX_ZOOM = 3.0f;

    private Integer mLeft, mTop, mRight, mBottom;

    private int centerX, centerY;

    private float mLastScale = 1.0f;

    private float totleScale = 1.0f;

    // childview

    private View mChildView;

    // 攔截滑動(dòng)事件

    float mDistansX, mDistansY, mTouchSlop;

    private enum MODE {

        ZOOM, DRAG, NONE

    }

    private MODE mode;

    boolean touchDown;

    public ZoomScrollLayout(Context context) {

        super(context);

        init(context);

    }

    public ZoomScrollLayout(Context context, AttributeSet attrs) {

        super(context, attrs);

        init(context);

    }

    public ZoomScrollLayout(Context context, AttributeSet attrs, int defStyleAttr) {

        super(context, attrs, defStyleAttr);

        init(context);

    }

    public void init(Context context) {

        mScaleDetector = new ScaleGestureDetector(context, this);

        mGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {

            @Override

            public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {

                if (mode == MODE.DRAG) {

                    if (mChildView == null) {

                        mChildView = getChildAt(0);

                        centerX = getWidth() / 2;

                        centerY = getHeight() / 2;

                    }

                    if (mLeft == null) {

                        mLeft = mChildView.getLeft();

                        mTop = mChildView.getTop();

                        mRight = mChildView.getRight();

                        mBottom = mChildView.getBottom();

                    }

                    // 防抖動(dòng)

                    if (touchDown) {

                        touchDown = false;

                        return true;

                    }

                    Logger.i("distanceX=" + distanceX + ";distanceY=" + distanceY);

                    Logger.i("mLeft=" + mLeft + ";mTop=" + mTop);

                    mLeft = mLeft - (int) distanceX;

                    mTop = mTop - (int) distanceY;

                    mRight = mRight - (int) distanceX;

                    mBottom = mBottom - (int) distanceY;

                    mChildView.layout(mLeft, mTop, mRight, mBottom);

                }

                return true;

            }

            @Override

            public boolean onDown(MotionEvent e) {

                touchDown = true;

                return super.onDown(e);

            }

        });

        // 系統(tǒng)最小滑動(dòng)距離

        mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();

    }

    @Override

    public boolean onInterceptTouchEvent(MotionEvent e) {

        int action = e.getActionMasked();

        int currentX = (int) e.getX();

        int currentY = (int) e.getY();

        switch (action) {

            case MotionEvent.ACTION_DOWN:

                //記錄上次滑動(dòng)的位置

                mDistansX = currentX;

                mDistansY = currentY;

                //將當(dāng)前的坐標(biāo)保存為起始點(diǎn)

                mode = MODE.DRAG;

                break;

            case MotionEvent.ACTION_MOVE:

                if (Math.abs(mDistansX - currentX) >= mTouchSlop || Math.abs(mDistansY - currentY) >= mTouchSlop) { //父容器攔截

                    return true;

                }

                break;

            //指點(diǎn)桿保持按下,并且進(jìn)行位移

            //有手指抬起,將模式設(shè)為NONE

            case MotionEvent.ACTION_UP:

            case MotionEvent.ACTION_POINTER_UP:

                mode = MODE.NONE;

                break;

        }

        return super.onInterceptTouchEvent(e);

    }

    @Override

    public boolean onTouchEvent(MotionEvent event) {

        mScaleDetector.onTouchEvent(event);

        mGestureDetector.onTouchEvent(event);

        return true;

    }

    @Override

    public boolean onScale(ScaleGestureDetector scaleGestureDetector) {

        Logger.i("MotionEvent.onScale");

        if (mode == MODE.ZOOM) {

            float scaleFactor = scaleGestureDetector.getScaleFactor();

            float tempScale = mLastScale * scaleFactor;

            if (tempScale <= MAX_ZOOM && tempScale >= MIN_ZOOM) {

                totleScale = tempScale;

                applyScale(totleScale);

            }

        }

        return false;

    }

    /**

    * 執(zhí)行縮放操作

    */

    public void applyScale(float scale) {

        mChildView.setScaleX(scale);

        mChildView.setScaleY(scale);

    }

    @Override

    public boolean onScaleBegin(ScaleGestureDetector scaleGestureDetector) {

        Logger.i("MotionEvent.onScaleBegin");

        mode = MODE.ZOOM;

        if (mode == MODE.ZOOM) {

            if (mChildView == null) {

                mChildView = getChildAt(0);

                centerX = getWidth() / 2;

                centerY = getHeight() / 2;

            }

            mLeft = mChildView.getLeft();

            mTop = mChildView.getTop();

            mRight = mChildView.getRight();

            mBottom = mChildView.getBottom();

        }

        return true;

    }

    @Override

    public void onScaleEnd(ScaleGestureDetector scaleGestureDetector) {

        mLastScale = totleScale;

    }

}

注意:ZoomScrollLayout 和ScrollView一樣,只能有一個(gè)子View

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容