Android-ViewFlipper的滑動與子檢視中item點選的衝突解決
阿新 • • 發佈:2019-01-25
場景: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<View> 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<View> 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); } }