GestureDetectorCompat和OnClick时间的冲突

黑金白土 2017-02-07 09:48:56
最近项目中有一个需求是类似于探探的滑动页面的,具体效果为手指滑动页面可以随手指移动,超过一定距离后,这个页面就消失,并显示下一个页面(如果还有下个页面)。本项目中该页面含有多张图片及文字,点击图片可以查看图片,点击文字进入到详情页面。从网上找了一个案例后,移植过来,出现以下问题:当图片及文字部分增加点击事件后,这个页面的滑动效果就不起作用了,并相应的是点击事件,即这个控件内部的子view消费了滑动事件。
具体代码为:
可滑动控件部分代码:
public class CardStack extends RelativeLayout {
public interface CardEventListener{
//section
// 0 | 1
//--------
// 2 | 3
// swipe distance, most likely be used with height and width of a view ;

public boolean swipeEnd(int section, float distance);
public boolean swipeStart(int section, float distance);
public boolean swipeContinue(int section, float distanceX, float distanceY);
public void discarded(int mIndex, int direction);
public void topCardTapped();
}
public CardStack(Context context, AttributeSet attrs) {
super(context, attrs);

//String sMyValue = attrs.getAttributeValue( "http://schemas.android.com/apk/res/android", "padding" );
//get attrs assign minVisiableNum
for(int i = 0; i<mNumVisible; i++){
addContainerViews();
}
setupAnimation();
}
private void setupAnimation(){
final View cardView = viewCollection.get(viewCollection.size()-1);
mCardAnimator = new CardAnimator(viewCollection);
mCardAnimator.initLayout();

final DragGestureDetector dd = new DragGestureDetector(CardStack.this.getContext(),new DragGestureDetector.DragListener(){

@Override
public boolean onDragStart(MotionEvent e1, MotionEvent e2,
float distanceX, float distanceY) {
mCardAnimator.drag(e1,e2,distanceX,distanceY);
return true;
}

@Override
public boolean onDragContinue(MotionEvent e1, MotionEvent e2,
float distanceX, float distanceY) {
float x1 = e1.getRawX();
float y1 = e1.getRawY();
float x2 = e2.getRawX();
float y2 = e2.getRawY();
//float distance = CardUtils.distance(x1,y1,x2,y2);
final int direction = CardUtils.direction(x1,y1,x2,y2);
mCardAnimator.drag(e1,e2,distanceX,distanceY);
mEventListener.swipeContinue(direction, Math.abs(x2-x1), Math.abs(y2-y1));
return true;
}

@Override
public boolean onDragEnd(MotionEvent e1, MotionEvent e2) {
//reverse(e1,e2);
float x1 = e1.getRawX();
float y1 = e1.getRawY();
float x2 = e2.getRawX();
float y2 = e2.getRawY();
float distance = CardUtils.distance(x1,y1,x2,y2);
final int direction = CardUtils.direction(x1,y1,x2,y2);

boolean discard = mEventListener.swipeEnd(direction, distance);
if(discard){
mCardAnimator.discard(direction, new AnimatorListenerAdapter(){

@Override
public void onAnimationEnd(Animator arg0) {
mCardAnimator.initLayout();
mIndex++;
mEventListener.discarded(mIndex,direction);

//mIndex = mIndex%mAdapter.getCount();
loadLast();

viewCollection.get(0).setOnTouchListener(null);
viewCollection.get(viewCollection.size()-1)
.setOnTouchListener(mOnTouchListener);
}

});
}else{
mCardAnimator.reverse(e1,e2);
}
return true;
}

@Override
public boolean onTapUp() {
mEventListener.topCardTapped();
return true;
}
}
);

mOnTouchListener = new OnTouchListener() {
private static final String DEBUG_TAG = "MotionEvents";
@Override
public boolean onTouch(View arg0, MotionEvent event) {
dd.onTouchEvent(event);
return true;
}
};
cardView.setOnTouchListener(mOnTouchListener);
}
}

