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


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


查看源代碼

[java]  view plain copy 在CODE上查看代碼片 派生到我的代碼片
  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 plain copy 在CODE上查看代碼片 派生到我的代碼片
  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 plain copy 在CODE上查看代碼片 派生到我的代碼片
  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 plain copy 在CODE上查看代碼片 派生到我的代碼片
  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拖動類以及實現幾個拖動效果就更加有幫助了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM