Android滑動(dòng)優(yōu)化高仿QQ6.0側(cè)滑菜單(滑動(dòng)優(yōu)化)
推薦閱讀:Android使用ViewDragHelper實(shí)現(xiàn)仿QQ6.0側(cè)滑界面(一)
但是之前的實(shí)現(xiàn),只是簡(jiǎn)單的可以顯示和隱藏左側(cè)的菜單,但是特別生硬,而且沒(méi)有任何平滑的趨勢(shì),那么今天就來(lái)優(yōu)化一下吧,加上平滑效果,而且可以根據(jù)手勢(shì)滑動(dòng)的方向來(lái)判斷是否是顯示和隱藏。
首先先來(lái)實(shí)現(xiàn)手勢(shì)判斷是否隱藏和顯示
這里就要用到了一個(gè)方法了,如下:
這個(gè)是ViewDradHelper里面的方法:
/**
* 當(dāng)view被釋放的時(shí)候處理的事情(松手)
*
* @param releasedChild 被釋放的子view
* @param xvel 水平方向的速度 幀每秒 向右為 +
* @param yvel 豎直方向的速度 向下為 +
*/
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
Log.d("DragLayout", "xvel : " + xvel + " yvel :" + yvel);
super.onViewReleased(releasedChild, xvel, yvel);
//判斷關(guān)閉和打開(kāi)
//在這里我們首先判斷什么時(shí)候打開(kāi),然后剩下的都是關(guān)閉狀態(tài)
//首先是我的主面板的左側(cè)具體屏幕左側(cè)已經(jīng)大于mRange/2的距離并且右滑的速度大于0,此時(shí)打開(kāi)
if (xvel >= 0 && mMainContent.getLeft() > mRange / 2.0f) {
open();
} else if (xvel > 0) {
//第二種就是我右滑的速度大于0(這里的速度自己定義哈,根據(jù)自己想要實(shí)現(xiàn)的敏感度)
open();
} else {
//剩余的所有情況都是關(guān)閉
close();
}
}
close()方法(DragLayout里面的方法):
/**
* 關(guān)閉
*/
public void close() {
int finalLeft = 0;
//調(diào)用layout方法,擺放主布局
/**
* @param l Left position, relative to parent
* @param t Top position, relative to parent
* @param r Right position, relative to parent
* @param b Bottom position, relative to parent
*/
mMainContent.layout(finalLeft, 0, finalLeft + mWidth, finalLeft + mHeight);
}
open()方法(DragLayout里面的方法):
/**
* 打開(kāi)
*/
public void open() {
int finalLeft = mRange;
mMainContent.layout(finalLeft, 0, finalLeft + mWidth, finalLeft + mHeight);
}
這個(gè)是否就可以實(shí)現(xiàn)根據(jù)手勢(shì)來(lái)判斷是否打開(kāi)和關(guān)閉了。
接下來(lái)我們就來(lái)實(shí)現(xiàn)如何平滑的關(guān)閉和打開(kāi),話不多說(shuō),代碼說(shuō)話(這里對(duì)上面的open和close做了一些處理):
public void close() {
close(true);
}
/**
* 關(guān)閉
*
* @param isSmooth 是否平滑的關(guān)閉
*/
public void close(boolean isSmooth) {
int finalLeft = 0;
if (isSmooth) {
/**
* public boolean smoothSlideViewTo(View child, int finalLeft, int finalTop)方法的解釋
*
* Animate the view <code>child</code> to the given (left, top) position.
* If this method returns true, the caller should invoke {@link #continueSettling(boolean)}
* on each subsequent frame to continue the motion until it returns false. If this method
* returns false there is no further work to do to complete the movement.
*
* 返回true 代表還沒(méi)有移動(dòng)到指定的位置,需要刷新界面,繼續(xù)移動(dòng)
* 返回false 就停止工作哈
*/
//1、觸發(fā)動(dòng)畫(huà)
if (mDragHelper.smoothSlideViewTo(mMainContent, finalLeft, 0)) {
//參數(shù)傳this,也就是child所在的viewgroup
ViewCompat.postInvalidateOnAnimation(this);
}
} else {
//調(diào)用layout方法,擺放主布局
/**
* @param l Left position, relative to parent
* @param t Top position, relative to parent
* @param r Right position, relative to parent
* @param b Bottom position, relative to parent
*/
mMainContent.layout(finalLeft, 0, finalLeft + mWidth, finalLeft + mHeight);
}
}
/**
* 打開(kāi)
*/
public void open(boolean isSmooth) {
int finalLeft = mRange;
if (isSmooth && mDragHelper.smoothSlideViewTo(mMainContent, finalLeft, 0)) {
//參數(shù)傳this,也就是child所在的viewgroup
ViewCompat.postInvalidateOnAnimation(this);
} else {
mMainContent.layout(finalLeft, 0, finalLeft + mWidth, finalLeft + mHeight);
}
}
public void open() {
open(true);
}
來(lái)看下效果圖吧(里面的白道問(wèn)題是錄屏導(dǎo)致,運(yùn)行的沒(méi)有這個(gè)哈):

