推荐阅读:android使用viewdraghelper实现仿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 竖直方向的速度 向下为 + */ @override public 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所在的viewgroup viewcompat.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所在的viewgroup viewcompat.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.0f log.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的地址,后期添加的也会更新至此。