Android實(shí)現(xiàn)ImageView圖片雙擊放大及縮小

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];

? ? }

}

?著作權(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)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

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