国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統 > Android > 正文

Android View移動的3種方式總結

2019-12-12 05:15:23
字體:
來源:轉載
供稿:網友

前言

在Android開發中,View一直是Android開發人員的一塊心病,一方面想要進階,一方面又害怕進階,可以說Android的View是進階路上的最大絆腳石,因為它涉及的東西太多了,比如本次我們此次要寫的View移動,另外還包括View的觸摸事件的傳遞,創建自定義View,這些都是極其重要且不得不面對的難題。但是無論如何,現在不克服的困難將來就會被困難克服。

在此之前,我們還是先了解Android坐標系的定義規則以及View的一些位置參數。

Android坐標系

View的位置及大小是由四個參數決定,即left、top、right、bottom,并且這四個參數都是相對于其父View的。

int width = right-left; int height = bottom-top;

在Activity中布局完成后,我們可以通過View一些方法獲取這些參數信息:

//left,top,right,bottom值的獲取 int left = getLeft(); int top = getTop(); int right = getRight(); int bottom = getBottom();

另外Android 3.0以后加入x,y,translationX,translationY等參數。(x,y)表示為View在ViewGroup中左上角的x,y的值,translationX,translationY在用于平移一個View。默認是都為0,在調用了View的setTranslationX()/setTranslationY()之后發生改變。

//x,y,translationX,translationY參數的獲取 int x = getX(); int y = getY(); int translationX = getTranslationX(); int translationY = getTranslationY();

PS:調用View的setTranslationX()setTranslationY()方法雖然可以使得View平移指定距離,但是這一過程是瞬間完成的。為了使View的移動使得更為平滑,因此可以使用View的屬性動畫來指定translationX和translationY。

ObjectAnimator valueAnimator = ObjectAnimator.ofFloat(textView, "translationX", 200); valueAnimator.setDuration(2000); valueAnimator.start();

另外,如果給View設置setTranslationX()setTranslationY()后,如果設置的值沒有發生變化,那么其只會移動一次,即首次指定的移動距離。查看源碼后我們發現原因:原來在設置值之后其會將設置進去的值和當前的translationX,translationY進行對比,不一致時才進行移動。

了解了View的一些基本參數之后,我們看關于View的三種移動方式。

一、使用Android系統提供的scrollTo()/scrollBy()方法實現View的移動。

不管是scrollTo()還是scrollBy()其移動的本質都是View/ViewGroup中的內容。并且其移動的過程是瞬間完成的,因此,為了實現更好的移動效果,他需要與Scroller類結合使用。另外,它不同于上面的Translation,移動的是View本身,這一點需要好好理解一下。

scrollTo()scrollBy()都是View中的方法, 不是Scroller中的方法 ,但是控制View的平滑移動與Scroller類密不可分。

scrollTo() :指是的移動的絕對位置,如果位置沒有變化,多次調用則不會起作用。

scrollTo移動過程示意圖

scrollBy() :其本質依然是調用的scrollTo() ,指的的移動當前位置的相對距離(每次都是先將當前的位置和設置的距離相加之和調用scrollTo(),這樣如果你多次調用,你就會發現其每次都會移動一段距離,這是和scrollTo()的本質區別)

scrollBy移動過程示意圖

PS:關于上面兩張圖,其實一直以來,我自己都沒完全搞明白什么相對絕對,所以兩張手圖可能會讓人更容易理解。還有就是scrollTo()scrollBy()移動方向問題,上面我們已經畫過Android的坐標系,x軸左→右為正,y軸從上→下為正。但是這并不適用于scrollTo和scrollBy,scrollTo和scrollBy剛好相反,即x軸左→右為負,y軸從上→下為負,簡直是有點坑爹啊。

Scroller類分析:而為什么使用Scroller類中的方法可以對View/ViewGroup的內容進行移動呢?下面我們試著分析一下。

首先

我們創建一個Scroller類的對象mScroller。

然后

要使View在規定的時間中移動到指定的位置,我們會調用startScroll()方法,startScroll()Scroller類中的方法,另外Scroller類中還有一個filing()方法也是很常用的,它主要是處理平滑的移動,一般營造滑動之后的慣性效果,使得View的移動更逼真。下面我們看startScroll()的源碼:

