如何在项目动画期间禁用 RecyclerView 项目装饰绘图
How to disable RecyclerView item decoration drawing for the duration of item animations
我有一些基本的物品装饰,用 ItemDecoration.onDrawOver
方法画了一些东西。
这个 RecyclerView
也设置了 DefaultItemAnimator
。
动画正在运行,一切都很好。除了一件事。
当所有现有项目与此适配器中的新项目集交换时,装饰将在动画 运行 时显示。
我需要一种隐藏它们的方法。
当动画结束时,它们需要显示,但当它是 运行 时,它们必须隐藏。
我尝试了以下方法:
public void onDrawOver(..., RecyclerView.State state) {
if(state.willRunPredictiveAnimations() || state.willRunSimpleAnimations()) {
return;
}
// else do drawing stuff here
}
但这没有帮助。装饰仅在动画的短时间内被移除,但随后在仍然 运行.
时再次出现
设置还包括一个 RecyclerView.Adapter
,其中 hasStableIds() (以防万一)。
自己找到答案:
要在项目动画期间隐藏项目装饰,可以简单地使用此检查 onDraw/onDrawOver
:
public void onDrawOver(..., RecyclerView parent, ...) {
if(parent.getItemAnimator() != null && parent.getItemAnimator().isRunning()) {
return;
}
// else do drawing stuff here
}
这可能在某种程度上取决于您使用的动画类型,但至少对于 DefaultItemAnimator
您需要考虑在动画期间完成的 X/Y 转换。您可以使用 child.getTranslationX()
和 child.getTranslationY()
.
获取这些值
例如,对于onDraw/onDrawOver
的垂直情况:
private void drawVertical(Canvas c, RecyclerView parent) {
final int left = parent.getPaddingLeft();
final int right = parent.getWidth() - parent.getPaddingRight();
final int childCount = parent.getChildCount();
final int dividerHeight = mDivider.getIntrinsicHeight();
for (int i = 1; i < childCount; i++) {
final View child = parent.getChildAt(i);
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
final int ty = (int)(child.getTranslationY() + 0.5f);
final int top = child.getTop() - params.topMargin + ty;
final int bottom = top + dividerHeight;
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(c);
}
}
(如果您需要支持 < API 11,您可能更愿意使用 ViewCompat.getTranslationY(child)
。)
注意:对于其他类型的动画,可能需要进行额外的调整。 (例如,可能还需要考虑水平平移。)
您可以尝试检查子 alpha(仅针对案例默认动画)。如果 alpha 0 则什么都不做
我有一些基本的物品装饰,用 ItemDecoration.onDrawOver
方法画了一些东西。
这个 RecyclerView
也设置了 DefaultItemAnimator
。
动画正在运行,一切都很好。除了一件事。
当所有现有项目与此适配器中的新项目集交换时,装饰将在动画 运行 时显示。
我需要一种隐藏它们的方法。 当动画结束时,它们需要显示,但当它是 运行 时,它们必须隐藏。
我尝试了以下方法:
public void onDrawOver(..., RecyclerView.State state) {
if(state.willRunPredictiveAnimations() || state.willRunSimpleAnimations()) {
return;
}
// else do drawing stuff here
}
但这没有帮助。装饰仅在动画的短时间内被移除,但随后在仍然 运行.
时再次出现设置还包括一个 RecyclerView.Adapter
,其中 hasStableIds() (以防万一)。
自己找到答案:
要在项目动画期间隐藏项目装饰,可以简单地使用此检查 onDraw/onDrawOver
:
public void onDrawOver(..., RecyclerView parent, ...) {
if(parent.getItemAnimator() != null && parent.getItemAnimator().isRunning()) {
return;
}
// else do drawing stuff here
}
这可能在某种程度上取决于您使用的动画类型,但至少对于 DefaultItemAnimator
您需要考虑在动画期间完成的 X/Y 转换。您可以使用 child.getTranslationX()
和 child.getTranslationY()
.
例如,对于onDraw/onDrawOver
的垂直情况:
private void drawVertical(Canvas c, RecyclerView parent) {
final int left = parent.getPaddingLeft();
final int right = parent.getWidth() - parent.getPaddingRight();
final int childCount = parent.getChildCount();
final int dividerHeight = mDivider.getIntrinsicHeight();
for (int i = 1; i < childCount; i++) {
final View child = parent.getChildAt(i);
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
final int ty = (int)(child.getTranslationY() + 0.5f);
final int top = child.getTop() - params.topMargin + ty;
final int bottom = top + dividerHeight;
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(c);
}
}
(如果您需要支持 < API 11,您可能更愿意使用 ViewCompat.getTranslationY(child)
。)
注意:对于其他类型的动画,可能需要进行额外的调整。 (例如,可能还需要考虑水平平移。)
您可以尝试检查子 alpha(仅针对案例默认动画)。如果 alpha 0 则什么都不做