天天看點

解析6種常用View 的滑動方法

  > view 的滑動是android 實作自定義控件的基礎,實作view 滑動有很多種方法,在這裡主要講解6 種滑動方法,分别是layout()、offsetleftandright()與offsettopandbottom()、layoutparams、動畫、scollto 與scollby,以及scroller。

  view 的滑動是android 實作自定義控件的基礎,同時在開發中我們也難免會遇到view 的滑動處理。其實不管是哪種滑動方式,其基本思想都是類似的:當點選事件傳到view 時,系統記下觸摸點的坐标,手指移動時系統記下移動後觸摸的坐标并算出偏移量,并通過偏移量來修改view 的坐标。實作view 滑動有很多種方法,在這裡主要講解6 種滑動方法,分别是layout()、offsetleftandright()與offsettopandbottom()、layoutparams、動畫、scollto 與scollby,以及scroller。

  view 進行繪制的時候會調用onlayout()方法來設定顯示的位置,是以我們同樣也可以通過修改view 的left、top、right、bottom 這4 種屬性來控制view 的坐标。首先我們要自定義一個view,在ontouchevent()方法中擷取觸摸點的坐标,代碼如下所示:

  接下來我們在action_move 事件中計算偏移量,再調用layout()方法重新放置這個自定義view 的位置即可。

  在每次移動時都會調用layout()方法對螢幕重新布局,進而達到移動view 的效果。自定義view,customview 的全部代碼如下所示:

  随後,我們在布局中引用自定義view 就可以了。

  運作程式,效果如圖1 所示。圖1 中的方塊就是我們自定義的customview,它會随着我們手指的滑動改變自己的位置。

          

解析6種常用View 的滑動方法

                 圖1 view 的滑動

  這兩種方法和layout()方法的效果差不多,其使用方式也差不多。我們将action_move中的代碼替換成如下代碼:

  layoutparams 主要儲存了一個view 的布局參數,是以我們可以通過layoutparams 來改變view 的布局參數進而達到改變view 位置的效果。同樣,我們将action_move 中的代碼替換成如下代碼:

  因為父控件是linearlayout,是以我們用了linearlayout.layoutparams。如果父控件是relativelayout,則要使用relativelayout.layoutparams。除了使用布局的layoutparams 外,我們還可以用viewgroup.marginlayoutparams 來實作:

  可以采用view 動畫來移動,在res 目錄建立anim 檔案夾并建立translate.xml:

  接下來在java 代碼中調用就好了,代碼如下所示:

  運作程式,我們設定的小方塊會向右平移300 像素,然後又會回到原來的位置。為了解決這個問題,我們需要在translate.xml 中加上fillafter="true",代碼如下所示。運作代碼後會發現,方塊向右平移300 像素後就停留在目前位置了。

  需要注意的是,view 動畫并不能改變view 的位置參數。如果對一個button 進行如上的平移動畫操作,當button 平移300 像素停留在目前位置時,我們點選這個button 并不會觸發點選事件,但在我們點選這個button 的原始位置時卻觸發了點選事件。對于系統來說這個button 并沒有改變原有的位置,是以我們點選其他位置當然不會觸發這個button 的點選事件。在android3.0 時出現的屬性動畫解決了上述問題,因為它不僅可以執行動畫,還能夠改變view 的位置參數。當然,這裡使用屬性動畫移動那就更簡單了,我們讓customview 在1000ms 内沿着x 軸向右平移300 像素,代碼如下所示。

  scrollto(x,y)表示移動到一個具體的坐标點,而scrollby(dx,dy)則表示移動的增量為dx、dy。其中,scollby 最終也是要調用scollto 的。view.java 的scollby 和scollto 的源碼如下所示:

scollto、scollby 移動的是view 的内容,如果在viewgroup 中使用,則是移動其所有的子view。我們将action_move 中的代碼替換成如下代碼:

  這裡若要實作customview 随手指移動的效果,就需要将偏移量設定為負值。為什麼要設定為負值呢?下面具體講解一下。假設我們正用放大鏡來看報紙,放大鏡用來顯示字的内容。同樣我們可以把放大鏡看作我們的手機螢幕,它們都是負責顯示内容的;而報紙則可以被看作螢幕下的畫布,它們都是用來提供内容的。放大鏡外的内容,也就是報紙的内容不會随着放大鏡的移動而消失,它一直存在。同樣,我們的手機螢幕看不到的視圖并不代表其不存在,如圖2 所示。

  

解析6種常用View 的滑動方法

                      圖2 初始情況

  畫布上有3 個控件,即button、edittext 和swichbutton。隻有button 在手機螢幕中顯示,它的android 坐标為(60,60) 。現在我們調用scrollby(50,50),按照字面的意思,這個button 應該會在螢幕右下側,可是事實并非如此。如果我們調用scrollby(50,50),裡面的參數都是正值,我們的手機螢幕向x 軸正方向,也就是向右邊平移50,然後手機螢幕向y 軸正方向,也就是向下方平移50,平移後的效果如圖3所示。

解析6種常用View 的滑動方法

                  圖3 調用scrollby(50,50)後

  雖然我們設定的數值是正數并且在x 軸和y 軸的正方向移動,但button 卻向相反方向移動了,這是參考對象不同導緻的差異。是以我們用scrollby 方法的時候要設定負數才會達到自己想要的效果。

  我們在用scollto/scollby 方法進行滑動時,這個過程是瞬間完成的,是以使用者體驗不大好。這裡我們可以使用scroller 來實作有過渡效果的滑動,這個過程不是瞬間完成的,而是在一定的時間間隔内完成的。scroller 本身是不能實作view 的滑動的,它需要與view 的computescroll()

方法配合才能實作彈性滑動的效果。在這裡我們實作customview 平滑地向右移動。首先我們要初始化scroller,代碼如下所示:

  接下來重寫computescroll()方法,系統會在繪制view 的時候在draw()方法中調用該方法。在這個方法中,我們調用父類的scrollto()方法并通過scroller 來不斷擷取目前的滾動值,每滑動一小段距離我們就調用invalidate()方法不斷地進行重繪,重繪就會調用computescroll()方法,這樣我們通過不斷地移動一個小的距離并連貫起來就實作了平滑移動的效果。

  我們在customview 中寫一個smoothscrollto 方法,調用scroller 的startscroll()方法,在2000ms 内沿x 軸平移delta 像素,代碼如下所示:

  最後我們在viewslideactivity.java 中調用customview 的smoothscrollto()方法。這裡我們設定customview 沿着x 軸向右平移400 像素。

 

  想及時獲得更多精彩文章,可在微信中搜尋“博文視點”或者掃描下方二維碼并關注。

                  

解析6種常用View 的滑動方法

繼續閱讀