场景:ViewFlipper中添加了几个View,每个View中有几条itemView,每个itemView设置了setOnClickListener,ViewFlipper中通过GestureDetector来控制左右翻页效果。
问题:不滑动,点击每个itemView,运行正常,当触发了滑动后,手势抬起时,依然会执行itemView的click事件
解决:在继承的ViewFlipper中,拦截手势动作onInterceptTouchEvent来拦截MotionEvent.ACTION_UP动作,如果正在处理滑动,直接返回true,不再下发,放置触发itemView的点击事件,下面给出ViewFlipper的代码,里面有注释
package com.custom.views.carousel;
import android.content.Context;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.TranslateAnimation;
import android.widget.ViewFlipper;
import java.util.ArrayList;
import java.util.List;
/**
* Created by menghui on 2017/10/23.
*/
public class JRJCarouselFlipper extends ViewFlipper {
/**
* 视图切换监听
*/
public interface CarouselChanged{
void onChanged(int oldIndex,int newIndex,View view);
}
private Animation rightInAnim,leftOutAnim,rightOutAnim,leftInAnim;
private List views;
private CarouselChanged carouselChanged;
//动画周期
private int duration = 500;
private GestureDetector gestureDetector;
private GestureDetector.OnGestureListener gestureListener;
//是否滑动中,该标志用来避免gesture的滑动和滑动View中item的点击冲突
private boolean fling = false;
public JRJCarouselFlipper(Context context) {
super(context);
init(context);
}
public JRJCarouselFlipper(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
private void init(Context ctx){
gestureListener = new GestureDetector.OnGestureListener() {
@Override
public boolean onDown(MotionEvent e) {
fling = false;
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) {
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
fling = true;
if (e1.getX() - e2.getX() > 100) {
setInAnimation(rightInAnim);
setOutAnimation(leftOutAnim);
int old = getDisplayedChild();
showNext();
int newindex = getDisplayedChild();
triggerChanged(old,newindex);
return true;
} else if (e1.getX() - e2.getX() < -100) {
setInAnimation(leftInAnim);
setOutAnimation(rightOutAnim);
int old = getDisplayedChild();
showPrevious();
int newindex = getDisplayedChild();
triggerChanged(old,newindex);
return true;
}
return false;
}
};
gestureDetector = new GestureDetector(gestureListener);
views = new ArrayList<>();
// 图片从右侧滑入
rightInAnim = new TranslateAnimation(Animation.RELATIVE_TO_PARENT, 1.0f,
Animation.RELATIVE_TO_PARENT, 0.0f,
Animation.RELATIVE_TO_PARENT, 0.0f,
Animation.RELATIVE_TO_PARENT, 0.0f);
rightInAnim.setDuration(duration);
// 图片从左侧滑出
leftOutAnim = new TranslateAnimation(Animation.RELATIVE_TO_PARENT, 0.0f,
Animation.RELATIVE_TO_PARENT, -1.0f,
Animation.RELATIVE_TO_PARENT, 0.0f,
Animation.RELATIVE_TO_PARENT, 0.0f);
leftOutAnim.setDuration(duration);
// 图片从右侧滑出
rightOutAnim = new TranslateAnimation(Animation.RELATIVE_TO_PARENT, 0.0f,
Animation.RELATIVE_TO_PARENT, 1.0f,
Animation.RELATIVE_TO_PARENT, 0.0f,
Animation.RELATIVE_TO_PARENT, 0.0f);
rightOutAnim.setDuration(duration);
// 图片从左侧滑入
leftInAnim = new TranslateAnimation(Animation.RELATIVE_TO_PARENT, -1.0f,
Animation.RELATIVE_TO_PARENT, 0.0f,
Animation.RELATIVE_TO_PARENT, 0.0f,
Animation.RELATIVE_TO_PARENT, 0.0f);
leftInAnim.setDuration(duration);
}
private void triggerChanged(int oldIndex,int newIndex){
if (views.size() <= 0)
return;
if (carouselChanged != null){
carouselChanged.onChanged(oldIndex,newIndex,views.get(newIndex));
}
}
public CarouselChanged getCarouselChanged() {
return carouselChanged;
}
public void setCarouselChanged(CarouselChanged carouselChanged) {
this.carouselChanged = carouselChanged;
}
/**
* 设置要轮播的视图列表
* @param views
*/
public void setViews(List views) {
this.views.clear();
this.removeAllViews();
this.views.addAll(views);
for(View v:views){
this.addView(v);
}
}
/**
* 拦截触屏,当按下时,fling=false,允许点击子视图中的item,当手势抬起时,为避免和滑动发生冲突,判断fling状态,
* 如果处于滑动中,并且是手势抬起,返回true,不再向下传递,使item点击事件失效
* @param ev
* @return
*/
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN)
fling = false;
else if (fling && ev.getAction() == MotionEvent.ACTION_UP){
return true;
}
return super.onInterceptTouchEvent(ev);
}
/**
* 分发触屏,交给gesture
* @param ev
* @return
*/
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
gestureDetector.onTouchEvent(ev);
return super.dispatchTouchEvent(ev);
}
}