Android-ViewFlipper的滑动与子视图中item点击的冲突解决

场景: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);
    }

}


你可能感兴趣的:(Android)