您的位置:首页 > 移动开发 > 微信开发

仿微信右滑销毁Activity

2017-01-09 18:51 330 查看
一直想自己实现Activity的侧滑销毁,无奈在finish activity的时候遇到了瓶颈。今天看到一个开源库,那哥们把Activity的背景设置成了透明,这才恍然大悟。这里share一下。



大体思路讲解:

1.获取Activity的DecorView

2.自定义布局,重写onInterceptTouchEvent与onTouchEvent函数对触摸事件进行处理,根据手势滑动对DecorView(内容)进行滑动

3.根据滑动的距离判断是销毁当前的Activity还是滑动恢复到原来位置

知识储备:

Android事件分发,请看我这篇博文

Activity、Window、DecorView讲解,请看这里

Scroller详解,请看xiaanming大神的博文

贴出核心类

public class SlidingFinishLayout extends FrameLayout {
private Scroller mScroller;
private int mTouchSlop;
private ViewGroup parentView;
private int screenWidth;

private int last_x;
private int last_y;

private int delay_x;
private int delay_y;

private boolean isFinish = false;

private Activity mActivity;

private SlidingFinishLayout.OnActivityFinishListener onActivityFinish;

public SlidingFinishLayout(Context context, AttributeSet attrs) {
super(context, attrs);
mScroller = new Scroller(context);
mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
}

public void attachActivity(Activity activity) {
this.mActivity = activity;
}

public void detachActivity() {
if (this.mActivity != null) {
mActivity = null;
}
}

@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
if (changed) {
ViewGroup decor = (ViewGroup) mActivity.getWindow().getDecorView();
mActivity.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
mActivity.getWindow().getDecorView().setBackgroundColor(Color.TRANSPARENT);
View decorChild = decor.findViewById(android.R.id.content);
while (decorChild.getParent() != decor) {
decorChild = (View) decorChild.getParent();
}
parentView = decor;
screenWidth = getWidth();
}
}

/**
* 进行事件拦截
*
* @param ev
* @return
*/
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean isIntercept = false;

switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
last_x = (int) ev.getRawX();
last_y = (int) ev.getRawY();
break;
case MotionEvent.ACTION_MOVE:
int current_x = (int) ev.getRawX();
int current_y = (int) ev.getRawY();

delay_x = current_x - last_x;
delay_y = current_y - last_y;
if ((Math.abs(delay_x) / (Math.abs(delay_y) + 1) >= 2)) { //30度角的时候才开始拦截事件
isIntercept = true;
}
break;
case MotionEvent.ACTION_UP:
break;
}
return isIntercept;
}

/**
* 进行事件处理
*
* @param ev
* @return
*/
@Override
public boolean onTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
last_x = (int) ev.getRawX();
last_y = (int) ev.getRawY();
break;
case MotionEvent.ACTION_MOVE:
int current_x = (int) ev.getRawX();
int current_y = (int) ev.getRawY();

delay_x = current_x - last_x;
delay_y = current_y - last_y;

if (Math.abs(delay_x) > mTouchSlop) {
if ((Math.abs(delay_x) / (Math.abs(delay_y) + 1) >= 2)) { //30度角的时候才开始处理事件
parentView.scrollBy(-delay_x, 0); //开始滑动
} else {
return false;
}
} else {
return false;
}

last_x = current_x;
last_y = current_y;
break;
case MotionEvent.ACTION_UP:

if (Math.abs(parentView.getScrollX()) > (screenWidth / 3)) { //如果滑动距离超出屏幕三分之一,则进行滑动销毁,否则恢复原位
scrollFinish();
} else {
scrollOriginal();
}
break;
}
return true;
}

/**
* 滑动销毁
*/
private void scrollFinish() {
final int delta = (screenWidth + parentView.getScrollX());
mScroller.startScroll(parentView.getScrollX(), 0, -delta + 1, 0);
postInvalidate();
isFinish = true;
}

/**
* 恢复到原始状态
*/
private void scrollOriginal() {
mScroller.startScroll(parentView.getScrollX(), 0, -parentView.getScrollX(), 0);
postInvalidate();
isFinish = false;
}

/**
* Activity销毁的时候通知回调
*
* @param onActivityFinish
*/
public void setOnActivityFinishListener(SlidingFinishLayout.OnActivityFinishListener onActivityFinish) {
this.onActivityFinish = onActivityFinish;
}

@Override
public void computeScroll() {
if (mScroller.computeScrollOffset()) {
parentView.scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
postInvalidate();

if (mScroller.isFinished() && isFinish) {
onActivityFinish.onActivityFinish();
}
}
}


在希望右滑销毁的Activity中使用

public class SlideFinishActivity extends AppCompatActivity implements SlidingFinishLayout.OnActivityFinishListener {

SlidingFinishLayout sf_test;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_slide_finish);

sf_test = (SlidingFinishLayout) findViewById(R.id.sf_test);
sf_test.setOnActivityFinishListener(this); //设置销毁的监听器
sf_test.attachActivity(this);
}

@Override
protected void onDestroy() {
super.onDestroy();
sf_test.detachActivity();
}

@Override
public void onActivityFinish() {
finish();
}
}


注意,该Activity的Style文件应该加入下面代码才可以生效 android:windowIsTranslucent。本代码是把Activity设置成透明状态

收工。

项目源码:https://github.com/WillSprint/SlideFinish

推荐一个侧滑库,本博客中的一些思想来源于该作者

https://github.com/Jude95/SwipeBackHelper
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  开源 Android