1. 程式人生 > >Android 7.0 Gallery圖庫源碼分析4 - SlotView手勢監聽及頁面跳轉

Android 7.0 Gallery圖庫源碼分析4 - SlotView手勢監聽及頁面跳轉

ofo 自帶 end follow mat views mha creat 找到

上篇文章講了初始化View時會實例化一個SlotView並監聽其事件,至於它是怎麽實現的,用的是Android自帶的GestureDetector。

GestureDetector是Android自帶的用來監聽各種用戶手勢的的一個類,比如監聽單擊、雙擊和長按等操作。關於GestureDetector的詳解可以參考此文章用戶手勢檢測-GestureDetector使用詳解

SlotView中定義了一個GestureDetector。

1 private final GestureDetector mGestureDetector;
2 
3 public SlotView(AbstractGalleryActivity activity, Spec spec) {
4 //給GestureDetector傳入我們自定義的Listener接口 5 mGestureDetector = new GestureDetector(activity, new MyGestureListener()); 6 ...... 7 }

然後在onTouch中攔截SlotView的觸摸事件並交給GestureDetector處理

1    @Override
2     protected boolean onTouch(MotionEvent event) {
3         ......
4         mGestureDetector.onTouchEvent(event);
5 ...... 6 //必須返回true,不然監聽不到完整事件 7 return true; 8 }

至於GestureDetector的監聽事件怎麽和SlotView的Listener綁定到一起的?我們看一下自定義的MyGestureListener接口,它就是實現了GestureDetector的OnGestureListener接口。

 1 private class MyGestureListener implements GestureDetector.OnGestureListener {
 2         ......
3 //點擊一次 4 @Override 5 public boolean onSingleTapUp(MotionEvent e) { 6 ...... 7 //獲取點擊的相冊索引 8 int index = mLayout.getSlotIndexByPosition(e.getX(), e.getY()); 9 //處理點擊事件 10 if (index != INDEX_NONE) mListener.onSingleTapUp(index); 11 return true; 12 } 13 }

從上述代碼可以看出當GestureDetector監測到點擊事件時會回調onSingleTapUp方法,在這個方法裏我們對點擊事件進行處理。上面的mListener就是SlotView中的Listener接口,這樣就將GestureDetector的監聽事件和SlotView的Listener綁定到一起了。所以每次接收到觸摸事件時最終都會傳給SlotView的Listener處理,至於SlotView的Listener具體怎麽實現每個ActivityState頁面都不一樣,比如AlbumSetPage中就是如下實現的,最後會調用AlbumSetPage對應的方法來處理觸摸事件

 1 private void initializeViews() {
 2     mSlotView.setListener(new SlotView.SimpleListener() {
 3             @Override
 4             public void onDown(int index) {
 5                 AlbumSetPage.this.onDown(index);
 6             }
 7 
 8             @Override
 9             public void onUp(boolean followedByLongPress) {
10                 AlbumSetPage.this.onUp(followedByLongPress);
11             }
12 
13             @Override
14             public void onSingleTapUp(int slotIndex) {
15                 AlbumSetPage.this.onSingleTapUp(slotIndex);
16             }
17 
18             @Override
19             public void onLongTap(int slotIndex) {
20                 AlbumSetPage.this.onLongTap(slotIndex);
21             }
22         });
23 }

現在手勢監聽流程已經講解完了,下面講一下界面的跳轉,我們找到AlbumSetPage的onSingleTapUp方法

 1 public void onSingleTapUp(int slotIndex) {
 2         if (mSelectionManager.inSelectionMode()) {
 3             ......
 4         } else {
 5             //顯示動畫
 6             mAlbumSetView.setPressedIndex(slotIndex);
 7             mAlbumSetView.setPressedUp();
 8             //通過Handler發送消息,msg.arg1是slotIndex,也就是點擊的相冊索引
 9             mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_PICK_ALBUM, slotIndex, 0),
10                     FadeTexture.DURATION);
11         }
12     }

Handler的handleMessage方法在AlbumSetPage的onCreate方法中

 1 mHandler = new SynchronizedHandler(mActivity.getGLRoot()) {
 2             @Override
 3             public void handleMessage(Message message) {
 4                 switch (message.what) {
 5                     case MSG_PICK_ALBUM: {
 6                         //跳轉到相冊
 7                         pickAlbum(message.arg1);
 8                         break;
 9                     }
10                     default: throw new AssertionError(message.what);
11                 }
12             }
13         };

我們看一下pickAlbum的代碼,

 1 private void pickAlbum(int slotIndex) {
 2     ......
 3     if (mGetAlbum && targetSet.isLeafAlbum()) {
 4             ......
 5         } else if (targetSet.getSubMediaSetCount() > 0) {
 6             ......
 7         } else {
 8             ......
 9             data.putString(AlbumPage.KEY_MEDIA_PATH, mediaPath);
10 
11             // We only show cluster menu in the first AlbumPage in stack
12             boolean inAlbum = mActivity.getStateManager().hasStateClass(AlbumPage.class);
13             data.putBoolean(AlbumPage.KEY_SHOW_CLUSTER_MENU, !inAlbum);
14             //通過StateManager跳轉到AlbumPage類中,跟應用的啟動流程差不多
15             mActivity.getStateManager().startStateForResult(
16                     AlbumPage.class, REQUEST_DO_ANIMATION, data);
17         }
18 }

通過上述代碼可以看出頁面Gallery的頁面跳轉都是通過StateManager來管理的。如果從相冊點擊進入某一張圖片,跳轉邏輯也跟著一樣,看下AlbumPage的handleMessage方法就知道了。

Android 7.0 Gallery圖庫源碼分析4 - SlotView手勢監聽及頁面跳轉