public classDoubleScaleImageViewextendsAppCompatImageViewimplementsView.OnTouchListener,ViewTreeObserver.OnGlobalLayoutListener{
? ? private boolean isFirst = false;
? ? private float doubleScale;// 雙擊放大的值? ? private Matrix mScaleMatrix;
? ? private float defaultScale;// 默認(rèn)的縮放值? ? private int mLastPinterCount;// 記錄上一次多點(diǎn)觸控的數(shù)量? ? private float mLastX;
? ? private float mLastY;
? ? private int mTouchSlop;
? ? private boolean isCanDrag;
? ? private boolean isCheckLeft;
? ? private boolean isCheckTop;
? ? private GestureDetector mGestureDetector;
? ? publicDoubleScaleImageView(Context context){
? ? ? ? this(context, null);
? ? }
? ? publicDoubleScaleImageView(Context context, AttributeSet attrs){
? ? ? ? this(context, attrs, 0);
? ? }
? ? publicDoubleScaleImageView(Context context, AttributeSet attrs,intdefStyleAttr){
? ? ? ? super(context, attrs, defStyleAttr);
? ? ? ? mScaleMatrix = new Matrix();
? ? ? ? setScaleType(ScaleType.MATRIX);
? ? ? ? setOnTouchListener(this);
? ? ? ? // getScaledTouchSlop是一個(gè)距離只祠,表示滑動(dòng)的時(shí)候裸影,手的移動(dòng)要大于這個(gè)距離才開始移動(dòng)控件萍桌。如果小于這個(gè)距離就不觸發(fā)移動(dòng)控件? ? ? ? mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
? ? ? ? mGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
? ? ? ? ? ? @Override? ? ? ? ? ? publicbooleanonDoubleTap(MotionEvent e){
? ? ? ? ? ? ? ? float x = e.getX();
? ? ? ? ? ? ? ? float y = e.getY();
? ? ? ? ? ? ? ? if (getScale() < doubleScale) {
? ? ? ? ? ? ? ? ? ? mScaleMatrix.postScale(doubleScale / getScale(), doubleScale / getScale(), x, y);// 放大? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? else {
? ? ? ? ? ? ? ? ? ? mScaleMatrix.postScale(defaultScale / getScale(), defaultScale / getScale(), x, y);// 縮小? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? setImageMatrix(mScaleMatrix);
? ? ? ? ? ? ? ? return super.onDoubleTap(e);
? ? ? ? ? ? }
? ? ? ? });
? ? }
? ? @Override? ? protectedvoidonAttachedToWindow(){// view附加到窗體上時(shí)調(diào)用該方法? ? ? ? super.onAttachedToWindow();
? ? ? ? getViewTreeObserver().addOnGlobalLayoutListener(this);
? ? }
? ? @SuppressWarnings("deprecation")
? ? @Override? ? protectedvoidonDetachedFromWindow(){// 將視圖從窗體上分離的時(shí)候調(diào)用該方法。? ? ? ? super.onDetachedFromWindow();
? ? ? ? getViewTreeObserver().removeGlobalOnLayoutListener(this);
? ? }
? ? @Override? ? publicvoidonGlobalLayout(){// 在這個(gè)方法中獲取ImageView加載完成后的圖片? ? ? ? if (!isFirst) {
? ? ? ? ? ? // 獲取控件的寬度和高度? ? ? ? ? ? int width = getWidth();
? ? ? ? ? ? int height = getHeight();
? ? ? ? ? ? // 得到我們的圖片以及圖片的寬度及高度? ? ? ? ? ? Drawable drawable = getDrawable();
? ? ? ? ? ? if (drawable == null) { return; }
? ? ? ? ? ? int imageWidth = drawable.getIntrinsicWidth();// 圖片的寬度? ? ? ? ? ? int imageHeight = drawable.getIntrinsicHeight();// 圖片的高度? ? ? ? ? ? float scale = 1.0f;
? ? ? ? ? ? // 如果圖片寬度大于控件寬度度硝,但是圖片高度小于控件 高度肿轨,我們要縮小圖片? ? ? ? ? ? if (imageWidth > width && imageHeight < height) {
? ? ? ? ? ? ? ? scale = width * 1.0f / imageWidth;
? ? ? ? ? ? }
? ? ? ? ? ? // 如果圖片寬度小于控件寬度,但是圖片高度大于控件 高度塘淑,我們要縮小圖片? ? ? ? ? ? if (imageWidth < width && imageHeight > height) {
? ? ? ? ? ? ? ? scale = height * 1.0f / imageHeight;
? ? ? ? ? ? }
? ? ? ? ? ? // 如果圖片的寬度都 大于或小于控件寬度萝招,我們則要對(duì)圖片進(jìn)行對(duì)應(yīng)縮放,保證圖片占滿控件? ? ? ? ? ? if ((imageWidth > width && imageHeight > height) || (imageWidth < width && imageHeight < height)) {
? ? ? ? ? ? ? ? scale = Math.min(width * 1.0f / imageWidth, height * 1.0f / imageHeight);
? ? ? ? ? ? }
? ? ? ? ? ? // 初始化對(duì)應(yīng)的縮放值? ? ? ? ? ? defaultScale = scale;
? ? ? ? ? ? doubleScale = defaultScale * 2;
? ? ? ? ? ? // 圖片縮放后存捺,將圖片要移動(dòng)到控件中心? ? ? ? ? ? int dx = width / 2 - imageWidth / 2;
? ? ? ? ? ? int dy = height / 2 - imageHeight / 2;
? ? ? ? ? ? mScaleMatrix.postTranslate(dx, dy);
? ? ? ? ? ? mScaleMatrix.postScale(defaultScale, defaultScale, width / 2, height / 2);
? ? ? ? ? ? setImageMatrix(mScaleMatrix);
? ? ? ? ? ? isFirst = true;
? ? ? ? }
? ? }
? ? @Override? ? publicbooleanonTouch(View v, MotionEvent event){
? ? ? ? if (mGestureDetector.onTouchEvent(event)) { return true; }
? ? ? ? float x = 0;
? ? ? ? float y = 0;
? ? ? ? int pointerCount = event.getPointerCount();// 獲取放在屏幕上的手指數(shù)量? ? ? ? for (int i = 0; i < pointerCount; i++) {
? ? ? ? ? ? x += event.getX(i);
? ? ? ? ? ? y += event.getY(i);
? ? ? ? }
? ? ? ? x /= pointerCount;
? ? ? ? y /= pointerCount;
? ? ? ? if (mLastPinterCount != pointerCount) {
? ? ? ? ? ? isCanDrag = false;
? ? ? ? ? ? mLastX = x;
? ? ? ? ? ? mLastY = y;
? ? ? ? }
? ? ? ? mLastPinterCount = pointerCount;
? ? ? ? switch (event.getAction()) {
? ? ? ? ? ? case MotionEvent.ACTION_MOVE:
? ? ? ? ? ? ? ? float dx = x - mLastX;
? ? ? ? ? ? ? ? float dy = y - mLastY;
? ? ? ? ? ? ? ? isCanDrag = isMove(dx, dy);
? ? ? ? ? ? ? ? if (isCanDrag) {
? ? ? ? ? ? ? ? ? ? RectF rectf = getMatrixRectf();
? ? ? ? ? ? ? ? ? ? if (null != getDrawable()) {
? ? ? ? ? ? ? ? ? ? ? ? isCheckLeft = isCheckTop = true;
? ? ? ? ? ? ? ? ? ? ? ? if (rectf.width() < getWidth()) {// 如果圖片寬度小于控件寬度(屏幕寬度)不允許橫向移動(dòng)? ? ? ? ? ? ? ? ? ? ? ? ? ? dx = 0;
? ? ? ? ? ? ? ? ? ? ? ? ? ? isCheckLeft = false;
? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? ? ? if (rectf.height() < getHeight()) {// 如果圖片高度小于控件高度(屏幕高度)不允許縱向移動(dòng)? ? ? ? ? ? ? ? ? ? ? ? ? ? dy = 0;
? ? ? ? ? ? ? ? ? ? ? ? ? ? isCheckTop = false;
? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? ? ? mScaleMatrix.postTranslate(dx, dy);
? ? ? ? ? ? ? ? ? ? ? ? checkTranslateWithBorder();
? ? ? ? ? ? ? ? ? ? ? ? setImageMatrix(mScaleMatrix);
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? mLastX = x;
? ? ? ? ? ? ? ? mLastY = y;
? ? ? ? ? ? ? ? break;
? ? ? ? ? ? case MotionEvent.ACTION_UP:
? ? ? ? ? ? case MotionEvent.ACTION_CANCEL:
? ? ? ? ? ? ? ? mLastPinterCount = 0;
? ? ? ? ? ? ? ? break;
? ? ? ? }
? ? ? ? return true;
? ? }
? ? /**
? ? * 移動(dòng)圖片時(shí)進(jìn)行邊界檢查
? ? */? ? privatevoidcheckTranslateWithBorder(){
? ? ? ? RectF rectf = getMatrixRectf();
? ? ? ? float delX = 0;
? ? ? ? float delY = 0;
? ? ? ? int width = getWidth();
? ? ? ? int height = getHeight();
? ? ? ? if (rectf.top > 0 && isCheckTop) {
? ? ? ? ? ? delY = -rectf.top;
? ? ? ? }
? ? ? ? if (rectf.bottom < height && isCheckTop) {
? ? ? ? ? ? delY = height - rectf.bottom;
? ? ? ? }
? ? ? ? if (rectf.left > 0 && isCheckLeft) {
? ? ? ? ? ? delX = -rectf.left;
? ? ? ? }
? ? ? ? if (rectf.right < width && isCheckLeft) {
? ? ? ? ? ? delX = width - rectf.right;
? ? ? ? }
? ? ? ? mScaleMatrix.postTranslate(delX, delY);
? ? }
? ? // 判斷是否有移動(dòng)? ? privatebooleanisMove(floatx,floaty){
? ? ? ? return Math.sqrt(x * x + y * y) > mTouchSlop;
? ? }
? ? /**
? ? * 獲取圖片的位置
? ? */? ? privateRectFgetMatrixRectf(){
? ? ? ? Matrix matrix = mScaleMatrix;
? ? ? ? RectF recft = new RectF();
? ? ? ? if (getDrawable() != null) {
? ? ? ? ? ? recft.set(0, 0, getDrawable().getIntrinsicWidth(), getDrawable().getIntrinsicHeight());
? ? ? ? ? ? matrix.mapRect(recft);
? ? ? ? }
? ? ? ? return recft;
? ? }
? ? // 獲取當(dāng)前圖片的縮放值? ? privatefloatgetScale(){
? ? ? ? float values[] = new float[9];
? ? ? ? mScaleMatrix.getValues(values);
? ? ? ? return values[Matrix.MSCALE_X];
? ? }
}