最近看到几个APP上都有侧滑退出activity的功能,自己就尝试也写了一个。下面先看下代码。
public class ScrollHelper {
private ValueAnimator valueAnimator;
private ViewGroup rootView;
private ViewGroup content;
private ViewGroup contentParent;
private int screenWidth;
private float downX;
private float downY;
private Context mContext;
private boolean isMove = false;
public ScrollHelper(final Activity mActivity){
//这个是关键,将activity的背景设置为透明,滑动的时候才能露出下层界面。
mActivity.setTheme(android.R.style.Theme_Translucent_NoTitleBar);
mContext = mActivity;
rootView = (ViewGroup) mActivity.findViewById(android.R.id.content);
screenWidth = mActivity.getResources().getDisplayMetrics().widthPixels;
//利用属性动画来使activity划出屏幕或者恢复原状。
valueAnimator = new ValueAnimator();
valueAnimator.setDuration(300);
valueAnimator.setInterpolator(new LinearInterpolator());
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
int tempOffsetX = (int) animation.getAnimatedValue();
content.setTranslationX(tempOffsetX);
if(tempOffsetX>=screenWidth){
mActivity.finish();
}
}
});
}
//这个方法要在activity中的dispatchTouchEvent中调用
public boolean dispatchTouchEvent(MotionEvent ev) {
if(rootView!=null){
content = (ViewGroup) rootView.getChildAt(0);
}
switch (ev.getAction()){
case MotionEvent.ACTION_DOWN:
downX = ev.getX();
downY = ev.getY();
break;
case MotionEvent.ACTION_MOVE:
float nowX = ev.getX();
float nowY = ev.getY();
float diffX = Math.abs(nowX-downX);
float diffY = Math.abs(nowY-downY);
if((diffX>diffY)&&(downX<dp2px(50))){
content.setTranslationX(ev.getX());
isMove = true;
}
break;
case MotionEvent.ACTION_UP:
//设置当滑动超过屏幕宽度的1/3时,将view划出屏幕。
if(ev.getX()>screenWidth/3){
valueAnimator.setIntValues((int)ev.getX(),screenWidth);
}else{
//不到1/3则恢复原状。
valueAnimator.setIntValues((int)ev.getX(),0);
}
if(isMove){
valueAnimator.start();
isMove = false;
}
break;
}
return true;
}
public int dp2px(float dpVal){
return (int)(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpVal,
mContext.getResources().getDisplayMetrics()));
}
}
大致说下思路。这个类是一个侧滑退出的助手类,在构造方法中传入需要用侧滑退出功能的activity对象。接着将该activity的theme设置为Theme_Translucent_NoTitleBar,这部是将activity的背景设置为透明,以便滑动的时候能看到下层的界面。然后创建一个属性动画,目的是为了处理界面在UP事件后是复原还是退出,具体逻辑在添加的动画数值监听器中处理,annimateValue达到或者大于屏幕宽度时,退出Activty.
接下来说下dispatchTouchEvent这个方法。这个方法要在activity的dispatchTouchEvent方法中执行,并将事件作为参数传递进来。在方法开始先通过之前的rootView拿到第一个子view,接下来的移动操作都是针对这个view来进行。在ACTION_DOWN事件中,记录下按下去的xy坐标。在ACTION_MOVE事件中,再用两个变量来记录当前的xy坐标。然后通过X方向和Y方向的坐标差的绝对值来判断左右滑动还是上下滑动,还有就是down事件中的坐标x必须在左边缘的某个数值范围内(这里我设定的是50),才判断是view可滑动,然后将isMove标志位设置为true,调用view的setTranslationX方法来进行移动。最后在UP事件中做判断,如果此时的X坐标大于屏幕的宽的某个比例(此处我设定的是1/3),就将动画的终点值设置为屏幕的宽(划出屏幕),否则设置为0(恢复原状).接下来要注意的是一定要在isMove这个标记位为true在执行动画的start操作,否则单纯的点击事件也会触发动画效果。
以上就是这个侧滑的退出的代码以及大致思路。但这个没有应用的实际场景之中,可能会存在一定的问题,目前有可能存在的问题就是事件的冲突问题,等到以后实际用到的时候再加以完善。