国内最全IT社区平台 联系我们 | 收藏本站
华晨云阿里云优惠2
您当前位置:首页 > php开源 > 综合技术 > 仿微信右滑销毁Activity

仿微信右滑销毁Activity

来源:程序员人生   发布时间:2017-03-16 08:58:02 阅读次数:4337次

1直想自己实现Activity的侧滑烧毁,无奈在finish activity的时候遇到了瓶颈。今天看到1个开源库,那哥们把Activity的背景设置成了透明,这才恍然大悟。这里share1下。
效果图
大体思路讲授:

  • 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)) { //如果滑动距离超越屏幕3分之1,则进行滑动烧毁,否则恢复原位
                    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

推荐1个侧滑库,本博客中的1些思想来源于该作者
https://github.com/Jude95/SwipeBackHelper

生活不易,码农辛苦
如果您觉得本网站对您的学习有所帮助,可以手机扫描二维码进行捐赠
程序员人生
------分隔线----------------------------
分享到:
------分隔线----------------------------
关闭
程序员人生