推薦閱讀:Android使用ViewDragHelper實現(xiàn)仿QQ6.0側(cè)滑界面(一)
但是之前的實現(xiàn),只是簡單的可以顯示和隱藏左側(cè)的菜單,但是特別生硬,而且沒有任何平滑的趨勢,那么今天就來優(yōu)化一下吧,加上平滑效果,而且可以根據(jù)手勢滑動的方向來判斷是否是顯示和隱藏。
首先先來實現(xiàn)手勢判斷是否隱藏和顯示
這里就要用到了一個方法了,如下:
這個是ViewDradHelper里面的方法:
/*** 當view被釋放的時候處理的事情(松手)** @param releasedChild 被釋放的子view* @param xvel 水平方向的速度 幀每秒 向右為 +* @param yvel 豎直方向的速度 向下為 +*/@Overridepublic void onViewReleased(View releasedChild, float xvel, float yvel) {Log.d("DragLayout", "xvel : " + xvel + " yvel :" + yvel);super.onViewReleased(releasedChild, xvel, yvel);//判斷關(guān)閉和打開//在這里我們首先判斷什么時候打開,然后剩下的都是關(guān)閉狀態(tài)//首先是我的主面板的左側(cè)具體屏幕左側(cè)已經(jīng)大于mRange/2的距離并且右滑的速度大于0,此時打開if (xvel >= 0 && mMainContent.getLeft() > mRange / 2.0f) {open();} else if (xvel > 0) {//第二種就是我右滑的速度大于0(這里的速度自己定義哈,根據(jù)自己想要實現(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里面的方法):
/*** 打開*/public void open() {int finalLeft = mRange;mMainContent.layout(finalLeft, 0, finalLeft + mWidth, finalLeft + mHeight);}這個是否就可以實現(xiàn)根據(jù)手勢來判斷是否打開和關(guān)閉了。
接下來我們就來實現(xiàn)如何平滑的關(guān)閉和打開,話不多說,代碼說話(這里對上面的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 代表還沒有移動到指定的位置,需要刷新界面,繼續(xù)移動* 返回false 就停止工作哈*///1、觸發(fā)動畫if (mDragHelper.smoothSlideViewTo(mMainContent, finalLeft, 0)) {//參數(shù)傳this,也就是child所在的viewgroupViewCompat.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);}}/*** 打開*/public void open(boolean isSmooth) {int finalLeft = mRange;if (isSmooth && mDragHelper.smoothSlideViewTo(mMainContent, finalLeft, 0)) {//參數(shù)傳this,也就是child所在的viewgroupViewCompat.postInvalidateOnAnimation(this);} else {mMainContent.layout(finalLeft, 0, finalLeft + mWidth, finalLeft + mHeight);}}public void open() {open(true);}來看下效果圖吧(里面的白道問題是錄屏導(dǎo)致,運行的沒有這個哈):

這個時候,基本上差不多了,剩下的,我們就來添加一些狀態(tài)和設(shè)置listener的方法,留給外面的調(diào)用吧。,代碼很簡單:
/*** 定義當前狀態(tài) 默認是關(guān)閉狀態(tài)*/private Status mStatus = Status.CLOSE;/*** 狀態(tài)枚舉* 關(guān)閉 CLOSE* 打開 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();/*** 打開邏輯*/void onOpen();/*** 拖拽邏輯** @param percent*/void onDraging(float percent);}狀態(tài)更新,方法調(diào)用,這個dispatchDragEvent()在onViewPositionChanged()這個方法中調(diào)用一下就行,因為拖拽的時候狀態(tài)時刻在變化,所以我們在這個方法中調(diào)用:
/*** 狀態(tài)更新方法執(zhí)行* * @param newLeft*/private void dispatchDragEvent(int newLeft) {//得到的一個百分比float percent = newLeft * 1.0f / mRange;//0.0f--->1.0fLog.d("DragLayout", "percent : " + percent);if (mListener != null) {mListener.onDraging(percent);}//跟新狀態(tài)執(zhí)行回調(diào)Status lastStatus = mStatus;mStatus = updateStatus(percent);if (mStatus != lastStatus) {//狀態(tài)發(fā)生變化if (mStatus == Status.CLOSE) {//當前狀態(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è)滑基本完成,下面我們來看下效果吧。
好了,這個側(cè)滑就這樣完成了,后期會加在主頁中加入listview(嘗試用RecycleView)實現(xiàn)左滑刪除效果,現(xiàn)在附上該demo的地址,后期添加的也會更新至此。
新聞熱點
疑難解答
圖片精選