我有一个ListView,它有一个OnItemClickListener。最重要的是,每一行(CardView)都有一个OnTouchListener,以实现滑动手势。
OnTouchListener对ACTION_DOWN,ACTION_CANCEL,ACTION_MOVE和ACTION_UP作出反应。我在ACTION_UP发生时使用performItemClick(),以便在需要时调用OnItemClickListener。
如果我在OnTouchListener中返回true,我通过ACTION_MOVE实现的滑动运动效果很好,单击该项也可以。 然而,视觉反馈为零。通常情况下,Lollipop会出现波纹或ICS背景会发生变化。
如果我返回False(意味着我不想拦截事件),那么就会有视觉反馈并且点击工作......但是我的OnTouchListener从不拦截任何ACTION_MOVE事件。这可以防止任何滑动。
我尝试了各种解决方案,例如使用v.setpressed()但它没有效果。
我很想知道如果我的OnTouchListener没有拦截事件,我将如何保留涟漪(或一般的视觉反馈)。
如果你很好奇,这是我的OnTouchListener。
private final View.OnTouchListener mTouchListener = new View.OnTouchListener() {
float mDownX;
private int mSwipeSlop = -1;
private boolean mItemPressed;
private VelocityTracker mVelocityTracker = null;
private HashMap<Long, Integer> mItemIdTopMap = new HashMap<>();
@Override
public boolean onTouch(final View v, MotionEvent event) {
int index = event.getActionIndex();
int pointerId = event.getPointerId(index);
if (mSwipeSlop < 0) {
mSwipeSlop = ViewConfiguration.get(getActivity())
.getScaledTouchSlop();
}
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
if (mItemPressed) {
// Multi-item swipes not handled
return false;
}
mItemPressed = true;
mDownX = event.getX();
if (mVelocityTracker == null) {
// Retrieve a new VelocityTracker object to watch the velocity of a motion.
mVelocityTracker = VelocityTracker.obtain();
} else {
// Reset the velocity tracker back to its initial state.
mVelocityTracker.clear();
}
mVelocityTracker.addMovement(event);
break;
case MotionEvent.ACTION_CANCEL:
v.setAlpha(1);
v.setTranslationX(0);
mItemPressed = false;
mVelocityTracker.recycle();
mVelocityTracker = null;
break;
case MotionEvent.ACTION_MOVE: {
mVelocityTracker.addMovement(event);
float x = event.getX() + v.getTranslationX();
float deltaX = x - mDownX;
float deltaXAbs = Math.abs(deltaX);
if (!mSwiping) {
if (deltaXAbs > mSwipeSlop) {
mSwiping = true;
getListView().requestDisallowInterceptTouchEvent(true);
mBackgroundContainer.showBackground(v.getTop(), v.getHeight());
}
}
if (mSwiping) {
v.setTranslationX((x - mDownX));
v.setAlpha(1 - deltaXAbs / v.getWidth());
}
}
break;
case MotionEvent.ACTION_UP: {
// User let go - figure out whether to animate the view out, or back into place
if (mSwiping) {
float x = event.getX() + v.getTranslationX();
float deltaX = x - mDownX;
float deltaXAbs = Math.abs(deltaX);
float fractionCovered;
float endX;
float endAlpha;
final boolean remove;
mVelocityTracker.computeCurrentVelocity(1000);
float velocityX = Math.abs(VelocityTrackerCompat.getXVelocity(mVelocityTracker, pointerId));
if (velocityX > 700 || deltaXAbs > v.getWidth() / 4) {
// fixme
fractionCovered = deltaXAbs / v.getWidth();
endX = deltaX < 0 ? -v.getWidth() : v.getWidth();
endAlpha = 0;
remove = true;
} else {
// Not far enough - animate it back
fractionCovered = 1 - (deltaXAbs / v.getWidth());
endX = 0;
endAlpha = 1;
remove = false;
}
mVelocityTracker.clear();
int SWIPE_DURATION = 600;
long duration = (int) ((1 - fractionCovered) * SWIPE_DURATION);
getListView().setEnabled(false);
v.animate().setDuration(duration).
alpha(endAlpha).translationX(endX).
withEndAction(new Runnable() { // fixme replace with AnimationListener
@Override
public void run() {
// Restore animated values
v.setAlpha(1);
v.setTranslationX(0);
if (remove) {
animateRemoval(getListView(), v);
} else {
mBackgroundContainer.hideBackground();
mSwiping = false;
getListView().setEnabled(true);
}
}
});
} else {
int position = getListView().getPositionForView(v);
if (position != ListView.INVALID_POSITION)
getListView().performItemClick(v, position, getListView().getItemIdAtPosition(position));
}
}
mItemPressed = false;
break;
default:
return false;
}
return true;
}
private void animateRemoval(final ListView listview, View viewToRemove) {
// irrelevant
}
};
这是基于几年前Chet Haase的demo。
我真的无法理解。帮助
谢谢!
答案 0 :(得分:8)
对我来说,v.setPressed做了诀窍,其中v是接收触摸事件的视图。这意味着在ACTION_DOWN上我调用了v.setPressed(true)和在ACTION_UP上调用v.setPressed(false)
答案 1 :(得分:0)
我发现导致出现新片段的点击可以防止出现波纹。在点击中添加一个短暂的延迟解决了我的问题。就是这个
columnViewHolder.rippleLayout.setOnClickListener((v) -> {
dataManager.setProducts(id, response.getProducts());
dataManager.setProductListPosition(id, position);
dataManager.clearCurrentProductItem();
Log.d(TAG, "product click " + product.toString());
EventBus.getDefault().post(new ProductDetailEvent(id, product));
tagManager.hubSpokeClick(product.getCode());
});
不起作用,但确实如此:
columnViewHolder.rippleLayout.setOnClickListener((v) -> {
handler.postDelayed(() -> {
dataManager.setProducts(id, response.getProducts());
dataManager.setProductListPosition(id, position);
dataManager.clearCurrentProductItem();
Log.d(TAG, "product click " + product.toString());
EventBus.getDefault().post(new ProductDetailEvent(id, product));
tagManager.hubSpokeClick(product.getCode());
}, 200l);
});