以下是DragGestureDetector 的部分代码:
public class DragGestureDetector {
GestureDetectorCompat mGestrueDetector;
DragListener mListener;
private boolean mStarted = false;
private MotionEvent mOriginalEvent;
public static interface DragListener {
public boolean onDragStart(MotionEvent e1, MotionEvent e2, float distanceX,
float distanceY);
public boolean onDragContinue(MotionEvent e1, MotionEvent e2, float distanceX,
float distanceY);
public boolean onDragEnd(MotionEvent e1, MotionEvent e2);

public boolean onTapUp();
}

public DragGestureDetector(Context context, DragListener myDragListener){
mGestrueDetector = new GestureDetectorCompat(context,new MyGestureListener());
mListener = myDragListener;
}
public void onTouchEvent(MotionEvent event){
mGestrueDetector.onTouchEvent(event);
int action = MotionEventCompat.getActionMasked(event);
switch(action) {
case (MotionEvent.ACTION_UP) :
Log.d(DEBUG_TAG,"Action was UP");
if(mStarted) {
mListener.onDragEnd(mOriginalEvent, event);
}
mStarted = false;
Log.e("TAG", "CardStack + ACTION_UP");
case (MotionEvent.ACTION_DOWN) :
//need to set this, quick tap will not generate drap event, so the
//originalEvent may be null for case action_up
//which lead to null pointer
mOriginalEvent = event;

case MotionEvent.ACTION_MOVE:
break;
}
}
class MyGestureListener extends GestureDetector.SimpleOnGestureListener {
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
float distanceY) {
if(mListener == null) return true;
if( mStarted == false){
mListener.onDragStart(e1,e2,distanceX,distanceY);
mStarted = true;
}
else{
mListener.onDragContinue(e1,e2,distanceX,distanceY);
}
mOriginalEvent = e1;
return true;
}

@Override
public boolean onSingleTapUp(MotionEvent e) {

return mListener.onTapUp();
}
}
}

以下是activity的部分代码:
public class YuepaoSwipActivity extends BaseActivity implements View.OnClickListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
ActivityUtil.setTransparentActivity(this);
this.setContentView(R.layout.activity_yuepao_swiper);

mCardStack = (CardStack)findViewById(R.id.container);
mCardStack.setContentResource(R.layout.card_content);
mCardStack.setStackMargin(9);
mCardAdapter = new CardsDataAdapter(this,0);

for(int i= 0; i<10; i++) {
YuepaoBean bean = new YuepaoBean();
bean.a = i;
// mCardAdapter.add(bean);
}
// mCardStack.setAdapter(mCardAdapter);

initView();
initData();
}
}
请教大神,我应该如何解决这个冲突?
...全文
254 3 打赏 收藏 转发到动态 举报
写回复
用AI写文章
3 条回复
切换为时间正序
请发表友善的回复…
发表回复
chinahbbt 2017-02-07
  • 打赏
  • 举报
回复
计算手指滑动的距离,如果距离大于0说明是滑动,则禁止事件传递.否则事件向子view传递
黑金白土 2017-02-07
  • 打赏
  • 举报
回复
引用 1 楼 jscoolstar 的回复:
不能运行不好调试啊, View cardView = viewCollection.get(viewCollection.size()-1);我觉得你这个view重写一下应该可以解决,要重写它的dispatchTouchEvent,判断如果滑动距离大于最小值(即非点击事件时),返回true,自己消费。
主要是代码太多了,你说的很对,我之前的着手点可能有些偏了,我先试试
jscoolstar 2017-02-07
  • 打赏
  • 举报
回复
不能运行不好调试啊, View cardView = viewCollection.get(viewCollection.size()-1);我觉得你这个view重写一下应该可以解决,要重写它的dispatchTouchEvent,判断如果滑动距离大于最小值(即非点击事件时),返回true,自己消费。

80,350

社区成员

发帖
与我相关
我的任务
社区描述
移动平台 Android
androidandroid-studioandroidx 技术论坛(原bbs)
社区管理员
  • Android
  • yechaoa
  • 失落夏天
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