//其接收四個/五個參數。如果duration不設置,則為默認。這四個參數都不難理解,這里不再做解釋。 public void startScroll(int startX, int startY, int dx, int dy, int duration) {  ... }

而一般我們調用這個方法后都要去調View的 invalidate() ,這個方法可以觸發View的draw()方法。而draw()中調用了 computeScroll() ,源碼中我們發現computeScroll()是個空方法,這也是為什么我們需要重寫 computeScroll()方法的原因。因為正在的移動操作就是在computeScroll()中進行的。

@Override public void computeScroll() { if (mScroller.computeScrollOffset()) {  scrollTo(mScroller.getCurrX(), mScroller.getCurrY());  //必須調用View的postInvalidate()/invalidate(),如果不加會導致View的移動只會第一幀。  postInvalidate(); } super.computeScroll(); }

上面我們看到Scroller類中還有一個computeScrollOffset()方法,它又是干啥的呢?它的主要作用就是判斷mCurrX,和mCurrY是否有改變,有則返回true,無則返回false。通過這個方法的判斷可以指點是否需要持續的調用scrollTo()去移動View。這里再給出一個示例,使用scrollTo()讓View跟著手指移動:

public class CuView extends LinearLayout { private float mStartX; private float mStartY; private Scroller mScroller; /** * 第一次滑動是否完成 */ private boolean isFirstFinish; public CuView(Context context) { super(context); init(context); } public CuView(Context context, AttributeSet attrs) { super(context, attrs); init(context); } private void init(Context context) { mScroller = new Scroller(context); } public CuView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(context); } @TargetApi(Build.VERSION_CODES.LOLLIPOP) public CuView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); init(context); } /** * 讓View跟著你的手指走吧 * @param event * @return */ @Override public boolean onTouchEvent(MotionEvent event) { int action = event.getAction(); switch (action) {  case MotionEvent.ACTION_DOWN:  /**   * 第一次移動完成后,我們不需要再去拿開始的位置了,否則造成View重新移動的最起始的位置。   */  if (!isFirstFinish) {   mStartX = event.getRawX();   mStartY = event.getRawY();  }  break;  case MotionEvent.ACTION_MOVE:  scrollTo((int) (mStartX - event.getRawX()), (int) (mStartY - event.getRawY()));  break;  case MotionEvent.ACTION_UP:  //第一次移動完成  isFirstFinish = true;  break; } return true; } /** * 測試startScroll */ public void startScroll() { /**  * 注意Scroller移動方向,  */ mScroller.startScroll(20, 20, -500, -500, 5000); invalidate(); } @Override public void computeScroll() { if (mScroller.computeScrollOffset()) {  scrollTo(mScroller.getCurrX(), mScroller.getCurrY());  invalidate(); } super.computeScroll(); }}

二、使用動畫實現View的移動。

這里包括View的Tween Animation/Frame Animation,以及3.0之后加入的Property Animation。其移動的是View的一個映像,View本身的位置及大小并沒有發生任何改變。

三、設置View的LayoutParams來移動View

LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) textView.getLayoutParams(); layoutParams.leftMargin = 50; textView.requestLayout();

總結

以上就是總結Android View移動的3種方式的全部內容了,希望本文的內容對大家開發Android的時候能有所幫助,如果有疑問大家可以留言交流。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 广汉市| 明星| 夏津县| 蕲春县| 苗栗市| 西昌市| 岑溪市| 若尔盖县| 大庆市| 昭苏县| 泰宁县| 叙永县| 卢湾区| 界首市| 淮北市| 靖江市| 萨迦县| 青岛市| 淮北市| 江油市| 台东县| 义马市| 临夏市| 界首市| 徐汇区| 盘山县| 济阳县| 馆陶县| 依安县| 马山县| 全州县| 绥化市| 武山县| 钦州市| 马边| 湘潭市| 和硕县| 洪泽县| 栾川县| 突泉县| 新干县|