swipefinishlayout 的实现

Posted by alonealice on 2016-09-19

很多android手机用户会发现ios应用自带右滑退出,这个功能虽小,却能很大程度上提高用户的使用体验,尤其是现在手机的尺寸越来越大的情况下。因此,越来越多的android应用也实现了这个效果。之前看到我一个朋友实现了android activity滑动关闭的效果,当时觉得好厉害,但是当自己尝试着去实现时发现,其实这个功能实现还是蛮简单的,现在在这里,我就讲讲如何使用几十行代码实现activity滑动关闭。

实现原理

activity滑动关闭的实现原理主要是activity的所有布局都包含在一个自定义的viewgroup中,当手指从屏幕左边缘滑动时,viewgroup做相应的scroll,当手指放开时,根据已经滑动的距离,返回原来的状态或整体滑动到最右边,并退出。

实现步骤

第一步,定义一个底层view并加入到viewgroup中

其实一开始我并不打算这么做,当时我直接把view都加在swipefinishlayout中。但是后来发现当swipefinishlayout中没有其他布局时,滑动效果无法出现,同时加入到swipefinishlayout中只能是一个view。所以为了解决这个问题,我就在创建时自己先加入一个Framlayout,其他的布局加到Framlayou中。

1
2
3
4
5
6
rootView=new FrameLayout(getContext(),attrs,defStyleAttr);
LayoutParams layoutParams=new LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.MATCH_PARENT);
rootView.setLayoutParams(layoutParams);

this.addView(rootView);
this.setBackgroundColor(Color.TRANSPARENT);

这里可以看到,我们把怎个布局的颜色设置为透明,同时把原先设置在布局中的颜色设置给rootview。同时把原先添加到swipefinishlayout中的view添加到Framlayout中。

1
2
3
4
5
6
7
public void addView(View child, int index, LayoutParams params) {
if(child==rootView) {
super.addView(child, index, params);
}else{
rootView.addView(child,index,params);
}
}

同时把原先加到swipefinishlayout中的view加到rootview中。

第二步,重写ontouch方法,让整体随手指滑动儿滑动

这部分是整个swipefinishlayout中的重中之重。首先,在手指开始按下时,要判断是否开启滑动操作,而判断的依据可根据实际需求来变换。这里我主要是判断ontouch方法中触点是否在最左边1/7处。
firstTouchRect=new Rect(0,0,width/7,height);
firstTouchRect.contains(event.getX(), event.getY())
而在滑动事件中,整体根据手指的触点位置滚动

1
2
3
4
5
scrollTo(-(int) x, 0);
if(rootView!=null&&isTransparent){
rootView.setAlpha(1-Math.abs(this.getScrollX()*1.0f/width)/5);
}
invalidate();

第三步,手指放开时,自动回滚到原来位置或者滑到最右边并退出

在这里我们需要用到scroller这个类。根据当前的滑动位置来关闭或者还原,时间都是500ms

1
2
3
4
5
6
if(isClose){
scroller.startScroll(-startX,0,startX,0,500);
}else{
scroller.startScroll(-startX,0,startX-width,0,500);
}
invalidate();

同时重写computeScroll方法,根据当前的scroller值,滑动整体布局。

1
2
3
4
5
6
if(scroller!=null&&scroller.computeScrollOffset()){
int x=scroller.getCurrX();
int y=scroller.getCurrY();
if(rootView!=null) scrollTo(x,y);
invalidate();
}

到这里,一个简单的滑动退出swipefinishlayout就完成了,这当中有很多的参数和样式都可以进行定制和拓展,这里就不在展开。
DEMO地址