android 布局之滑動探究 scrollTo 和 scrollBy 方法使用說明

來源:互聯網
上載者:User

標籤:

涉及到滑動,就涉及到VIEW,大家都知道,android的UI介面都是由一個一個的View以及View的衍生類別組成,View作為基類,而常用的布局裡面的各種布局就是它派生出來的ViewGroup的子類,ViewGroup作為各個組件的容器搭建了整體的UI。以下是android UI的結構示:

查看源碼

[java] view plaincopy 
  1. /** 
  2.  * Implement this to do your drawing. 
  3.  * 
  4.  * @param canvas the canvas on which the background will be drawn 
  5.  */  
  6. protected void onDraw(Canvas canvas) {  
  7. }  

可以發現,View的實現一般是通過繪製onDraw方法進行,如果你要改變它的介面可以重寫onDraw,達到你的效果,在源碼中,你找不到    

 

 

[java] view plaincopy 
  1. public void addView(View child) {  
  2.         addView(child, -1);  
  3.     }  

這個方法,因為它不知道,只有在它的衍生類別例如ViewGroup中會有這個方式去添加子布局。

 

而ViewGroup作為一個組件容器,它可以包含任何組件,可是你必須重寫他的onLayout() 方法和 onMeasure()來設定容器布局的位置和繪製它的大小才能正常顯示。

 

 

首先 ,我們必須明白在Android View視圖是沒有邊界的,Canvas是沒有邊界的,只不過我們通過繪製特定的View時對 Canvas對象進行了一定的操作,例如 : translate(平移)、clipRect(剪下)等,以便達到我們的對該Canvas對象繪製的要求 ,我們可以將這種無邊界的視圖稱為“視圖座標”-----它不受物理螢幕限制。通常我們所理解的一個Layout布局檔案只是該視圖的顯示地區,超過了這個顯示地區將不能顯示到父視圖的地區中 ,對應的,我們可以將這種有邊界的視圖稱為“布局座標”------ 父視圖給子視圖分配的布局(layout)大小。而且, 一個視圖的在螢幕的起始座標位於視圖座標起始處,如所示。


其實是相對於父類別檢視的左上方座標為原點(0,0),而不是整體ViewGroup的左上方為原點。

由於布局座標只能顯示特定的一塊內容,所以我們只有移動布局座標的座標原點就可以將視圖座標的任何位置顯示出來。

(註:例如cocos2D的布局就和android的布局座標原點座標不一樣,是左下角會原點,所以會有所差異。)

 

這裡就大致提下View和ViewGroup,(網上很多大神都對這塊進行了分析,這裡只是做了少量摘抄記錄)目的是為了引出今天的主角scrollTo 和 scrollBy。

 

查看下源碼可以發現:

 

[java] view plaincopy 
  1. <span style="font-family:SimSun;font-size:14px;">  /** 
  2.      * The offset, in pixels, by which the content of this view is scrolled 
  3.      * horizontally. 
  4.      * {@hide} 
  5.      */  
  6.     @ViewDebug.ExportedProperty(category = "scrolling")  
  7.     protected int mScrollX;  
  8.     /** 
  9.      * The offset, in pixels, by which the content of this view is scrolled 
  10.      * vertically. 
  11.      * {@hide} 
  12.      */  
  13.     @ViewDebug.ExportedProperty(category = "scrolling")  
  14.     protected int mScrollY;  
  15.     /** 
  16.      * Return the scrolled left position of this view. This is the left edge of 
  17.      * the displayed part of your view. You do not need to draw any pixels 
  18.      * farther left, since those are outside of the frame of your view on 
  19.      * screen. 
  20.      * 
  21.      * @return The left edge of the displayed part of your view, in pixels. 
  22.      */  
  23.     public final int getScrollX() {  
  24.         return mScrollX;  
  25.     }  
  26.   
  27.     /** 
  28.      * Return the scrolled top position of this view. This is the top edge of 
  29.      * the displayed part of your view. You do not need to draw any pixels above 
  30.      * it, since those are outside of the frame of your view on screen. 
  31.      * 
  32.      * @return The top edge of the displayed part of your view, in pixels. 
  33.      */  
  34.     public final int getScrollY() {  
  35.         return mScrollY;  
  36.     }</span>  


mScrollX:表示離視圖起始位置的x水平方向的位移量

 

mScrollY:表示離視圖起始位置的y垂直方向的位移量

分別通過getScrollX() 和getScrollY()方法獲得。

注意:mScrollX和mScrollY指的並不是座標,而是位移量。

 

 

[java] view plaincopy 
  1. <span style="font-family:SimSun;font-size:14px;"> /** 
  2.      * Set the scrolled position of your view. This will cause a call to 
  3.      * {@link #onScrollChanged(int, int, int, int)} and the view will be 
  4.      * invalidated. 
  5.      * @param x the x position to scroll to 
  6.      * @param y the y position to scroll to 
  7.      */  
  8.     public void scrollTo(int x, int y) {  
  9.         if (mScrollX != x || mScrollY != y) {  
  10.             int oldX = mScrollX;  
  11.             int oldY = mScrollY;  
  12.             mScrollX = x;  
  13.             mScrollY = y;  
  14.             invalidateParentCaches();  
  15.             onScrollChanged(mScrollX, mScrollY, oldX, oldY);  
  16.             if (!awakenScrollBars()) {  
  17.                 postInvalidateOnAnimation();  
  18.             }  
  19.         }  
  20.     }  
  21.   
  22.     /** 
  23.      * Move the scrolled position of your view. This will cause a call to 
  24.      * {@link #onScrollChanged(int, int, int, int)} and the view will be 
  25.      * invalidated. 
  26.      * @param x the amount of pixels to scroll by horizontally 
  27.      * @param y the amount of pixels to scroll by vertically 
  28.      */  
  29.     public void scrollBy(int x, int y) {  
  30.         scrollTo(mScrollX + x, mScrollY + y);  
  31.     }</span>  


從以上的代碼可以看出,scrollTo 和 scrollBy區別,其實2者的效果是一樣的。

 

 

scrollTo(int x,int y):

如果位移位置發生了改變,就會給mScrollX和mScrollY賦新值,改變當前位置。

注意:x,y代表的不是座標點,而是位移量。

例如:

我要移動view到座標點(100,100),那麼我的位移量就是(0,,0)  - (100,100) = (-100 ,-100)  ,我就要執行view.scrollTo(-100,-100),達到這個效果。

 

scrollBy(int x,int y):

從源碼中看出,它實際上是調用了scrollTo(mScrollX + x, mScrollY + y);

mScrollX + x和mScrollY + y,即表示在原先位移的基礎上在發生位移,通俗的說就是相對我們當前位置位移。

根據父類VIEW裡面移動,如果移動到了超出的地方,就不會顯示。

查看上文中的你就會知道大概。

 

下面通過一個小例子瞭解下這2個方法之間的的使用,

如下:

核心代碼就是本文講的2個方法,這裡就列出代碼了。

提供一個簡單的DEMO:

這裡大致搞清楚了這2個方法後,對後面的Scroller拖動類以及實現幾個拖動效果就更加有協助了。

著作權聲明:本文為博主原創文章,未經博主允許不得轉載。

android 布局之滑動探究 scrollTo 和 scrollBy 方法使用說明

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.