点击事件的传递
1.DispatchTouchEvent()返回True代表可以分发事件,
2.onInterceptTouchEvent()返回False表示不拦截事件,
3.onTouchEvent()返回True代表执行点击事件,在执行完以后必须返回True,否则不会处理Touch事件
通过点击事件来实现下拉刷新的操作
实现下拉刷新的原理其实就是在FramLayout布局中添加两个View,写有下拉刷新的View放在最底下,然后拖拽最上面的一个View将下面的View漏出来,来实现刷新操作,最后在将最上面的View放回到原来的位置
1.首先创建一个Java类继承与FramLayout,然后复写里面的构造器
2.得到LayoutInflater对象,然后添加View
3.在onInterceptTouchEvent()中设置条件进行事件拦截,最后交给TouchEvent处理
4.在TouchEvent对事件进行处理,实现下拉刷新的操作
public class MyRefresh extends FrameLayout{
private ListView content;
public MyRefresh(Context context) {
super(context);
}
public MyRefresh(Context context, AttributeSet attrs) {
super(context, attrs);
//得到inflater
LayoutInflater inflater= (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
//添加View
View refresh=inflater.inflate(R.layout.refresh, null);
addView(refresh);
//添加ListView
content=(ListView) inflater.inflate(R.layout.content, null);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(context, android.R.layout.simple_list_item_1,
new String[]{"as", "sadf", "der", "as", "sadf", "der", "as", "sadf", "der",
"as", "sadf", "der", "as", "sadf", "der", "as", "sadf", "der"});
content.setAdapter(adapter);
addView(content);
Log.d("fresh","第一个子View的位置"+content.getFirstVisiblePosition());
}
public MyRefresh(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
Log.d("fresh","DispatchTouchEvent:"+ev.getAction()+"是否拦截:"+super.dispatchTouchEvent(ev));
return super.dispatchTouchEvent(ev);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
if (ev.getAction()==MotionEvent.ACTION_DOWN){
Log.d("fresh","InterceptTouchEvent:"+ev.getAction()+"是否拦截:"+super.onInterceptTouchEvent(ev));
}
//判断ListView的位置,如果ListView的第一个子View的位置在(0,0)就拦截事件,然后然后就发送到onTOuchEvent事件中进行处理
if (content.getFirstVisiblePosition()==0){
View firstView=content.getChildAt(0);
Log.d("fresh","得到第一个View的Y值"+firstView.getY());
if (firstView.getY()>=0.0){
Log.d("fresh","已经拦截");
return true;//返回true就表示拦截
}
}
return super.onInterceptTouchEvent(ev);
}
float oldY;
float y;
@Override
public boolean onTouchEvent(MotionEvent event) {
Log.d("fresh","运行到"+event.ACTION_DOWN);
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
oldY=event.getY();//首先得到触摸时的位置
Log.d("fresh","oldy的值为"+oldY);
break;
case MotionEvent.ACTION_MOVE:
Log.d("fresh","运行到"+event.ACTION_MOVE);
y=event.getY();//MOVE结束时的位置
float distance=y-oldY;//得到MOVE距离
content.setTranslationY(content.getTranslationY()+distance);//位移
oldY=y;
invalidate();
break;
case MotionEvent.ACTION_UP:
Log.d("fresh","运行到"+event.ACTION_UP);
//设置动画将ListView放回到原来的位置
ObjectAnimator.ofFloat(content,"translationY",content.getTranslationY(),0).setDuration(300).start();
break;
}
return true;
}
}
其中ListView的xml布局是
<?xml version="1.0" encoding="utf-8"?>
<ListView xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ffffff">
</ListView>
手势检测
0.创建一个Java类继承一个Button
1.首先创建一个手势对象,然后在设置Simple监听事件复写里面的方法
2.最后需要在TouchEvent事件中将手势事件放入到里面
3.最后创建一个自定义的手势监听
public class MyButton extends Button {
/***
* 自定义点击监听
* 首先是写一个接口,里面包含一个方法,这个方法里的参数包含了这个View
* 然后创建一个实例化的对象
* 最后给这个对象加上一个set方法
*/
public interface OnClickDoubleListener{
public void onClickDouble(View v);
}
private OnClickDoubleListener listener;
public void setOnClickDoubleListener(OnClickDoubleListener listener) {
this.listener = listener;
}
public OnClickDoubleListener getListener() {
return listener;
}
private GestureDetector mGesture;//创建一个手势检测对象
public MyButton(Context context) {
super(context);
}
public MyButton(final Context context, AttributeSet attrs) {
super(context, attrs);
//创建手势监听复写方法
mGesture=new GestureDetector(context,new GestureDetector.SimpleOnGestureListener(){
//复写点击两次的方法
@Override
public boolean onDoubleTap(MotionEvent e) {
if (listener!=null){
listener.onClickDouble(MyButton.this);
}
Log.d("button","连续点击了两次");
return true;
}
//复写滑动方法
//第一个参数是DOWN下的事件,即手触摸到屏幕时的事件
//第二个参数是MOVE事件,即手移动时的事件,
//第三个参数是沿x轴滑动的速度
//第四个参数是是沿Y轴滑动的速度
// @Override
// public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
// if (Math.abs(e2.getX()-e1.getX())>50){
// setTranslationX(e2.getX()-e1.getX());//X轴平移平移
// ObjectAnimator.ofFloat(MyButton.this,"translationX",getTranslationX(),e2.getX()-e1.getX()).setDuration(2000).start();
// return true;
// }
// return super.onFling(e1, e2, velocityX, velocityY);
// }
//复写滚动方法
//第一个参数是DOWN下的事件,即手触摸到屏幕时的事件
//第二个参数是MOVE事件,即手移动时的事件,
//第三个参数是沿x轴滑动的速度
//第四个参数是是沿Y轴滑动的速度
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
setTranslationX(getTranslationX()+e2.getX()-e1.getX());//X轴平移
setTranslationY(getTranslationY()+e2.getY()-e1.getY());//Y轴平移
return super.onScroll(e1, e2, distanceX, distanceY);
}
});
}
public MyButton(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
mGesture.onTouchEvent(event);//手势检测一定要在onTouchEvent中获取事件,否则不会触发时间
return super.onTouchEvent(event);
}
}