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