天天看點

自定義View--滾動View

       實作這麼一個效果,一個布局中有一個View,那個View會随着我們手指的拖動而滑動,這種效果該如何實作? 

  我們第一反應應該是自定義一個DragView類繼承View,然後重寫onTouchEvent()方法,然後根據我們手指滑動的軌迹來調整DragView的顯示位置。沒錯,就是這個思路,下面我們來實作一下。

1     private float lastX;
 2     private float lastY;
 3     @Override
 4     public boolean onTouchEvent(MotionEvent event) {
 5 
 6         switch (event.getAction()) {
 7             case MotionEvent.ACTION_DOWN:
 8                 lastX = event.getRawX();
 9                 lastY = event.getRawY();
10                 break;
11             case MotionEvent.ACTION_UP:
12                 break;
13             case MotionEvent.ACTION_MOVE:
14                 float dx = event.getRawX() - lastX;
15                 float dy = event.getRawY() - lastY;
16                 //控制View移動的方法
17                 move(dx, dy);
18                 lastX = event.getRawX();
19                 lastY = event.getRawY();
20 
21                 break;
22 
23         }
24 
25         return true;
26 
27     }      

注意這裡getRawX()和getX()的差別,Raw是“未經處理”的意思,getRawX()擷取的是觸點相對于整個螢幕的坐标,以螢幕左上角為原點。而getX()是經過處理後的坐标,aa也就是觸點相對于目前View的坐标,是以View的左上角為坐标原點。

  很簡短的一段邏輯,記錄手指每次移動的相對距離,然後調用move方法來移動控件,最後 return true代表這個控件消費了事件,如果不了解的同學需要先看這篇文章Android事件分發機制,來了解onTouchEvent是如何被調用的,然後再往下看。 

  接下來就是move方法的實作,我們實作View滑動的思路有3種:第1種就是改變View的屬性,類似于屬性動畫的原理,可以看看這篇文章:Android動畫原理;第2種是改變View的布局參數來實作滑動;第3種是使用View的scrollBy方法來實作滑動,我們先來看第一種的實作。

1  private void move(float dx, float dy) {
2         setTranslationX(getTranslationX()+dx);
3         setTranslationY(getTranslationY()+dy);
4     }      

  這裡是依靠重新設定View的TranslationX屬性值來實作滑動,我們看看效果。 

  效果還不錯,我們試試另一種方法,就是改變布局來實作滑動

1 private void move(float dx, float dy) {
2         setLeft((int) (getLeft()+dx));
3         setRight((int) (getRight()+dx));
4         setTop((int) (getTop()+dy));
5         setBottom((int) (getBottom()+dy));
6     }      

  效果和上圖一樣。最後我們看用scrollBy()來實作的滑動

1 private void move(float dx, float dy) {
2         //這裡要用負數,因為滑動的是布局的邊框,正好和内容的滑動方向相反
3         int x = (int) -dx;
4         int y = (int) -dy;
5         this.scrollBy(x, y);
6     }      

  結果居然沒有滑動效果!後來才知道,原來這個是滑動View的内容,而不是View本身。是以我們在View上畫個小點就能看出來他是怎麼工作的了。 

  果然,隻有小點在随着滑動,也就是View的内容。是以我們有内容滑動的時候可以用srcollBy或者srcollTo,如果View本身要滑動上面兩種方法是很好的選擇。

代碼位址:https://github.com/linghu88/mScrollview

繼續閱讀