Android仿微信列表滑動刪除之可滑動控件(一)
這次是列表滑動刪除的第三波,仿微信的列表滑動刪除。先上個效果圖:
前面的文章里面說過開源框架SwipeListView的實(shí)現(xiàn)原理是每個列表item中包含上下兩層view,普通狀態(tài)下上層的view覆蓋著下層的view,當(dāng)用戶滑開上層的view,下層的view就顯示出來了。但是仔細(xì)觀察微信列表的item,很明顯并非這個實(shí)現(xiàn)方案,微信的item應(yīng)該一個單層view,只不過這個item超出了所在的ListView的寬度,在用戶滑動item的時(shí)候,item超出屏幕的view則會顯示在屏幕之上,這種滑動實(shí)現(xiàn)也很不錯。
既然推測出微信的實(shí)現(xiàn)原理,現(xiàn)在就要尋找具體的實(shí)現(xiàn)方案了,我最開始想的比較簡單,以為寫一個橫向線性布局LinearLayout,讓其包含兩個子布局,左邊的子布局寬度設(shè)置為填充父布局的寬度,以為另一個子布局就自然而然的會超出父布局的顯示范圍,但是具體測試的時(shí)候,發(fā)現(xiàn)就算左邊的子布局設(shè)置為填充父布局的寬度,但實(shí)際顯示的時(shí)候還是兩個子布局被包含在父布局的顯示范圍內(nèi),右邊的子布局無法做到超出父布局的顯示范圍。
糾結(jié)了一段時(shí)間,偶然情況下想起了ScrollView還有一種類型是HorizontalScrollView,,這個android提供的HorizontalScrollView可以做到其子view超出它的顯示范圍,那我可以直接使用HorizontalScrollView來實(shí)現(xiàn)這個item,我決定自定義一個控件,繼承自HorizontalScrollView,在代碼里面直接添加兩個子布局,并讓左邊的布局寬度填充這個控件的自身寬度,以便讓右邊的布局超出控件的顯示范圍,不過很不辛,HorizontalScrollView比較傲嬌,很難駕馭,奇葩bug層出不窮,譬如左邊的子布局渲染出來了,但是右邊的子布局愣是沒初始化,更別說滑動了,弄的焦頭爛額,最后實(shí)在沒辦法,只得暫時(shí)放下。
最后則是想到了使用一個自定義的ViewGroup來實(shí)現(xiàn)這個item?,F(xiàn)在很多app在第一次啟動的時(shí)候,會出現(xiàn)一個介紹性的導(dǎo)航界面,用戶一頁一頁的滑動,看完導(dǎo)航的介紹之后再正式進(jìn)入app,現(xiàn)在這種導(dǎo)航介紹應(yīng)該大多數(shù)是用ViewPager實(shí)現(xiàn)的,ViewPager可以做到兩個滑動的子頁同時(shí)顯示在屏幕范圍內(nèi),具有很好的體驗(yàn)效果。但是ViewPager是在之后的support.v4里面引入的,最初并沒有,那一開始這種導(dǎo)航介紹使用什么方案實(shí)現(xiàn)的呢?當(dāng)然就是自定義的ViewGroup了,其實(shí)supprot.v4.ViewPager本身就是一個自定義的ViewGroup。關(guān)于使用自定義的ViewGroup實(shí)現(xiàn)導(dǎo)航介紹,csdn上有個大牛有專門寫過一個文章介紹了,這里就不詳細(xì)說了。
本篇的要講的是如何使用自定義的ViewGroup實(shí)現(xiàn)item的子view可以超出父布局的顯示范圍這樣的效果。
寫一個SwipeItemView,繼承自ViewGroup,構(gòu)造方法里面,傳入左邊布局的引用id和右邊布局的引用id,初始化左子布局和右子布局,并將它們添加到SwipeItemView中作為子view,代碼如下:
private void init(Context context, AttributeSet attrs) { mScroller = new Scroller(context); ...... if(mPrimaryViewID == -1) throw new RuntimeException( "Illegal attribute 'primaryView', make sure you have set it"); mPrimaryView = LayoutInflater.from(getContext()).inflate( mPrimaryViewID, null); mPrimaryView.setClickable(false); addView(mPrimaryView, 0); if(mSlidingViewID != -1) { mSlidingView = LayoutInflater.from(getContext()).inflate( mSlidingViewID, null); mSlidingView.setClickable(false); addView(mSlidingView, 1); } }
接下來需要重寫VIewGroup的onMeasure()方法,用來測量這個SwipeItemView及其子view的寬高,其中先獲取轉(zhuǎn)入的heightMeasureSpec中包含的heightSize,當(dāng)heightSize的值和heightMeasureSpec相同的時(shí)候,是測量整個SwipeItemView的寬高,這是我們不做額外的處理,當(dāng)heightSize不等于的傳入的heightMeasureSpec的時(shí)候,是用于測量SwipeItemView它包含的子view的寬高,這里我們做一下額外的處理,主要是針對超出SwipeItemView顯示范圍的右邊的mSlidingView,我想要它的寬只是包裹其內(nèi)容就行,不想它的寬和屏幕范圍等寬,所以構(gòu)造一個這樣的參數(shù)MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),具體代碼如下:
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int heightSize = MeasureSpec.getSize(heightMeasureSpec); int widthSize = MeasureSpec.getSize(widthMeasureSpec); int heightMode = MeasureSpec.getMode(heightMeasureSpec); int widthMode = MeasureSpec.getMode(widthMeasureSpec); if(heightSize != heightMeasureSpec) { mPrimaryView.measure(MeasureSpec.makeMeasureSpec(widthSize, widthMode), MeasureSpec.makeMeasureSpec(heightSize, heightMode)); if(mSlidingView != null) { mSlidingView.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), MeasureSpec.makeMeasureSpec(heightSize, heightMode)); } } else { mPrimaryView.measure(widthMeasureSpec, heightMeasureSpec); if(mSlidingView != null) mSlidingView.measure(widthMeasureSpec, heightMeasureSpec); } }
然后是重寫ViewGroup的onLayout()方法,用來放置子view在SwipeItemView中的具體位置,主要就是讓右邊的mSlidingView排列在左邊的mPrimaryView的右邊,具體代碼如下:
@Override protected void onLayout(boolean changed, int l, int t, int r, int b) { mPrimaryView.layout(l, t, r, b); if(mSlidingView != null) mSlidingView.layout(r, t, r + mSlidingView.getMeasuredWidth(), b); }
好了,具體的SwipeItemView的初始化完成了,接下來需要做什么工作呢,看一下上面的構(gòu)造方法,有沒有看到mScroller = new Scroller(context)這行代碼,我們需要使用這個mScroller來做這個SwipeItemView滑動的動畫效果。我們知道ViewGroup中提供了scrollBy()和scrollTo()兩個方法用來移動這個ViewGroup視圖內(nèi)容的位置,其中scrollBy()移動參數(shù)指定的距離,scrollTo()方法移動到參數(shù)指定的位置。但是scrollBy()還好,如果每次都是移動一小段距離的話,給用戶的感覺就是一段連續(xù)的動畫效果了,但是scrollTo()則是瞬間移動,中間沒有任何動畫效果,會讓人感覺到非常突兀,這樣我們就需要用到mScroller這個對象了。
Scroller是android提供的用來實(shí)現(xiàn)我們需要的移動動畫效果的。Scroller本身并非去執(zhí)行移動的動畫的,感覺上Scroller更多是作為一個指揮者,當(dāng)我們調(diào)用它的Scroller.startScroll()方法的時(shí)候,這個方法我們需要傳入移動初始的位置、移動的距離以及花費(fèi)的時(shí)間,簡單理解的話,我們假設(shè)指定的時(shí)間是10s,那第3s的時(shí)候,ViewGroup視圖內(nèi)容應(yīng)該移動到什么位置,第7s,應(yīng)該移動到哪個位置,而且這個時(shí)刻Scroller計(jì)算出來的位置可以通過Scroller.getCurrX()和Scroller.getCurrY()獲取到,這個過程,Scroller會回調(diào)ViewGroup中的computeScroll()方法,在這個回調(diào)方法中,我們調(diào)用scrollTo()執(zhí)行具體的移動操作。而我們實(shí)現(xiàn)的這個scrollToWithAnimation()方法就是提供給后面的SwipeListView用來移動某個item并且使其移動過程帶有動畫效果的方法。代碼如下:
@Override public void computeScroll() { if(mScroller.computeScrollOffset()) { scrollTo(mScroller.getCurrX(), mScroller.getCurrY()); } } /** * just like scrollTo(), but with animation :D * */ public void scrollToWithAnimation(int scrollX, int scrollY) { mScroller.abortAnimation(); mScroller.startScroll(getScrollX(), getScrollY(), scrollX - getScrollX(), getScrollY() - scrollY, 300); }
接下來需要實(shí)現(xiàn)一個自定義的ListView,暫且命名為SwipeListView。下一篇繼續(xù)。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Android自定義控件實(shí)現(xiàn)可左右滑動的導(dǎo)航條
- Android控件之SlidingDrawer(滑動式抽屜)詳解與實(shí)例分享
- Android開源堆疊滑動控件仿探探效果
- Android自定義控件ScrollView實(shí)現(xiàn)上下滑動功能
- Android實(shí)現(xiàn)可滑動的自定義日歷控件
- Android控件SeekBar仿淘寶滑動驗(yàn)證效果
- Android自定義View實(shí)現(xiàn)隨手勢滑動控件
- Android自定義滑動解鎖控件使用詳解
- Android自定義控件實(shí)現(xiàn)滑動開關(guān)效果
- Android自定義雙向滑動控件
相關(guān)文章
Android提高之MediaPlayer播放網(wǎng)絡(luò)視頻的實(shí)現(xiàn)方法
這篇文章主要介紹了Android的MediaPlayer播放網(wǎng)絡(luò)視頻的實(shí)現(xiàn)方法,是一個非常實(shí)用的功能,需要的朋友可以參考下2014-08-08Kotlin?掛起函數(shù)CPS轉(zhuǎn)換原理解析
這篇文章主要為大家介紹了Kotlin?掛起函數(shù)CPS轉(zhuǎn)換原理解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12Android ProgressBar 模擬進(jìn)度條效果的實(shí)現(xiàn)
這篇文章主要介紹了Android ProgressBar 模擬進(jìn)度條效果的實(shí)現(xiàn),本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-04-04Android學(xué)習(xí)教程之懸浮窗菜單制作(9)
這篇文章主要為大家詳細(xì)介紹了Android學(xué)習(xí)教程之懸浮窗菜單制作方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-11-11Android實(shí)現(xiàn)爆炸式菜單按鈕彈出效果
這篇文章主要介紹了Android實(shí)現(xiàn)爆炸式菜單按鈕彈出效果,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-05-05Android BroadcastReceiver廣播簡單使用
這篇文章主要為大家詳細(xì)介紹了Android BroadcastReceiver廣播簡單的使用,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-04-04Android基于ViewPager+Fragment實(shí)現(xiàn)左右滑屏效果的方法
這篇文章主要介紹了Android基于ViewPager+Fragment實(shí)現(xiàn)左右滑屏效果的方法,結(jié)合實(shí)例形式分析了Android實(shí)現(xiàn)滑屏效果的布局與滑動功能相關(guān)操作技巧,需要的朋友可以參考下2017-07-07詳解Android App中創(chuàng)建ViewPager組件的方法
這篇文章主要介紹了詳解Android App中創(chuàng)建ViewPager組件的方法,ViewPager最基本的功能就是可以使視圖滑動,需要的朋友可以參考下2016-03-03