您的位置:首页 > 其它

onInterceptTouchEvent、onTouchEvent、GestureDetector、SimpleOnGestureListener

2016-01-07 02:24 489 查看

一:Activity

public class AppointActivity extends BaseActivity implements AppointTabbarView.IAppointTabbarItemCheckedListener,
PullToRefreshView.OnHeaderRefreshListener, PullToRefreshView.OnFooterRefreshListener{
public static final int APPOINT_SUCCESS = 0;
public static final int APPOINT_DONE = 1;
public static final int APPOINT_CANCEL = 2;
private int type=APPOINT_SUCCESS;
private AppointTabbarView tabbarView;

private PullToRefreshView mPullToRefreshView;
private IphoneTreeView treeView;
private AppointManageAdapter adapter;
private List<BookingUserGroupVO> userGroupVOs;
private TextView tv_setting_hint;
private int index = 0;

private GestureDetector detector;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.appoint_manage);
initView();
initHint();
initPatientList(index);
initGestureDetector();
}

private void initHint() {
boolean isNotFirst = PreferenceHelper.getBoolean(this, PreferenceHelper.APPOINT_SETTING_HINT_IS_FIRST_LOAD,
PreferenceHelper.APP_CONFIGURE_NAME);

if (!isNotFirst) {
tv_setting_hint.setVisibility(View.VISIBLE);
PreferenceHelper.setBooleanParam(this, PreferenceHelper.APPOINT_SETTING_HINT_IS_FIRST_LOAD, true,
PreferenceHelper.APP_CONFIGURE_NAME);
}else {
tv_setting_hint.setVisibility(View.GONE);
}
}

private void initView(){
initTitleView(R.string.appoint_manage, getString(R.string.setting), true, this);
tv_setting_hint = (TextView) findViewById(R.id.tv_setting_hint);
tabbarView = (AppointTabbarView) findViewById(R.id.tabbar);
tabbarView.setListener(this);
userGroupVOs = new ArrayList<BookingUserGroupVO>();

mPullToRefreshView = (PullToRefreshView) findViewById(R.id.main_pull_refresh_view);
treeView = (IphoneTreeView) findViewById(R.id.appoint_list);

mPullToRefreshView.setOnHeaderRefreshListener(this);
mPullToRefreshView.setOnFooterRefreshListener(this);

View head = LayoutInflater.from(this).inflate(R.layout.appoint_group_head, null);
treeView.setHeaderView(head, Utils.dip2px(this, 38));
adapter = new AppointManageAdapter(this,userGroupVOs);
treeView.setAdapter(adapter);
}
private void initGestureDetector(){
detector = new GestureDetector(AppointActivity.this,new GestureDetector.SimpleOnGestureListener(){
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
/**
* 用户按下的动作已经在mPullToRefreshView的onInterceptTouchEvent方法中消费掉了,所以这里e1是null,需要从
* mPullToRefreshView中获取用户按下去时的x值
*/
//从左向右滑动
if((e2.getRawX()-mPullToRefreshView.getmLastMotionX())>310){
if(index == 0){
index = 1;
tabbarView.setSomeOneChecked(index);
initPatientList(index);
return true;
}
if(index == 1){
index = 2;
tabbarView.setSomeOneChecked(index);
initPatientList(index);
}
}
//从右向左滑动
if((mPullToRefreshView.getmLastMotionX()-e2.getRawX())>310){
if(index == 2){
index = 1;
tabbarView.setSomeOneChecked(index);
initPatientList(index);
return true;
}
if(index == 1){
index = 0;
tabbarView.setSomeOneChecked(index);
initPatientList(index);
}
}
return super.onFling(e1, e2, velocityX, velocityY);
}
});
}
private void initPatientList(int index) {
if(StringUtils.isEmpty(Utils.getTokenFromDataBase(this))) {
return;
}
TokenRequestParams params=new TokenRequestParams(this);
if(index == 0){
params.put("type", "1");
}
if(index == 1){
params.put("type", "2");
}
if(index == 2){
params.put("type", "3");
}

NetRequest.doGetArray(this, true, params, UrlConstants.APPOINT_GET_USER_LIST, new IRequestJSONArraySuccessListener() {
@Override
public void handle(JSONArray data) {
List<BookingUserVO> list = GsonFactory.getNewInstance().fromJson(data.toString(), new TypeToken<List<BookingUserVO>>() {
}.getType());
if(list!=null && list.size()>0){
showPatientList(list);
}
}
});
}
private void showPatientList(List<BookingUserVO> list){
userGroupVOs.clear();
Set<String> dateSet = new TreeSet<String>();
for(int i=0;i<list.size();i++){
list.get(i).setDate(DateUtil.getDate(list.get(i).getStart()*1000));
dateSet.add(list.get(i).getDate());
}
for(String date:dateSet){
List<BookingUserVO> userVOs = new ArrayList<BookingUserVO>();
for(int k=0;k<list.size();k++){
if(list.get(k).getDate().equals(date)){
userVOs.add(list.get(k));
}
}
BookingUserGroupVO userGroupVO = new BookingUserGroupVO();
userGroupVO.setDate(date);
userGroupVO.setUserList(userVOs);
userGroupVOs.add(userGroupVO);
}
notifyDataSetChanged();
}
private void notifyDataSetChanged(){
adapter = new AppointManageAdapter(AppointActivity.this,userGroupVOs);
treeView.setAdapter(adapter);
adapter.notifyDataSetChanged();
}
@Override
public void onFooterRefresh(PullToRefreshView view) {
mPullToRefreshView.postDelayed(new Runnable() {

@Override
public void run() {
mPullToRefreshView.onFooterRefreshComplete();
}
}, 1000);
}

