我有一个自定义的java类,它扩展了FrameLayout,它位于另一个扩展了FrameLayout的自定义父视图之上
我具有以下功能,可通过动画关闭视图-
private void dismissCard(final View view, int xPos) {
view.animate()
.x(xPos)
.y(0)
.setInterpolator(new AccelerateInterpolator())
.setDuration(DURATION)
.setListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animator) {
setOnTouchListener(null);
}
@Override
public void onAnimationEnd(Animator animator) {
ViewGroup viewGroup = (ViewGroup) view.getParent();
if (viewGroup != null) {
viewGroup.removeView(view);
}
}
@Override
public void onAnimationCancel(Animator animator) {
}
@Override
public void onAnimationRepeat(Animator animator) {
}
});
}
问题是,我已经覆盖了onTouch()
函数以移动视图功能,并且每次触摸时,我都会获得该视图的父级(这是一个自定义视图),获取该视图的所有子级并由此确定视图在顶部。因此,我的问题是,在制作动画时,动画视图仍位于顶部,因此可以再次移动动画,直到动画消失并调用viewGroup.removeView(view)
。
这是我的onTouch()
实现-
@Override
public boolean onTouch(final View view, MotionEvent motionEvent) {
TinderStackLayout tinderStackLayout = ((TinderStackLayout) view.getParent());
TinderCardView topCard = (TinderCardView) tinderStackLayout.getChildAt(tinderStackLayout.getChildCount() - 1);
if (topCard.equals(view)) {
switch (motionEvent.getAction()) {
case MotionEvent.ACTION_DOWN:
oldX = motionEvent.getX();
oldY = motionEvent.getY();
// cancel any current animations
view.clearAnimation();
return true;
case MotionEvent.ACTION_UP:
if (isCardBeyondLeftBoundary(view)) {
Log.d("top card dismissed - ", topCard.usernameTextView.getText().toString());
onCardSwipedListener.send(new TopCardMovedEvent(-(screenWidth)));
dismissCard(view, -(screenWidth * 2));
} else if (isCardBeyondRightBoundary(view)) {
showLawyerContactDetailsFragment(topCard);
onCardSwipedListener.send(new TopCardMovedEvent(-(screenWidth)));
resetCard(view);
} else {
onCardSwipedListener.send(new TopCardMovedEvent(-(screenWidth)));
resetCard(view);
}
return true;
case MotionEvent.ACTION_MOVE:
newX = motionEvent.getX();
newY = motionEvent.getY();
dX = newX - oldX;
dY = newY - oldY;
float posX = view.getX() + dX;
onCardSwipedListener.send(new TopCardMovedEvent(-(screenWidth)));
// Set new position
view.setX(view.getX() + dX);
view.setY(view.getY() + dY);
setCardRotation(view, view.getX());
updateAlphaOfBadges(posX);
return true;
default:
return super.onTouchEvent(motionEvent);
}
}
return super.onTouchEvent(motionEvent);
}
[我缺少的是一种在dismissCard()
制作动画时阻止触摸能力的方法。我该如何实施?
在要设置动画的类中声明一个布尔变量(isAnimating),并在onAnimationStart
中将其设置为true,在onAnimationEnd
中将其设置为false。
在onTouch
中访问此变量
@Override
public boolean onTouch(final View view, MotionEvent motionEvent) {
TinderStackLayout tinderStackLayout = ((TinderStackLayout) view.getParent());
TinderCardView topCard = (TinderCardView) tinderStackLayout.getChildAt(tinderStackLayout.getChildCount() - 1);
if (topCard.equals(view)&& !isAnimating) { //access event's only if animation is ended.
switch (motionEvent.getAction()) {
case MotionEvent.ACTION_DOWN:
oldX = motionEvent.getX();
oldY = motionEvent.getY();
// cancel any current animations
view.clearAnimation();
return true;
case MotionEvent.ACTION_UP:
if (isCardBeyondLeftBoundary(view)) {
Log.d("top card dismissed - ", topCard.usernameTextView.getText().toString());
onCardSwipedListener.send(new TopCardMovedEvent(-(screenWidth)));
dismissCard(view, -(screenWidth * 2));
} else if (isCardBeyondRightBoundary(view)) {
showLawyerContactDetailsFragment(topCard);
onCardSwipedListener.send(new TopCardMovedEvent(-(screenWidth)));
resetCard(view);
} else {
onCardSwipedListener.send(new TopCardMovedEvent(-(screenWidth)));
resetCard(view);
}
return true;
case MotionEvent.ACTION_MOVE:
newX = motionEvent.getX();
newY = motionEvent.getY();
dX = newX - oldX;
dY = newY - oldY;
float posX = view.getX() + dX;
onCardSwipedListener.send(new TopCardMovedEvent(-(screenWidth)));
// Set new position
view.setX(view.getX() + dX);
view.setY(view.getY() + dY);
setCardRotation(view, view.getX());
updateAlphaOfBadges(posX);
return true;
default:
return super.onTouchEvent(motionEvent);
}
}
return super.onTouchEvent(motionEvent);
}
P.S-更好的解决方案是,当isAnimating为true
时返回false。在我的应用中,我重写了父类中的分派操作,并且不允许任何事件到达父类或其子类。
override fun dispatchTouchEvent(ev: MotionEvent?): Boolean {
if (isAnimationOnGoing) {
return false
}
return super.dispatchTouchEvent(ev)
}