解决android中HorizontalScrollView的滚动事件与组件的Touch冲突问题 --- 修正版

 


在上一章 中的解决android中HorizontalScrollView的滚动事件与组件的Touch冲突问题 这一篇文章中虽然组件能够在滑动的时候检测到up事件,但是无法滑动,而在这里我们可以用另一种方法来实现,那就是当我们touch的时候,在MotionEvent中有一种情况就是MotionEvent.ACTION_CANCEL,这个事件是指Touch事件的取消通知,这样我们虽然无法捕获up事件但是我们可以通过MotionEvent.ACTION_CANCEL来判断用户之前是否进行了MotionEvent.ACTION_DOWN事件,如果用户MotionEvent.ACTION_DOWN则设置flag =0,当进入CANCEL时,判断一下当前是否flag ==0 ,如果等于0,则这里实现up的功能。

 

当然这种方法也不是完美的,原因在于用户是想实现组件的touch事件还是实现滚动事件,因为如果用户想滑动的,但是用户却触摸到实现Touch事件的组件,如果用户想实现组件的touch事件,但是却移动了一下组件,这个定界不好解决,

还有一个折中的方法就是触摸点的坐标,这里假设组件是宽大于高,那我们就要用event.getX(),当手的MotionEvent.ACTION_MOVE触摸点与MotionEvent.ACTION_DOWN的间距大于diff(这个用户自己设置),我们就认为它是滑动,这时设置flag=-1,否则我们认为是组件的Touch事件,那就重写onInterceptTouchEvent,内容如下:

@Override
	public boolean onInterceptTouchEvent(MotionEvent ev) {
		Log.e("tet", MainActivity.flag+"  ");
		if (MainActivity.flag == -1) {
			return super.onInterceptTouchEvent(ev);
		}else{
			return false;
		}
	}

返回false,让组件实现Touch的up事件。

 

当然我们不可能无限制的去检测距离来判断,因为有时我们我们需要在Down的时候改变组件的背景,当松开手的时候,再次改变组件的背景,所以,我们还要添加一个时间的检测功能,当在timeout(用户自己设置)内并且小于diff,则我们认为是组件的touch事件,否则则认为是滚动事件。综上所述,我们就可以解决滚动和Touch的冲突问题。

Horizon.java内容:

package com.example.test;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.HorizontalScrollView;

public class Horizon extends HorizontalScrollView{

	public Horizon(Context context) {
		super(context);
	}
	
	public Horizon(Context context, AttributeSet attrs) {
		super(context, attrs);
	}


	@Override
	public boolean onInterceptTouchEvent(MotionEvent ev) {
		Log.e("tet", MainActivity.flag+"  ");
		if (MainActivity.flag == 0) {
			return false;
		}else{
			return super.onInterceptTouchEvent(ev);
		}
	}

}

主类:

package com.example.test;

import android.os.Bundle;
import android.app.Activity;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.widget.Button;

public class MainActivity extends Activity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		btn1 = (Button)findViewById(R.id.btn1);
		btn1.setOnTouchListener(new OnTouchListener() {
			@Override
			public boolean onTouch(View v, MotionEvent event) {
				switch (event.getAction()) {
				case MotionEvent.ACTION_DOWN:
					flag = 0;
					Down_t = System.currentTimeMillis();
					Down_x = event.getX();
					Log.e("test", "down  "+event.getX());
					break;
				case MotionEvent.ACTION_MOVE:
					if (Math.abs(event.getX() - Down_x) > diff && (System.currentTimeMillis() - Down_t) <= timeout) {
						flag = 1;//认为是滑动
					}
					Log.e("test", "move  "+event.getX());
					break;
				case MotionEvent.ACTION_UP:
					Log.e("test", "up");
					flag = -1;
					break;
				case MotionEvent.ACTION_CANCEL:
					if(flag == 0 || flag == 1){
						flag = -1;
					}
					Log.e("test", "cancel");
					break;
				}
				return false;
			}
		});
		btn3 = (Button)findViewById(R.id.btn3);
		btn3.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				Log.e("tec", "clic");
			}
		});
	}

	public Button btn1;
	public Button btn3;
	public static int flag = -1;
	public float Down_x = 0;
	public float diff = 2;
	public long  Down_t = 0;
	public long timeout = 100;
}


所以上面我们在Touch上面的Down事件中改变图片的功能,在Move的else里面来实现
case MotionEvent.ACTION_MOVE:
     if (Math.abs(event.getX() - Down_x) > diff && (System.currentTimeMillis() - Down_t) <= timeout) {
      flag = 1;
     }else{

       

   }

当然还需要精细一点的就是Touch事件中的MOVE事件太多,我们可以添加一个标志位,只有在flag ==0的时候才去判断间距和超时,同样改变背景颜色的只有在flag =0的时候,还要设置flag = 2,这样即使move事件也不会进入这两个判断条件,但是相应的Horizon这个类中的判断条件相应的还要添加一个条件,

if (MainActivity.flag == 0 || MainActivity.flag == 2) {
   return false;
  }else{
   return super.onInterceptTouchEvent(ev);
  }

 

同样下面的MOVE代码如下:

case MotionEvent.ACTION_MOVE:
					if (flag == 0 && Math.abs(event.getX() - Down_x) > diff && (System.currentTimeMillis() - Down_t) < timeout) {
						flag = 1;//认为是滑动
					}else if(flag == 0 && Math.abs(event.getX() - Down_x) <= diff && (System.currentTimeMillis() - Down_t) >= timeout){
						flag = 2;
					}
					Log.e("test", "move  "+event.getX());
					break;


 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值