SimpleDateFormat sdf = new SimpleDateFormat("MM-dd HH:mm:ss");
@Override
public void onHeaderRefresh(PullToRefreshView view) {
mPullToRefreshView.postDelayed(new Runnable() {

@Override
public void run() {
String time = sdf.format(new Date());
mPullToRefreshView.onHeaderRefreshComplete("更新于:"+time);
//                 mPullToRefreshView.onHeaderRefreshComplete();
}
}, 1000);

}

@Override
public void tabbarItemChecked(int index) {
Log.i("yin","按钮的索引:"+index);
this.index = index;
initPatientList(index);

}

@Override
public void onClick(View v) {
super.onClick(v);
if (v.getId() == R.id.title_menu) {
Utils.startActivity(this, AppointSettingsActivity.class);
}
}

@Override
public boolean onTouchEvent(MotionEvent event) {
if(event == null){
Log.i("yin","触摸了null");
}else {
Log.i("yin","没有触摸null");
}
detector.onTouchEvent(event);
return super.onTouchEvent(event);
}
}


其中上面的关键代码是:
private void initGestureDetector(){
detector = new GestureDetector(AppointActivity.this,new GestureDetector.SimpleOnGestureListener(){
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
/**
* 用户按下的动作已经在mPullToRefreshView的onInterceptTouchEvent方法中消费掉了,所以这里e1是null,需要从
* mPullToRefreshView中获取用户按下去时的x值
*/
//从左向右滑动
if((e2.getRawX()-mPullToRefreshView.getmLastMotionX())>310){
if(index == 0){
index = 1;
tabbarView.setSomeOneChecked(index);
initPatientList(index);
return true;
}
if(index == 1){
index = 2;
tabbarView.setSomeOneChecked(index);
initPatientList(index);
}
}
//从右向左滑动
if((mPullToRefreshView.getmLastMotionX()-e2.getRawX())>310){
if(index == 2){
index = 1;
tabbarView.setSomeOneChecked(index);
initPatientList(index);
return true;
}
if(index == 1){
index = 0;
tabbarView.setSomeOneChecked(index);
initPatientList(index);
}
}
return super.onFling(e1, e2, velocityX, velocityY);
}
});
}
@Override
public boolean onTouchEvent(MotionEvent event) {
detector.onTouchEvent(event);
return super.onTouchEvent(event);
}


二,布局文件关键代码是

<com.yin.PullToRefreshView
android:id="@+id/main_pull_refresh_view"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_below="@id/tabbar"
android:background="@android:color/white"
android:orientation="vertical" >

<com.yin.IphoneTreeView
android:id="@+id/appoint_list"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:divider="@null"
android:groupIndicator="@android:color/transparent"
android:cacheColorHint="#00000000"/>

</com.yin.PullToRefreshView>

三,自定义的控件的关键代码是

