【android开发】手势滑动关闭Activity(随手指消失)的辅助类的实现

  • Post author:
  • Post category:其他


【CSDN抽风,把我写一个多小时的东西覆盖了。真的是哔了狗了,自己又没有备份。。。重写吧。。。】

这个类主要是实现向右滑动关闭Activity,效果如下:

手势滑动关闭Activity效果

老套路,先写思路:

1)将Activity的背景设置为透明模式。(从而可以看到下一层Activity)

2)创建一个FrameLayout,将contentView从DecorView中移除,并将contentView添加到我们的FrameLayout中,最后再将我们的FrameLayout添加回原来contentView的地方。

【熟悉android ViewTree的人应该能轻松理解contentView和DecorView。针对不熟悉的朋友,我做简单介绍:我们将Activity界面看做由ActionBar部分 + ContentView部分(onCreate中的setContentView方法设置的部分) 组成,如果我们设置为NoActionBar类型的主题时,ActionBar部分将不存在,整个Activity都由ContentView部分组成。而Activity会有个rootView来容纳他们,这个rootView就是DecorView。】示意图如下:

DecorView示意图

3)实现FrameLayout的拦截逻辑,当手势向右滑动时,拦截事件,将contentView进行水平方向移动。

分析完开动代码。


1、创建自定义ViewGroup类并申明必须要的参数,代码如下:

class MySwipeView extends FrameLayout {

    private Activity activity;// 绑定的Activity
    private ViewGroup decorView;
    private View contentView;// activity的ContentView
    private float intercept_X = 0;// onInterceptTouchEvent刚触摸时的X坐标
    private float intercept_Y = 0;// onInterceptTouchEvent手指刚触摸时的y坐标
    private int touchSlop = 0;// 产生滑动的最小值

    public MySwipeView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        touchSlop = ViewConfiguration.get(getContext())
                .getScaledTouchSlop();
        setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,
                LayoutParams.MATCH_PARENT));
    }

    public MySwipeView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public MySwipeView(Context context) {
        this(context, null);
    }
}

2、实现Activity的绑定,并将contentView从decorView中移除,然后添加到我们的FrameLayout中,最后将我们的FrameLayout添加回DecorView。代码如下:

/**
 * 绑定Activity
 * @param activity
 */
public void setActivity(Activity activity) {
    this.activity = activity;
    initCoverView();
}

/**
 * 将contentView从DecorView中移除,并添加到CoverView中,最后再将CoverView添加到DecorView中
 */
private void initCoverView() {
    decorView = (ViewGroup) activity.getWindow().getDecorView();
    // decorView.setBackgroundColor(Color.parseColor("#33000000"));
    contentView = (ViewGroup) decorView
            .findViewById(android.R.id.content);
    ViewGroup contentParent = (ViewGroup) contentView.getParent();
    contentParent.removeView(contentView);
    addView(contentView);
    contentView.setBackgroundColor(Color.WHITE);
    contentParent.addView(this);
}

3、实现事件拦截代码。说到事件拦截,熟悉android事件分发机制的朋友,应该知道。ViewGroup有个public boolean onInterceptTouchEvent(MotionEvent ev)方法,当此方法返回true时,ViewGroup将不会传递事件给他的childView,同时会调用该ViewGroup的onTouchEvent来处理该事件;反之,返回false时,事件将会传递给他的childView处理。我们通过实现onInterceptTouchEvent的逻辑来过滤我们需要的事件。代码如下,看一两遍理解没问题的:

@Override
public boolean onInterceptTouchEvent(android.view.MotionEvent ev) {

        return shouldInterceptEvent(ev);
};


/**
 * 判断是否应该拦截事件。
 * 如果水平方向的偏移量(不取绝对值) > 垂直方向的偏移量(取绝对值),并且水平方向的偏移量大于最小滑动距离,我们将拦截事件。
 * 【实际过程中,我们发现touchSlope还是偏小,所以取了其3倍的数值作为最小滑动距离】
 * @param event
 *            事件对象
 * @return true表示拦截,false反之
 */
private boolean shoul



版权声明:本文为LanTingShuXu原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。