package com.netease.nim.uikit.common.ui.imageview; /* * Copyright 2012 Laurence Dawson * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* * This class is based upon the file ImageViewTouchBase.java which can be found at: * https://dl-ssl.google.com/dl/googlesource/git-repo/repo * * Copyright (C) 2009 The Android Open Source Project */ import android.content.Context; import android.util.AttributeSet; import android.util.Log; import android.view.GestureDetector; import android.view.MotionEvent; import android.view.ScaleGestureDetector; public class MultiTouchZoomableImageView extends BaseZoomableImageView { // Scale and gesture listeners for the view private GestureDetector mGestureDetector; private ScaleGestureDetector mScaleDetector; protected boolean transIgnoreScale = false; private boolean scaleRecognized = false; // Programatic entry point public MultiTouchZoomableImageView(Context context) { super(context); initMultiTouchZoomableImageView( context ); } // XML entry point public MultiTouchZoomableImageView(Context context, AttributeSet attrs) { super(context, attrs); initMultiTouchZoomableImageView( context ); } // Setup the view protected void initMultiTouchZoomableImageView( Context context) { // Setup the gesture and scale listeners mScaleDetector = new ScaleGestureDetector( context, new ScaleListener() ); mGestureDetector = new GestureDetector(context, new MyGestureListener()); } // Adjusts the zoom of the view class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener { @Override public boolean onScale( ScaleGestureDetector detector ) { // Check if the detector is in progress in order to proceed if(detector!=null && detector.isInProgress() ){ try{ // Grab the scale float targetScale = getScale() * detector.getScaleFactor(); // Correct for the min scale targetScale = Math.min( maxZoom(), Math.max( targetScale, 1.0f) ); // Zoom and invalidate the view zoomTo( targetScale, detector.getFocusX(), detector.getFocusY() ); invalidate(); scaleRecognized = true; return true; }catch(IllegalArgumentException e){ e.printStackTrace(); } } return false; } } // Handles taps and scrolls of the view private class MyGestureListener extends GestureDetector.SimpleOnGestureListener { @Override public boolean onSingleTapConfirmed(MotionEvent e) { if(mImageGestureListener!=null){ mImageGestureListener.onImageGestureSingleTapConfirmed(); return false; } return super.onSingleTapConfirmed(e); } public void onLongPress(MotionEvent e) { if(mImageGestureListener!=null && !scaleRecognized){ mImageGestureListener.onImageGestureLongPress(); } } @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { try { // Skip if there are multiple points of contact if ( (e1!=null&&e1.getPointerCount() > 1) || (e2!=null&&e2.getPointerCount() > 1) || (mScaleDetector!=null && mScaleDetector.isInProgress()) ) return false; // Scroll the bitmap if (transIgnoreScale || getScale() > zoomDefault()) { stopFling(); postTranslate(-distanceX, -distanceY); if (isScrollOver(distanceX)) { if (mViewPager!=null) { mViewPager.requestDisallowInterceptTouchEvent(false); } } else { if (mViewPager!=null) { mViewPager.requestDisallowInterceptTouchEvent(true); } } center(true, true, false); } else { if (mViewPager!=null) { mViewPager.requestDisallowInterceptTouchEvent(false); } } } catch (IllegalArgumentException e) { e.printStackTrace(); } // Default case return true; } @Override public boolean onDoubleTap(MotionEvent e) { // If the zoom is over 1x, reset to 1x if ( getScale() != zoomDefault() ){ zoomTo(zoomDefault()); } // If the zoom is default, zoom into 2x else zoomTo(zoomDefault()*3, e.getX(), e.getY(),200); // Always true as double tap was performed return true; } @Override public boolean onFling( MotionEvent e1, MotionEvent e2, float velocityX, float velocityY ) { if ( (e1!=null&&e1.getPointerCount() > 1) || (e2!=null&&e2.getPointerCount() > 1) ) return false; if ( mScaleDetector.isInProgress() ) return false; final float FLING_MIN_DISTANCE = 100; final float FLING_MIN_VELOCITY = 200; if (e1.getX() - e2.getX() > FLING_MIN_DISTANCE && Math.abs(velocityX) > FLING_MIN_VELOCITY) { Log.i("MultiTouchZoomableImageView","Fling Left"); } else if (e2.getX() - e1.getX() > FLING_MIN_DISTANCE && Math.abs(velocityX) > FLING_MIN_VELOCITY) { Log.i("MultiTouchZoomableImageView","Fling Right"); } else if (e1.getY() - e2.getY() > FLING_MIN_DISTANCE && Math.abs(velocityY) > FLING_MIN_VELOCITY) { Log.i("MultiTouchZoomableImageView","Fling Up"); } else if (e2.getY() - e1.getY() > FLING_MIN_DISTANCE && Math.abs(velocityY) > FLING_MIN_VELOCITY) { Log.i("MultiTouchZoomableImageView","Fling Down"); if (!transIgnoreScale && getScale() <= zoomDefault()) { mImageGestureListener.onImageGestureFlingDown(); return true; } } try { float diffX = e2.getX() - e1.getX(); float diffY = e2.getY() - e1.getY(); if ( Math.abs( velocityX ) > 800 || Math.abs( velocityY ) > 800 ) { scrollBy( diffX / 2, diffY / 2, 300 ); invalidate(); } } catch(NullPointerException e){ } catch (IllegalArgumentException e) { e.printStackTrace(); } return super.onFling( e1, e2, velocityX, velocityY ); } } @Override public boolean onTouchEvent(MotionEvent event) { try { if (mViewPager!=null) { switch (event.getAction()) { case MotionEvent.ACTION_MOVE: mViewPager.requestDisallowInterceptTouchEvent(true); break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: mViewPager.requestDisallowInterceptTouchEvent(false); scaleRecognized = false; break; } } // If the bitmap was set, check the scale and gesture detectors if(mBitmap!=null){ // Check the scale detector mScaleDetector.onTouchEvent(event); // Check the gesture detector if(!mScaleDetector.isInProgress()) mGestureDetector.onTouchEvent(event); } else { mImageGestureListener.onImageGestureSingleTapConfirmed(); return false; } } catch (Exception e) { e.printStackTrace(); } return true; } }