/**
* 该例子即实现了下拉刷新,上拉加载更多,也实现了左右滑动
* 这里的当前控件就是PullToRefreshView这个控件,其子控件是其包裹的listview等
* 当前控件的onInterceptTouchEvent()与其子控件的onInterceptTouchEvent()的关系:
* 如果当前控件的onInterceptTouchEvent()返回false,说明当前控件不拦截该Touch事件,因此会由其子控件的onInterceptTouchEvent()
* 接收该Touch事件;
* 如果当前控件的onInterceptTouchEvent()返回true,则说明当前控件拦截了当前的onTouch事件,因此该touch事件会由当前控件的onTouchEvent()接收执行,
* 当前控件的子控件则接收不到该touch事件;
* 需要注意的是touch事件MotionEvent.ACTION_DOWN动作,肯定是首先执行的,且是瞬间的,因此该动作会先由当前控件的onInterceptTouchEvent()消费掉,所以当前控件
* 的onTouchEvent()方法或其子控件的onInterceptTouchEvent()和onTouchEvent()都不可能再接收到MotionEvent.ACTION_DOWN动作。
* 但是MotionEvent.ACTION_MOVE动作是联系的,是随着用户的手势不断执行的,因此如果当前控件onInterceptTouchEvent()在MotionEvent.ACTION_MOVE动作的过程中返回了
* true,则当前控件的onTouchEvent()方法会接收这个MotionEvent.ACTION_MOVE动作继续执行!!!;
* 如果当前控件onInterceptTouchEvent()在MotionEvent.ACTION_MOVE动作的过程中返回了false,则其子控件会接收该MotionEvent.ACTION_MOVE动作继续执行???
*
* 如果当前控件的onTouchEvent()方法返回true,则说明该onTouch事件被当前控件的onTouchEvent()垄断了,因此当前控件所在的Activity的onTouchEvent()就接收不到该
* onTouch事件了,如果当前控件的onTouchEvent()方法返回false,则当前控件所在的Activity的onTouchEvent()可继续接收该onTouch事件继续执行。
*
* 由上可知,用户的一个按下-->滑动-->松开的动作可能有多个控件的多个方法参与处理,例如这里的用户的触摸事件就由PullToRefreshView的onInterceptTouchEvent()、
* onTouchEvent()以及其所在Activity的onTouchEvent()、GestureDetector的onFling()处理,因此我要想实现左右滑动则需要在当前控件的onInterceptTouchEvent()方法
* 中获取用户按下时的开始值,在其所在Activity的onFling()方法中获取其松开时的x值。
* @param e
* @return
*/
@Override
public boolean onInterceptTouchEvent(MotionEvent e) {
int y = (int) e.getRawY();
int x= (int) e.getRawX();
switch (e.getAction()) {
case MotionEvent.ACTION_DOWN:
// 首先拦截down事件,记录y坐标
mLastMotionY = y;
mLastMotionX = x;//记录用户按下时的x值,以便activity的GestureDetector的onFling()方法获取到用户按下时的起始位置
break;
case MotionEvent.ACTION_MOVE:
// deltaY > 0 是向下运动,< 0是向上运动
int deltaX = x - mLastMotionX;
int deltaY = y - mLastMotionY;
if((deltaY>=300)||(deltaY<=(-300))){//给用户的手势一段缓冲的空间(这里给了300),避免用户刚触摸屏幕就触发上拉或下拉
if (isRefreshViewScroll(deltaY)) {
mLock = false;//将mLock置为false,则将触摸事件交给当前控件的onTouchEvent()处理下拉和上拉
return true;
}
}
if((deltaX>=300)||(deltaX<=(-300))){
mLock = true;//引入mLock的目的是希望用户左右滑动时将触摸事件交给Activity的onTouchEvent()方法和GestureDetector处理
return true;
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
break;
}
return false;
//		return true;
}

/*
* 如果在onInterceptTouchEvent()方法中没有拦截(即onInterceptTouchEvent()方法中 return
* false)则由PullToRefreshView 的子View来处理;
* 否则由下面的方法来处理(即由PullToRefreshView自己来处理)
*/
@Override
public boolean onTouchEvent(MotionEvent event) {
if (mLock) {
return false;
}
int y = (int) event.getRawY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
// onInterceptTouchEvent已经记录
// mLastMotionY = y;
break;
case MotionEvent.ACTION_MOVE:
int deltaY = y - mLastMotionY;
if (mPullState == PULL_DOWN_STATE) {
// PullToRefreshView执行下拉
Log.i(TAG, " pull down!parent view move!");
headerPrepareToRefresh(deltaY);
// setHeaderPadding(-mHeaderViewHeight);
} else if (mPullState == PULL_UP_STATE) {
// PullToRefreshView执行上拉
Log.i(TAG, "pull up!parent view move!");
footerPrepareToRefresh(deltaY);
}
mLastMotionY = y;
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
int topMargin = getHeaderTopMargin();
if (mPullState == PULL_DOWN_STATE) {
if (topMargin >= 0) {
// 开始刷新
headerRefreshing();
} else {
// 还没有执行刷新,重新隐藏
setHeaderTopMargin(-mHeaderViewHeight);
}
} else if (mPullState == PULL_UP_STATE) {
if (Math.abs(topMargin) >= mHeaderViewHeight
+ mFooterViewHeight) {
// 开始执行footer 刷新
footerRefreshing();
} else {
// 还没有执行刷新,重新隐藏
setHeaderTopMargin(-mHeaderViewHeight);
}
}
break;
}
//		return super.onTouchEvent(event);
//		super.onTouchEvent(event);
return true;
}


这里例子可以很好的理解onInterceptTouchEvent、onTouchEvent、GestureDetector、SimpleOnGestureListener

以上部分代码来自网络,我只是为了理解触摸事件,自己加一些注释记录一下,别骂人啊
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: