Android View滑動(dòng)的實(shí)現(xiàn)分析示例
實(shí)現(xiàn)View滑動(dòng)有很多種方法,這篇帖子介紹6中滑動(dòng)的方法,分別是:
layout()、offsetLeftAndRight()、offsetTopAndBottom()、LayoutParams、scrollTo、scrollBy、Scroller。
1.layout方法
繪制View的時(shí)候會(huì)調(diào)用onLayout方法來(lái)設(shè)置顯示的位置,因此我們同樣也可以通過(guò)修改View的left、top、right、bottom、這四個(gè)屬性來(lái)控制View的坐標(biāo)。首先我們要自定義一個(gè)View在onTouchEvent方法中獲取觸摸點(diǎn)的坐標(biāo):
@Override public boolean onTouchEvent(MotionEvent event) { //獲取手指觸摸點(diǎn)的橫坐標(biāo)和縱坐標(biāo) int x = (int) event.getX(); int y = (int) event.getY(); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: lastX = x; lastY = y; break; } .... }
接下來(lái)我們?cè)贏CTION_MOVE事件中計(jì)算偏移量,再調(diào)用layout方法重新放置這個(gè)自定義View的位置。
case MotionEvent.ACTION_MOVE: //計(jì)算移動(dòng)的距離 int offsetX = x - lastX; int offsetY = y - lastY; //調(diào)用layout方法來(lái)重新放置它 layout(getLeft() - offsetX, getTop() + offsetY, getRight() - offsetX, getBottom() - offsetY); break;
在每次移動(dòng)時(shí)都會(huì)調(diào)用layout方法對(duì)屏幕重新布局,從而達(dá)到移動(dòng)View的效果。
2.offsetLeftAndRight()與offsetTopAndBottom()
其這兩種方法和layout方法效果差不多,其使用方法也差不多。我們將ACTION_MOVE中的代碼替代如下:
case MotionEvent.ACTION_MOVE: //計(jì)算移動(dòng)的距離 int offsetX = x - lastX; int offsetY = y - lastY; //對(duì)left和right進(jìn)行偏移 offsetLeftAndRight(offsetX); //對(duì)top和bottom進(jìn)行偏移 offsetTopAndBottom(offsetY); break;
3.LayoutParams(改變布局參數(shù))
LayoutParms 主要保存了一個(gè)View的布局參數(shù) , 因此我們可以通過(guò)LayoutParams來(lái)改變View的采納數(shù);從而達(dá)到改變View位置的效果。同樣,我們將ACTION_MOVE中的代碼替換如下:
LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) getLayoutParams(); layoutParams.leftMargin = getLeft() + offsetX; layoutParams.topMargin = getLeft() + offsetY; setLayoutParams(layoutParams);
4.scrollTo與scrollBy
scrollTo(x,y) 表示移動(dòng)到一個(gè)具體的坐標(biāo)點(diǎn),而scrollBy(dx.dy)則表示移動(dòng)的增量為dx,dy。
其中,scrollBy最終也是要調(diào)用scrollTo的。View.java文件中的scrollBy和scrollTo代碼如下:
scrollTo、scrollBy 移動(dòng)的是View的內(nèi)容,如果在ViewGroup中使用,則是移動(dòng)其所有的子View,我們將ACTION_MOVE中的代碼替換如下:
((View) getParent()).scrollBy(-offsetX, -offsetY);
這里若要實(shí)現(xiàn)View隨手指移動(dòng)的效果,則需要將偏移量設(shè)置為負(fù)值,為什么要設(shè)置負(fù)值呢?
假設(shè)我們正在用放大鏡來(lái)看報(bào)紙,放大鏡用來(lái)顯示子的內(nèi)容,同樣我們可以吧放大鏡看作我們的手機(jī)屏幕,它們都是負(fù)責(zé)顯示內(nèi)容,也就是報(bào)紙的內(nèi)容不會(huì)隨著放大鏡的移動(dòng)而消失,它一直存在,同樣,我們的手機(jī)屏幕看不到的視圖并不代表其不存在,上圖畫(huà)布中有3個(gè)控件,及Button、EditText和SwitchButton。只有Button在屏幕中顯示,它的Android坐標(biāo)為(60,60)?,F(xiàn)在我們調(diào)用scrollBy(50,50),按照字面的意思,這個(gè)Button應(yīng)該會(huì)在屏幕右下側(cè),可事實(shí)并非如此。如果我們調(diào)用scrollBy(50,50)里面的參數(shù)都會(huì)正值,則我們的手機(jī)屏幕想X軸正方向,也就是右邊平移50然后屏幕向Y正方向,也就是下方平移50,雖然我們?cè)O(shè)置的數(shù)值是正數(shù)并且在X軸和Y軸的正方向移動(dòng),但Button卻向反方向移動(dòng)了,這就是參考對(duì)象不同導(dǎo)致的差異。
所以,當(dāng)我們使用scrollBy方法的時(shí)候,要是設(shè)置負(fù)數(shù)才會(huì)達(dá)到自己想要的效果。
5.Scroller
我們?cè)谟胹crollTo/scrollBy方法進(jìn)行滑動(dòng)時(shí),這個(gè)過(guò)程是瞬間完成的,所以用戶體驗(yàn)并不好,這里我們可以使用Scroller來(lái)實(shí)現(xiàn)有過(guò)度效果的滑動(dòng),這個(gè)過(guò)程不是瞬間完成的,而是在一定的時(shí)間間隔內(nèi)完成的。Scroller本身不能實(shí)現(xiàn)View的滑動(dòng),它需要與View的computeScroll方法配合才能實(shí)現(xiàn)彈性滑動(dòng)效果
public MyView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); mScroller = new Scroller(context); }
接下來(lái)重寫(xiě)computeScroll方法,系統(tǒng)會(huì)在繪制View的時(shí)候在draw方法中調(diào)用該方法,在這個(gè)方法中,我們調(diào)用父類的scrollTo方法并通過(guò)Scroller來(lái)不斷獲取當(dāng)前的滑動(dòng)值。每滑動(dòng)一小段距離,我們就會(huì)調(diào)用invalidate方法不斷的進(jìn)行重繪。重繪就會(huì)調(diào)用computeScroll方法,這樣我們通過(guò)不斷地移動(dòng)一個(gè)小的距離并連貫起來(lái)就實(shí)現(xiàn)了平滑移動(dòng)的效果。
@Override public void computeScroll() { super.computeScroll(); if (mScroller.computeScrollOffset()) { ((View) getParent()).scrollTo(mScroller.getCurrX(), mScroller.getCurrY()); invalidate(); } }
我們會(huì)在View中寫(xiě)一個(gè)smoothScrollTo方法,調(diào)用Scroller的startScroll方法,在200ms內(nèi)沿X軸平移delta像素
public void smoothScrollTo(int destX, int destY) { int scrollX = getScrollX(); int delta = destX - scrollX; mScroller.startScroll(scrollX, 0, delta, 0, 2000); invalidate(); }
最后我們?cè)赩iewSlideActivity.Java中調(diào)用View的smoothScrollTo方法。在此我們?cè)O(shè)定View沿V軸向右平移400像素
mCustomView.smoothScrollTo(-400,0);
到此這篇關(guān)于Android View滑動(dòng)的實(shí)現(xiàn)分析示例的文章就介紹到這了,更多相關(guān)Android View滑動(dòng)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Android 7.0開(kāi)發(fā)獲取存儲(chǔ)設(shè)備信息的方法
這篇文章主要介紹了Android 7.0開(kāi)發(fā)獲取存儲(chǔ)設(shè)備信息的方法,結(jié)合實(shí)例形式分析了Android7.0針對(duì)存儲(chǔ)設(shè)備信息的獲取、判斷操作方法與相關(guān)注意事項(xiàng),需要的朋友可以參考下2017-11-11Android onTouchEvent事件中onTouch方法返回值(介紹)
下面小編就為大家?guī)?lái)一篇Android onTouchEvent事件中onTouch方法返回值(介紹)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-04-04Android數(shù)據(jù)庫(kù)greenDAO配置與使用介紹
這篇文章主要介紹了Android集成GreenDao數(shù)據(jù)庫(kù),使用數(shù)據(jù)庫(kù)存儲(chǔ)時(shí)候,一般都會(huì)使用一些第三方ORM框架,比如GreenDao,本文分幾步給大家介紹Android集成GreenDao數(shù)據(jù)庫(kù)的方法,需要的朋友可以參考下2023-03-03Android多種方式實(shí)現(xiàn)相機(jī)圓形預(yù)覽的示例代碼
這篇文章主要介紹了Android多種方式實(shí)現(xiàn)相機(jī)圓形預(yù)覽的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-08-08Android實(shí)現(xiàn)Toast提示框圖文并存的方法
這篇文章主要介紹了Android實(shí)現(xiàn)Toast提示框圖文并存的方法,實(shí)例分析了Toast提示框的參數(shù)設(shè)置及圖文調(diào)用的相關(guān)技巧,需要的朋友可以參考下2016-01-01詳解Android——藍(lán)牙技術(shù) 帶你實(shí)現(xiàn)終端間數(shù)據(jù)傳輸
藍(lán)牙技術(shù)在智能硬件方面有很多用武之地,本篇文章主要介紹了Android——藍(lán)牙技術(shù),實(shí)現(xiàn)兩個(gè)終端間數(shù)據(jù)的傳輸,有興趣的朋友可以了解一下。2016-12-12android實(shí)現(xiàn)多線程下載文件(支持暫停、取消、斷點(diǎn)續(xù)傳)
本篇文章主要介紹了androids實(shí)現(xiàn)多線程下載文件,主要包括暫停、取消、斷點(diǎn)續(xù)傳等功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。2017-02-02Android開(kāi)發(fā)常用經(jīng)典代碼段集錦
這篇文章主要介紹了Android開(kāi)發(fā)常用經(jīng)典代碼段,涉及Android開(kāi)發(fā)過(guò)程中針對(duì)手機(jī)、聯(lián)系人、圖片、存儲(chǔ)卡等的相關(guān)操作技巧,非常簡(jiǎn)單實(shí)用,需要的朋友可以參考下2016-02-02