【CSDN抽风,把我写一个多小时的东西覆盖了。真的是哔了狗了,自己又没有备份。。。重写吧。。。】
这个类主要是实现向右滑动关闭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。】示意图如下:
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