QQ可以在任何一个子页面,向右→滑动,可以返回上一个界面,也就相当于按了返回键,或者是Finish了当前的Activity.
这个是用Finish作为例子,模拟返回键原理同样如此.
关键:特效关键是要监听用户的手势,先判断手势,优先级必须最高,判断完手势,才决定是否返回,还是执行其他的事件
关于手势的处理可以看这个:http://blog.csdn.net/lmj623565791/article/details/39102591
要想优先级大于所有的View,则这个View必须是所有的Activity的父View.
一个方法是把重写一个ViewGroup,在每个布局中都添加这个ViewGroup.这个方法比较繁琐,却很实用
另外一个方法是:一般来说一个项目的所有的Activity都会继承一个BaseActivity,我们只要在BaseActivity中,重写setContentView方法,在这里把所有的View都变成一个View的子View
这个也可以达到这个效果
下面的例子是采用第二种方法
BaseActivity
package com.zy.tour;
import java.lang.reflect.Field;
import java.util.ArrayList;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import com.zy.tour.util.app.LApplication;
import com.zy.tour.util.http.ProgressUtil;
import com.zy.tour.util.ui.RightSlidLinearLayout;
import com.zy.tour.util.ui.RightTouchListtener;
@SuppressLint("ClickableViewAccessibility")
public abstract class BaseActivity extends Activity {
private RightSlidLinearLayout linearLayout;
int x = 0, sbar = 0;// 状态栏高度
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
initContentView();
RightTouchListtener listtener = new RightTouchListtener(this);
linearLayout.setOnTouchListener(listtener);
linearLayout.setLongClickable(true);
/**
* 得到屏幕状态栏高度
*/
Class<?> c = null;
Object obj = null;
Field field = null;
try {
c = Class.forName("com.android.internal.R$dimen");
obj = c.newInstance();
field = c.getField("status_bar_height");
x = Integer.parseInt(field.get(obj).toString());
sbar = getResources().getDimensionPixelSize(x);
} catch (Exception e1) {
e1.printStackTrace();
}
}
@Override
protected void onResume() {
super.onResume();
activitys.add(this);
}
private void initContentView() {
ViewGroup content = (ViewGroup) findViewById(android.R.id.content);
content.removeAllViews();
linearLayout = new RightSlidLinearLayout(this);
linearLayout.setOrientation(LinearLayout.VERTICAL);
linearLayout
.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS);
linearLayout.setBackgroundColor(getResources().getColor(
R.color.second_font_color));
content.addView(linearLayout);
}
@Override
public void setContentView(View customContentView) {
linearLayout.addView(customContentView);
}
@Override
public void setContentView(int layoutResID) {
View view = LayoutInflater.from(this).inflate(layoutResID, null);
linearLayout.addView(view);
RightSlidLinearLayout.LayoutParams layoutParams = (RightSlidLinearLayout.LayoutParams) view
.getLayoutParams();
layoutParams.width = LApplication.metrics.widthPixels;
layoutParams.height = LApplication.metrics.heightPixels - sbar;
view.getParent().requestDisallowInterceptTouchEvent(false);
}
}
RightSliLinearLayout
package com.zy.tour.util.ui;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.LinearLayout;
import com.zy.tour.util.app.LApplication;
/**
* @类名:RightSlidLinearLayout
* @功能描述:右滑动LinearLayout,实现在任何地方向右滑动都可以回到上一个Activity
* @作者:XuanKe'Huang
* @时间:2014-10-7 下午6:24:27
* @Copyright @2014
*/
@SuppressLint("ClickableViewAccessibility")
public class RightSlidLinearLayout extends LinearLayout {
public RightSlidLinearLayout(Context context, AttributeSet attrs,
int defStyle) {
super(context, attrs, defStyle);
init(context);
}
public RightSlidLinearLayout(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public RightSlidLinearLayout(Context context) {
super(context);
init(context);
}
/**
* @方法名: init
* @功能描述:初始化
* @param context
* 上下文对象
* @return void
* @throws
*/
private void init(Context context) {
this.context = context;
}
private Context context;
private int startX = 0;// 开始点
private int moveDistance = 0;// 移动的距离
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:// 手指按下
startX = (int) ev.getRawX();
break;
case MotionEvent.ACTION_MOVE:// 手指移动
moveDistance = (int) (ev.getRawX() - startX);
break;
case MotionEvent.ACTION_UP:// 手指离开
Log.e("hua_sli", moveDistance + "");
startX = 0;
if (moveDistance > LApplication.metrics.widthPixels / 3) {
((Activity) context).finish();
return true;
}
break;
default:
break;
}
return super.dispatchTouchEvent(ev);
}
}
RightTouchListtener
package com.zy.tour.util.ui;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.util.Log;
import android.view.GestureDetector;
import android.view.GestureDetector.OnGestureListener;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import com.zy.tour.util.app.LApplication;
/**
* @类名:RightTouchListtener
* @功能描述: 监听向右滑动事件
* @作者:XuanKe'Huang
* @时间:2014-10-9 上午11:38:26
* @Copyright 2014
*/
@SuppressLint("ClickableViewAccessibility")
public class RightTouchListtener implements OnTouchListener {
private GestureDetector detector;
private Context context;
@SuppressWarnings("deprecation")
public RightTouchListtener(Context context) {
this.context = context;
detector = new GestureDetector(new GestureListener());
}
@Override
public boolean onTouch(View v, MotionEvent event) {
return detector.onTouchEvent(event);
}
// 手势滑动监听
class GestureListener implements OnGestureListener {
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
if (e2.getX() - e1.getX() > LApplication.metrics.widthPixels / 3) {
Log.e("hua_gesture", e2.getX() - e1.getX() + "");
((Activity) context).finish();
}
return false;
}
@Override
public boolean onDown(MotionEvent e) {
return false;
}
@Override
public void onShowPress(MotionEvent e) {
}
@Override
public boolean onSingleTapUp(MotionEvent e) {
return false;
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2,
float distanceX, float distanceY) {
return false;
}
@Override
public void onLongPress(MotionEvent e) {
}
}
}