這期內(nèi)容當(dāng)中小編將會給大家?guī)碛嘘P(guān)ImageView如何在Android應(yīng)用中使用,文章內(nèi)容豐富且以專業(yè)的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。
成都創(chuàng)新互聯(lián)-專業(yè)網(wǎng)站定制、快速模板網(wǎng)站建設(shè)、高性價比石樓網(wǎng)站開發(fā)、企業(yè)建站全套包干低至880元,成熟完善的模板庫,直接使用。一站式石樓網(wǎng)站制作公司更省心,省錢,快速模板網(wǎng)站建設(shè)找我們,業(yè)務(wù)覆蓋石樓地區(qū)。費用合理售后完善,十載實體公司更值得信賴。
MatrixImageView類改改代碼了:
public class MatrixImageView extends ImageView { private static final int MODE_NONE = 190; private static final int MODE_DRAG = 468; private static final int MODE_ZOOM = 685; private int mode; private float startX, startY; private float midX, midY; private Matrix currMatrix, savedMatrix; private float preRotate, rotate; private float preSpacing; private GestureDetector detector; public MatrixImageView(Context context, AttributeSet attrs) { super(context, attrs); initView(); detector=new GestureDetector(context,onGestureListener); } private void initView() { mode = MODE_NONE; currMatrix = new Matrix(); savedMatrix = new Matrix(); DisplayMetrics dm = getResources().getDisplayMetrics(); Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.test); bitmap = Bitmap.createScaledBitmap(bitmap, dm.widthPixels, dm.heightPixels, true); setImageBitmap(bitmap); } @Override public boolean onTouchEvent(MotionEvent event) { return detector.onTouchEvent(event); } private GestureDetector.SimpleOnGestureListener onGestureListener=new GestureDetector.SimpleOnGestureListener(){ @Override public boolean onSingleTapUp(MotionEvent e) { Log.e("TAG", "====onSingleTapUp====="); return super.onSingleTapUp(e); } @Override public void onLongPress(MotionEvent e) { Log.e("TAG", "====onLongPress====="); super.onLongPress(e); } @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { Log.e("TAG", "====onScroll====="); Log.e("TAG", "distanceX===>"+distanceX); Log.e("TAG", "distanceY===>"+distanceY); return super.onScroll(e1, e2, distanceX, distanceY); } @Override public void onShowPress(MotionEvent e) { Log.e("TAG", "====onShowPress====="); super.onShowPress(e); } @Override public boolean onDown(MotionEvent e) { Log.e("TAG", "====onDown====="); return true; } @Override public boolean onDoubleTap(MotionEvent e) { Log.e("TAG", "====onDoubleTap====="); return super.onDoubleTap(e); } @Override public boolean onDoubleTapEvent(MotionEvent e) { Log.e("TAG", "====onDoubleTapEvent====="); return super.onDoubleTapEvent(e); } @Override public boolean onSingleTapConfirmed(MotionEvent e) { Log.e("TAG", "====onSingleTapConfirmed====="); return super.onSingleTapConfirmed(e); } @Override public boolean onContextClick(MotionEvent e) { Log.e("TAG", "====onContextClick====="); return super.onContextClick(e); } @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { Log.e("TAG", "====onFling====="); Log.e("TAG", "velocityX===>"+velocityX); Log.e("TAG", "velocityY===>"+velocityY); return super.onFling(e1, e2, velocityX, velocityY); } }; }
首先我們在構(gòu)造方法中創(chuàng)建一個手勢監(jiān)測器的對象GestureDetector:
public MatrixImageView(Context context, AttributeSet attrs) { super(context, attrs); initView(); detector=new GestureDetector(context,onGestureListener); }
GestureDetector既然是監(jiān)聽我們的手勢的工具類,那我們是不是得把我們得手勢交給它呢? 是的!! 于是我們在onTouchEvent中把事件交給GestureDetector:
@Override public boolean onTouchEvent(MotionEvent event) { return detector.onTouchEvent(event); }
那我們把事件交給了GestureDetector,GestureDetector處理完畢后我們怎么知道呢? 還記得我們創(chuàng)建GestureDetector對象的時候傳遞的參數(shù)嗎?
detector=new GestureDetector(context,onGestureListener);
我們傳遞給了GestureDetector一個onGestureListener對象,GestureDetector檢查完畢手勢后,會調(diào)用onGestureListener中的方法進(jìn)行回調(diào),我們只需要在onGestureListener對象的相應(yīng)方法中作出處理就可以了:
private GestureDetector.SimpleOnGestureListener onGestureListener=new GestureDetector.SimpleOnGestureListener(){ @Override public boolean onSingleTapUp(MotionEvent e) { Log.e(“TAG”, “====onSingleTapUp=====”); return super.onSingleTapUp(e); } @Override public void onLongPress(MotionEvent e) { Log.e("TAG", "====onLongPress====="); super.onLongPress(e); } @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { Log.e("TAG", "====onScroll====="); Log.e("TAG", "distanceX===>"+distanceX); Log.e("TAG", "distanceY===>"+distanceY); return super.onScroll(e1, e2, distanceX, distanceY); } @Override public void onShowPress(MotionEvent e) { Log.e("TAG", "====onShowPress====="); super.onShowPress(e); } @Override public boolean onDown(MotionEvent e) { Log.e("TAG", "====onDown====="); return super.onDown(e); } @Override public boolean onDoubleTap(MotionEvent e) { Log.e("TAG", "====onDoubleTap====="); return super.onDoubleTap(e); } @Override public boolean onDoubleTapEvent(MotionEvent e) { Log.e("TAG", "====onDoubleTapEvent====="); return super.onDoubleTapEvent(e); } @Override public boolean onSingleTapConfirmed(MotionEvent e) { Log.e("TAG", "====onSingleTapConfirmed====="); return super.onSingleTapConfirmed(e); } @Override public boolean onContextClick(MotionEvent e) { Log.e("TAG", "====onContextClick====="); return super.onContextClick(e); } @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { Log.e("TAG", "====onFling====="); Log.e("TAG", "velocityX===>"+velocityX); Log.e("TAG", "velocityY===>"+velocityY); return super.onFling(e1, e2, velocityX, velocityY); } };
我們先不管其中方法啥時候調(diào)用,我們先重寫它的所有方法,然后打上log,看看我們手指操作后相應(yīng)的回調(diào),于是我們運行代碼:
是的,沒錯!就只是一張圖片,因為我們也只是顯示了一張圖片:
我們輕輕的點擊一下屏幕:
03-02 20:47:41.367 1798-1798/com.leo.gestureimageview E/TAG: ====onDown=====
03-02 20:47:41.466 1798-1798/com.leo.gestureimageview E/TAG: ====onShowPress=====
03-02 20:47:41.967 1798-1798/com.leo.gestureimageview E/TAG: ====onLongPress=====
輕輕的點擊一下屏幕:
我們可以看到log執(zhí)行順序:onDown->onShowPress->onLongPress
我們點擊屏幕按下,然后過一會再放開:
03-02 21:51:27.121 17138-17138/com.leo.gestureimageview E/TAG: ====onDown=====
03-02 21:51:27.222 17138-17138/com.leo.gestureimageview E/TAG: ====onShowPress=====
03-02 21:51:27.722 17138-17138/com.leo.gestureimageview E/TAG: ====onLongPress=====
我們滑動一下手指:
03-02 21:51:27.121 17138-17138/com.leo.gestureimageview E/TAG: ====onDown=====
03-02 21:51:27.222 17138-17138/com.leo.gestureimageview E/TAG: ====onShowPress=====
03-02 21:51:27.722 17138-17138/com.leo.gestureimageview E/TAG: ====onLongPress=====
不管我們怎么樣操作,打印的log總是這三個方法? 這是咋回事呢? 如果看到這里你有疑問的話,那我告訴你,你Android事件傳遞機(jī)制掌握的還不是很好,為什么這么說呢?? 下面我們帶著疑問看看源碼:
猜都可以猜到GestureDetector處理手勢的代碼肯定在onTouchEvent方法中,那么我們看一下onTouchEvent方法:
public boolean onTouchEvent(MotionEvent ev) { if (mDoubleTapListener != null) { boolean hadTapMessage = mHandler.hasMessages(TAP); if (hadTapMessage) mHandler.removeMessages(TAP); if ((mCurrentDownEvent != null) && (mPreviousUpEvent != null) && hadTapMessage && isConsideredDoubleTap(mCurrentDownEvent, mPreviousUpEvent, ev)) { // This is a second tap mIsDoubleTapping = true; // Give a callback with the first tap of the double-tap handled |= mDoubleTapListener.onDoubleTap(mCurrentDownEvent); // Give a callback with down event of the double-tap handled |= mDoubleTapListener.onDoubleTapEvent(ev); } else { // This is a first tap mHandler.sendEmptyMessageDelayed(TAP, DOUBLE_TAP_TIMEOUT); } } mDownFocusX = mLastFocusX = focusX; mDownFocusY = mLastFocusY = focusY; if (mCurrentDownEvent != null) { mCurrentDownEvent.recycle(); } mCurrentDownEvent = MotionEvent.obtain(ev); mAlwaysInTapRegion = true; mAlwaysInBiggerTapRegion = true; mStillDown = true; mInLongPress = false; mDeferConfirmSingleTap = false; if (mIsLongpressEnabled) { mHandler.removeMessages(LONG_PRESS); mHandler.sendEmptyMessageAtTime(LONG_PRESS, mCurrentDownEvent.getDownTime() + TAP_TIMEOUT + LONGPRESS_TIMEOUT); } mHandler.sendEmptyMessageAtTime(SHOW_PRESS, mCurrentDownEvent.getDownTime() + TAP_TIMEOUT); handled |= mListener.onDown(ev); break; }
代碼太多了,那為什么我們只收到了onDown、onShowPress、onLongPress這三個方法的回調(diào)呢?
我們知道,當(dāng)我們手指剛按下屏幕的時候,ACTION_DOWN會執(zhí)行,然后我們看到這么一行代碼:
handled |= mListener.onDown(ev);
mListener是我們傳遞的SimpleOnGestureListener,于是就看到了控制臺的第一個log:
03-02 21:51:29.706 17138-17138/com.leo.gestureimageview E/TAG: ====onDown=====
我們的onDown是打印了,然后handled |= mListener.onDown(ev);看一下我們返回的是什么值:
@Override public boolean onDown(MotionEvent e) { Log.e("TAG", "====onDown====="); return super.onDown(e); }
我們直接返回了super.onDown(e),接著我們看一下父類返回的是什么:
public boolean onDown(MotionEvent e) { return false; }
可以看到,父類直接返回了false,所以handled此時為false,然后當(dāng)ACTION_DOWN執(zhí)行完畢后,就回到了我們的自定義view中的onTouchEvent方法中了:
@Override public boolean onTouchEvent(MotionEvent event) { return detector.onTouchEvent(event); }
此時我們的view中的onTouchEvent 方法返回的是false,到了這里懂事件傳遞機(jī)制的小伙伴都懂,當(dāng)我們的onTouchEvent返回了false的話,后面的事件都將接收不到了,也就是說只能執(zhí)行ACTION_DOWN,那么有些小伙伴可能又要說了,那我把view的clickable或者longclickable設(shè)置成true,事件不就可以傳遞了么?
好的~! 我們試一試:
運行代碼,還是只打印了那三個方法,那這又是怎么回事呢? 還記得我們view的onTouchEvent方法么?我們是這么寫的:
@Override public boolean onTouchEvent(MotionEvent event) { return detector.onTouchEvent(event); }
如果改成這樣再試試:
@Override public boolean onTouchEvent(MotionEvent event) { detector.onTouchEvent(event); return super.onTouchEvent(event); }
拖動手指返回結(jié)果:
好啦~??! 終于看到我們久違的結(jié)果了,如果我們還是想用以前的寫法,把onTouchEvent的返回結(jié)果交給GestureDetector處理該怎么做呢?
@Override public boolean onTouchEvent(MotionEvent event) { return detector.onTouchEvent(event); }
我們只需要在回調(diào)方法的onDown中返回true即可:
@Override public boolean onDown(MotionEvent e) { Log.e("TAG", "====onDown====="); return true; }
我們再次運行代碼并拖動手指:
好啦~! 說了那么多不知道小伙伴們理解了沒?還是不理解的小伙伴可以去看看我前幾篇事件傳遞的博客,嘻嘻~我們還是快點往下走吧….
我們長按一下屏幕然后提起手指:
03-02 22:29:37.361 22104-22104/com.leo.gestureimageview E/TAG: ====onDown=====
03-02 22:29:37.367 22104-22104/com.leo.gestureimageview E/TAG: ====onSingleTapUp=====
03-02 22:29:37.663 22104-22104/com.leo.gestureimageview E/TAG: ====onSingleTapConfirmed=====
執(zhí)行了onDown=>onSingleTapUp=>onSingleTapConfirmed.
我們快速點擊一下屏幕:
03-02 22:31:48.603 22104-22104/com.leo.gestureimageview E/TAG: ====onDown=====
03-02 22:31:48.610 22104-22104/com.leo.gestureimageview E/TAG: ====onSingleTapUp=====
03-02 22:31:48.903 22104-22104/com.leo.gestureimageview E/TAG: ====onSingleTapConfirmed=====
執(zhí)行了onDown=>onSingleTapUp=>onSingleTapConfirmed.
然后我們再次滑動手指:
03-02 22:34:41.820 22104-22104/com.leo.gestureimageview E/TAG: ====onDown=====
03-02 22:34:41.920 22104-22104/com.leo.gestureimageview E/TAG: ====onShowPress=====
03-02 22:34:42.018 22104-22104/com.leo.gestureimageview E/TAG: ====onScroll=====
03-02 22:34:42.018 22104-22104/com.leo.gestureimageview E/TAG: distanceX===>-117.13138
03-02 22:34:42.018 22104-22104/com.leo.gestureimageview E/TAG: distanceY===>75.100464
03-02 22:34:42.036 22104-22104/com.leo.gestureimageview E/TAG: ====onScroll=====
03-02 22:34:42.036 22104-22104/com.leo.gestureimageview E/TAG: distanceX===>-75.859314
執(zhí)行順序:onDown=》onShowPress=》onScroll(很多次)
最后我們手指拖動距離長一點再快一點:
03-02 22:47:42.453 5103-5103/com.leo.gestureimageview E/TAG: distanceX===>-274.69336
03-02 22:47:42.453 5103-5103/com.leo.gestureimageview E/TAG: distanceY===>-0.34838867
03-02 22:47:42.460 5103-5103/com.leo.gestureimageview E/TAG: ====onFling=====
03-02 22:47:42.460 5103-5103/com.leo.gestureimageview E/TAG: velocityX===>27284.943
03-02 22:47:42.460 5103-5103/com.leo.gestureimageview E/TAG: velocityY===>-95.6131
前 面還有一段log沒給出了,調(diào)用方法順序為:onDown=》onShowPress=》onScroll(很多次)=》最后松開手指的時候onFling();
好了~! 到這里,我們的回調(diào)方法中還有幾個沒有被調(diào)用,就是監(jiān)聽雙擊事件的時候,于是我們雙擊屏幕:
03-02 22:50:34.786 5103-5103/com.leo.gestureimageview E/TAG: ====onDown=====
03-02 22:50:34.793 5103-5103/com.leo.gestureimageview E/TAG: ====onSingleTapUp=====
03-02 22:50:34.924 5103-5103/com.leo.gestureimageview E/TAG: ====onDoubleTap=====
03-02 22:50:34.924 5103-5103/com.leo.gestureimageview E/TAG: ====onDoubleTapEvent=====
03-02 22:50:34.924 5103-5103/com.leo.gestureimageview E/TAG: ====onDown=====
03-02 22:50:34.932 5103-5103/com.leo.gestureimageview E/TAG: ====onDoubleTapEvent=====
我們雙擊屏幕執(zhí)行的方法為:
onDown=>onSingleTapUp=>onDoubleTap=>onDoubleTapEvent=>onDoubleTapEvent
可見,執(zhí)行了一次onDoubleTap,兩次onDoubleTapEvent
好啦~! 看完了SimpleOnGestureListener中所有方法的回調(diào),我們反過來再看一遍這些回調(diào)方法:
好啦~!說了那么api內(nèi)容,下面寫個小例子用一下GestureDetector:
package com.leo.gestureimageview; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Matrix; import android.util.AttributeSet; import android.util.DisplayMetrics; import android.util.Log; import android.view.GestureDetector; import android.view.MotionEvent; import android.widget.ImageView; public class MatrixImageView extends ImageView { private Matrix currMatrix; private GestureDetector detector; public MatrixImageView(Context context, AttributeSet attrs) { super(context, attrs); initView(); detector=new GestureDetector(context,onGestureListener); } private void initView() { currMatrix = new Matrix(); DisplayMetrics dm = getResources().getDisplayMetrics(); Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.test); bitmap = Bitmap.createScaledBitmap(bitmap, dm.widthPixels, dm.heightPixels, true); setImageBitmap(bitmap); } @Override public boolean onTouchEvent(MotionEvent event) { return detector.onTouchEvent(event); } private float currX; private float currY; private GestureDetector.SimpleOnGestureListener onGestureListener=new GestureDetector.SimpleOnGestureListener(){ @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { Log.e("TAG", "====onScroll====="); Log.e("TAG", "distanceX===>"+distanceX); Log.e("TAG", "distanceY===>"+distanceY); currX-=distanceX; currY-=distanceY; currMatrix.reset(); currMatrix.postTranslate(currX,currY); setImageMatrix(currMatrix); return super.onScroll(e1, e2, distanceX, distanceY); } }; }
上述就是小編為大家分享的ImageView如何在Android應(yīng)用中使用了,如果剛好有類似的疑惑,不妨參照上述分析進(jìn)行理解。如果想知道更多相關(guān)知識,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。