這個(gè)時(shí)候,基本上差不多了,剩下的,我們就來(lái)添加一些狀態(tài)和設(shè)置listener的方法,留給外面的調(diào)用吧。,代碼很簡(jiǎn)單:
/**
* 定義當(dāng)前狀態(tài) 默認(rèn)是關(guān)閉狀態(tài)
*/
private Status mStatus = Status.CLOSE;
/**
* 狀態(tài)枚舉
* 關(guān)閉 CLOSE
* 打開(kāi) OPEN
* 拖拽 DRAGING
*/
public enum Status {
CLOSE, OPEN, DRAGING;
}
private OnDragStatusListener mListener;
public void setDragStateListener(OnDragStatusListener listener) {
mListener = listener;
}
public interface OnDragStatusListener {
/**
* 關(guān)閉邏輯
*/
void onClose();
/**
* 打開(kāi)邏輯
*/
void onOpen();
/**
* 拖拽邏輯
*
* @param percent
*/
void onDraging(float percent);
}
狀態(tài)更新,方法調(diào)用,這個(gè)dispatchDragEvent()在onViewPositionChanged()這個(gè)方法中調(diào)用一下就行,因?yàn)橥献У臅r(shí)候狀態(tài)時(shí)刻在變化,所以我們?cè)谶@個(gè)方法中調(diào)用:
/**
* 狀態(tài)更新方法執(zhí)行
*
* @param newLeft
*/
private void dispatchDragEvent(int newLeft) {
//得到的一個(gè)百分比
float percent = newLeft * 1.0f / mRange;
//0.0f--->1.0f
Log.d("DragLayout", "percent : " + percent);
if (mListener != null) {
mListener.onDraging(percent);
}
//跟新?tīng)顟B(tài)執(zhí)行回調(diào)
Status lastStatus = mStatus;
mStatus = updateStatus(percent);
if (mStatus != lastStatus) {
//狀態(tài)發(fā)生變化
if (mStatus == Status.CLOSE) {
//當(dāng)前狀態(tài)是關(guān)閉
if (mListener != null) {
mListener.onClose();
}
} else if (mStatus == Status.OPEN) {
if (mListener != null) {
mListener.onOpen();
}
}
}
}
/**
* 狀態(tài)更新方法
*
* @param percent
* @return
*/
private Status updateStatus(float percent) {
if (percent == 0) {
return Status.CLOSE;
} else if (percent == 1) {
return Status.OPEN;
}
return Status.DRAGING;
}
好了,到此為止,高仿QQ6.0側(cè)滑基本完成,下面我們來(lái)看下效果吧。
好了,這個(gè)側(cè)滑就這樣完成了,后期會(huì)加在主頁(yè)中加入listview(嘗試用RecycleView)實(shí)現(xiàn)左滑刪除效果,現(xiàn)在附上該demo的地址,后期添加的也會(huì)更新至此。
- Android左右滑出菜單實(shí)例分析
- Android實(shí)現(xiàn)原生側(cè)滑菜單的超簡(jiǎn)單方式
- Android實(shí)現(xiàn)頂部導(dǎo)航菜單左右滑動(dòng)效果
- Android實(shí)現(xiàn)自定義滑動(dòng)式抽屜菜單效果
- android實(shí)現(xiàn)上滑屏幕隱藏底部菜單欄的示例
- Android側(cè)滑菜單之DrawerLayout用法詳解
- android RecyclerView側(cè)滑菜單,滑動(dòng)刪除,長(zhǎng)按拖拽,下拉刷新上拉加載
- Android仿微信滑動(dòng)彈出編輯、刪除菜單效果、增加下拉刷新功能
- Android利用滑動(dòng)菜單框架實(shí)現(xiàn)滑動(dòng)菜單效果
- android自定義左側(cè)滑出菜單效果
相關(guān)文章
android小動(dòng)畫(huà):不斷擴(kuò)散的圓點(diǎn)
這篇文章介紹了如何實(shí)現(xiàn)android小動(dòng)畫(huà):不斷擴(kuò)散的圓點(diǎn),文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,下面的實(shí)例代碼,大家可以看看2021-11-11
淺談Android textview文字對(duì)齊換行的問(wèn)題
下面小編就為大家分享一篇淺談Android textview文字對(duì)齊換行的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-01-01
Android開(kāi)發(fā)TextView內(nèi)的文字實(shí)現(xiàn)自動(dòng)換行
這篇文章主要為大家介紹了Android開(kāi)發(fā)TextView內(nèi)的文字實(shí)現(xiàn)自動(dòng)換行,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-06-06
利用Kotlin如何實(shí)現(xiàn)Android開(kāi)發(fā)中的Parcelable詳解
這篇文章主要給大家介紹了關(guān)于利用Kotlin如何實(shí)現(xiàn)Android開(kāi)發(fā)中的Parcelable的相關(guān)資料,并且給大家介紹了關(guān)于Kotlin使用parcelable出現(xiàn):BadParcelableException: Parcelable protocol requires a Parcelable.Creator...問(wèn)題的解決方法,需要的朋友可以參考下。2017-12-12
Android 通過(guò)SQLite數(shù)據(jù)庫(kù)實(shí)現(xiàn)數(shù)據(jù)存儲(chǔ)管理
SQLiteOpenHelper 是Android 提供的一個(gè)抽象工具類(lèi),負(fù)責(zé)管理數(shù)據(jù)庫(kù)的創(chuàng)建、升級(jí)工作。本文主要介紹了如何使用SQLite數(shù)據(jù)庫(kù)實(shí)現(xiàn)對(duì)數(shù)據(jù)進(jìn)行存儲(chǔ)管理,感興趣的可以了解一下2021-11-11
Android ScrollView實(shí)現(xiàn)橫向和豎向拖動(dòng)回彈效果
這篇文章主要為大家詳細(xì)介紹了Android ScrollView實(shí)現(xiàn)橫向和豎向拖動(dòng)回彈效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-09-09
深入解析Android App開(kāi)發(fā)中Context的用法
這篇文章主要介紹了深入解析Android App開(kāi)發(fā)中Context的用法,包括Context的創(chuàng)建場(chǎng)景和Context對(duì)資源的訪問(wèn)等內(nèi)容,需要的朋友可以參考下2016-02-02
Android側(cè)滑導(dǎo)航欄的實(shí)例代碼
這篇文章主要介紹了Android側(cè)滑導(dǎo)航欄的實(shí)例代碼的相關(guān)資料,需要的朋友可以參考下2017-01-01
MobLink Android端業(yè)務(wù)場(chǎng)景簡(jiǎn)單說(shuō)明
這篇文章主要介紹了MobLink Android端業(yè)務(wù)場(chǎng)景簡(jiǎn)單說(shuō)明,MobLink的功能實(shí)現(xiàn)就是在分享前會(huì)將鏈接的參數(shù)信息保存到服務(wù)器,更多相關(guān)內(nèi)容需要的朋友可以參考一下2022-09-09
Android超實(shí)用的Toast提示框優(yōu)化分享
Toast是Android中用來(lái)顯示顯示信息的一種機(jī)制,和Dialog不一樣的是,Toast是沒(méi)有焦點(diǎn)的,而且Toast顯示的時(shí)間有限,過(guò)一定的時(shí)間就會(huì)自動(dòng)消失。那么這篇文章跟大家分享下Android中Toast的優(yōu)化,對(duì)大家日常開(kāi)發(fā)還是很實(shí)用,下面來(lái)一起看看吧。2016-09-09

