之前的实现只是简单的可以显示和隐藏左侧的菜单,但是特别生硬,而且没有任何平滑的趋势,那么今天就来优化一下吧,加上平滑效果,而且可以根据手势滑动的方向来判断是否是显示和隐藏
正文
Android滑动优化高仿QQ6.0侧滑菜单(滑动优化)
推荐阅读:
但是之前的实现,只是简单的可以显示和隐藏左侧的菜单,但是特别生硬,而且没有任何平滑的趋势,那么今天就来优化一下吧,加上平滑效果,而且可以根据手势滑动的方向来判断是否是显示和隐藏。
首先先来实现手势判断是否隐藏和显示
这里就要用到了一个方法了,如下:
这个是viewdradhelper里面的方法:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
/*** 当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);//判断关闭和打开//在这里我们首先判断什么时候打开,然后剩下的都是关闭状态//首先是我的主面板的左侧具体屏幕左侧已经大于mrange/2的距离并且右滑的速度大于0,此时打开if (xvel >= 0 && mmaincontent.getleft() > mrange / 2.0f) {open();} else if (xvel > 0) {//第二种就是我右滑的速度大于0(这里的速度自己定义哈,根据自己想要实现的敏感度)open();} else {//剩余的所有情况都是关闭close();}} |
close()方法(draglayout里面的方法):
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
/*** 关闭*/public void close() {int finalleft = 0;//调用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里面的方法):
|
1
2
3
4
5
6
7
|
/*** 打开*/public void open() {int finalleft = mrange;mmaincontent.layout(finalleft, 0, finalleft + mwidth, finalleft + mheight);} |
这个是否就可以实现根据手势来判断是否打开和关闭了。
接下来我们就来实现如何平滑的关闭和打开,话不多说,代码说话(这里对上面的open和close做了一些处理):
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
|
public void close() {close(true);}/*** 关闭** @param issmooth 是否平滑的关闭*/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 代表还没有移动到指定的位置,需要刷新界面,继续移动* 返回false 就停止工作哈*///1、触发动画if (mdraghelper.smoothslideviewto(mmaincontent, finalleft, 0)) {//参数传this,也就是child所在的viewgroupviewcompat.postinvalidateonanimation(this);}} else {//调用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)) {//参数传this,也就是child所在的viewgroupviewcompat.postinvalidateonanimation(this);} else {mmaincontent.layout(finalleft, 0, finalleft + mwidth, finalleft + mheight);}}public void open() {open(true);} |
来看下效果图吧(里面的白道问题是录屏导致,运行的没有这个哈):

这个时候,基本上差不多了,剩下的,我们就来添加一些状态和设置listener的方法,留给外面的调用吧。,代码很简单:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
/*** 定义当前状态 默认是关闭状态*/private status mstatus = status.close;/*** 状态枚举* 关闭 close* 打开 open* 拖拽 draging*/public enum status {close, open, draging;}private ondragstatuslistener mlistener;public void setdragstatelistener(ondragstatuslistener listener) {mlistener = listener;}public interface ondragstatuslistener {/*** 关闭逻辑*/void onclose();/*** 打开逻辑*/void onopen();/*** 拖拽逻辑** @param percent*/void ondraging(float percent);} |
状态更新,方法调用,这个dispatchdragevent()在onviewpositionchanged()这个方法中调用一下就行,因为拖拽的时候状态时刻在变化,所以我们在这个方法中调用:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
|
/*** 状态更新方法执行* * @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);}//跟新状态执行回调status laststatus = mstatus;mstatus = updatestatus(percent);if (mstatus != laststatus) {//状态发生变化if (mstatus == status.close) {//当前状态是关闭if (mlistener != null) {mlistener.onclose();}} else if (mstatus == status.open) {if (mlistener != null) {mlistener.onopen();}}}}/*** 状态更新方法** @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侧滑基本完成,下面我们来看下效果吧。

好了,这个侧滑就这样完成了,后期会加在主页中加入listview(尝试用recycleview)实现左滑删除效果,现在附上该demo的地址,后期添加的也会更新至此。

发表评论