Android實(shí)現(xiàn)果凍滑動(dòng)效果的控件
前言
在微信是的處理方法是讓用戶(hù)滑動(dòng),但最終還是回滾到最初的地方,這樣的效果很生動(dòng)(畢竟成功還是取決于細(xì)節(jié))。那么在安卓我們要怎么弄呢。下面為大家介紹一下JellyScrollView,是我繼承ScrollView的一個(gè)有阻尼的效果的果凍滑動(dòng)控件。
下面話(huà)不多說(shuō)了,先來(lái)看看效果圖
(在虛擬機(jī)或者真機(jī)跑起來(lái)是很流暢,可能是錄制視頻做成gif的時(shí)候有點(diǎn)卡頓。)
實(shí)現(xiàn)原理
其實(shí)只需要重寫(xiě)下它的攔截方法的邏輯就好了,ScrollView的攔截方法onInterceptTouchEvent一般情況下都默認(rèn)地返回false,表示不攔截該事件。我們只需要在用戶(hù)滑動(dòng)了界面的情況下,攔截下來(lái)并移動(dòng)布局就好了,當(dāng)用戶(hù)松開(kāi)手就恢復(fù)布局。很簡(jiǎn)單
第一步:集成ScrollView重寫(xiě)幾個(gè)構(gòu)造方法;
第二步:重寫(xiě)下onFinishInflate方法,獲得第一個(gè)子view;
第三步:在攔截方法里面處理上面所說(shuō)的邏輯;
public class JellyScrollView extends ScrollView { private View inner;// 子View private float y;// 點(diǎn)擊時(shí)y坐標(biāo) private Rect normal = new Rect();// 矩形(這里只是個(gè)形式,只是用于判斷是否需要?jiǎng)赢?huà).) private boolean isCount = false;// 是否開(kāi)始計(jì)算 private boolean isMoving = false;// 是否開(kāi)始移動(dòng). private int top;// 拖動(dòng)時(shí)時(shí)高度。 private int mTouchSlop;//系統(tǒng)最少滑動(dòng)距離 public JellyScrollView(Context context) { super(context); } public JellyScrollView(Context context, AttributeSet attrs) { super(context, attrs); } public JellyScrollView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop(); } /*** * 根據(jù) XML 生成視圖工作完成.該函數(shù)在生成視圖的最后調(diào)用,在所有子視圖添加完之后. 即使子類(lèi)覆蓋了 onFinishInflate * 方法,也應(yīng)該調(diào)用父類(lèi)的方法,使該方法得以執(zhí)行. */ @Override protected void onFinishInflate() { if (getChildCount() > 0) { inner = getChildAt(0); } } /**攔截事件*/ @Override public boolean onInterceptTouchEvent(MotionEvent ev) { if (inner != null) { int action = ev.getAction(); switch (action) { case MotionEvent.ACTION_DOWN: y = ev.getY(); top = 0; break; case MotionEvent.ACTION_UP: // 手指松開(kāi). isMoving = false; if (isNeedAnimation()) { animation(); } break; /*** * 排除出第一次移動(dòng)計(jì)算,因?yàn)榈谝淮螣o(wú)法得知y坐標(biāo), 在MotionEvent.ACTION_DOWN中獲取不到, * 因?yàn)榇藭r(shí)是ScrollView的touch事件傳遞到到了ListView的子item上面.所以從第二次計(jì)算開(kāi)始. * 然而我們也要進(jìn)行初始化,就是第一次移動(dòng)的時(shí)候讓滑動(dòng)距離歸0. 之后記錄準(zhǔn)確了就正常執(zhí)行. */ case MotionEvent.ACTION_MOVE: final float preY = y;// 按下時(shí)的y坐標(biāo) float nowY = ev.getY();// 每時(shí)刻y坐標(biāo) int deltaY = (int) (nowY - preY);// 滑動(dòng)距離 if (!isCount) { deltaY = 0; // 在這里要?dú)w0. } if (Math.abs(deltaY) < mTouchSlop && top <= 0) return true; // 當(dāng)滾動(dòng)到最上或者最下時(shí)就不會(huì)再滾動(dòng),這時(shí)移動(dòng)布局 isNeedMove(); if (isMoving) { // 初始化頭部矩形 if (normal.isEmpty()) { // 保存正常的布局位置 normal.set(inner.getLeft(), inner.getTop(), inner.getRight(), inner.getBottom()); } // 移動(dòng)布局 inner.layout(inner.getLeft(), inner.getTop() + deltaY / 3, inner.getRight(), inner.getBottom() + deltaY / 3); top += (deltaY / 6); } isCount = true; y = nowY; break; } } return super.onInterceptTouchEvent(ev); } /*** * 回縮動(dòng)畫(huà) */ public void animation() { // 開(kāi)啟移動(dòng)動(dòng)畫(huà) TranslateAnimation ta = new TranslateAnimation(0, 0, inner.getTop(), normal.top); ta.setDuration(200); inner.startAnimation(ta); // 設(shè)置回到正常的布局位置 inner.layout(normal.left, normal.top, normal.right, normal.bottom); normal.setEmpty(); // 手指松開(kāi)要?dú)w0. isCount = false; y = 0; } // 是否需要開(kāi)啟動(dòng)畫(huà) public boolean isNeedAnimation() { return !normal.isEmpty(); } /*** * 是否需要移動(dòng)布局 * inner.getMeasuredHeight():獲取的是控件的總高度 * getHeight():獲取的是屏幕的高度 * * @return */ public void isNeedMove() { int offset = inner.getMeasuredHeight() - getHeight(); int scrollY = getScrollY(); // scrollY == 0是頂部 // scrollY == offset是底部 if (scrollY == 0 || scrollY == offset) { isMoving = true; } } }
然后在布局里面在最外層就使用我們的JellyScrollView
(為了方便展示,我只是大概寫(xiě)了一部分布局代碼)
<?xml version="1.0" encoding="utf-8"?><cn.ichengxi.fang.view.JellyScrollView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/bg" android:scrollbars="none"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <TextView android:id="@+id/personal_setting_txt" android:layout_width="match_parent" android:layout_height="wrap_content" android:alpha="0.8" android:gravity="center_vertical" android:text="設(shè)置" android:textColor="@android:color/black" /> </LinearLayout></cn.ichengxi.fang.view.JellyScrollView>12345678910111213141516171819202122231234567891011121314151617181920212223
總結(jié)
好了,這樣就可以很優(yōu)雅的實(shí)現(xiàn)了果凍控件的效果啦。以上就是本文的全部?jī)?nèi)容了,希望這篇文章的內(nèi)容對(duì)大家能有所幫助,如果有疑問(wèn)大家可以留言交流。
- Android自定義View實(shí)現(xiàn)隨手勢(shì)滑動(dòng)控件
- Android控件SeekBar仿淘寶滑動(dòng)驗(yàn)證效果
- Android自定義滑動(dòng)接聽(tīng)電話(huà)控件組實(shí)例
- Android仿微信列表滑動(dòng)刪除之可滑動(dòng)控件(一)
- Android實(shí)現(xiàn)IOS相機(jī)滑動(dòng)控件
- Android自定義控件實(shí)現(xiàn)滑動(dòng)開(kāi)關(guān)效果
- Android自定義控件實(shí)現(xiàn)可左右滑動(dòng)的導(dǎo)航條
- 使用Android自定義控件實(shí)現(xiàn)滑動(dòng)解鎖九宮格
- Android控件之SlidingDrawer(滑動(dòng)式抽屜)詳解與實(shí)例分享
- Android開(kāi)源堆疊滑動(dòng)控件仿探探效果
相關(guān)文章
android檢測(cè)SD卡讀寫(xiě)權(quán)限方法
今天小編就為大家分享一篇android檢測(cè)SD卡讀寫(xiě)權(quán)限方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-08-08Android中加載網(wǎng)絡(luò)資源時(shí)的優(yōu)化可使用(線(xiàn)程+緩存)解決
Android 中加載網(wǎng)絡(luò)資源時(shí)的優(yōu)化;基本的思路是線(xiàn)程+緩存來(lái)解決,具體解決思路如下,有類(lèi)似情況的朋友可以參考下哈2013-06-06Android實(shí)現(xiàn)計(jì)時(shí)與倒計(jì)時(shí)的方法匯總
這篇文章主要介紹了Android實(shí)現(xiàn)計(jì)時(shí)與倒計(jì)時(shí)的方法匯總,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2017-06-06Android ViewPager實(shí)現(xiàn)輪播圖效果
這篇文章主要為大家詳細(xì)介紹了Android ViewPager實(shí)現(xiàn)輪播圖效果的相關(guān)資料,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-02-02Android中使用include標(biāo)簽和merge標(biāo)簽重復(fù)使用布局
這篇文章主要介紹了Android中使用include標(biāo)簽和merge標(biāo)簽重復(fù)使用布局,文中講解了創(chuàng)建可復(fù)用布局的例子以及include標(biāo)簽和merge標(biāo)簽使用例子,需要的朋友可以參考下2014-06-06Android中AlarmManager+Notification實(shí)現(xiàn)定時(shí)通知提醒功能
本篇文章主要介紹了Android中AlarmManager+Notification實(shí)現(xiàn)定時(shí)通知提醒功能,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2017-10-10Android結(jié)合x(chóng)ml實(shí)現(xiàn)幀動(dòng)畫(huà)
將一組動(dòng)作相近的圖片組合在一起,然后按照一定的時(shí)間來(lái)播放,就會(huì)形成一個(gè)動(dòng)畫(huà),我們可以稱(chēng)之為幀動(dòng)畫(huà)。在 Android 中可通過(guò)結(jié)合 xml 的方式來(lái)輕松實(shí)現(xiàn)。2021-05-05Android EditText限制輸入字符類(lèi)型的方法總結(jié)
這篇文章主要介紹了Android EditText限制輸入字符類(lèi)型的方法總結(jié)的相關(guān)資料,需要的朋友可以參考下2017-03-03