gpt4 book ai didi

android - 工具栏 animateLayoutChanges 奇怪的行为

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:21:45 26 4
gpt4 key购买 nike

我在我的代码中设置了 animateLayoutChanges=true 来为我的 fragment 中的选项项目设置动画。

当我打开 PreferenceFragment 时,我启用向上导航图标,然后在关闭它时将其禁用,但它的行为很奇怪,在标题左侧(NavigationIcon 所在的位置)留下了一种填充。

这是一个显示正在发生的事情的 gif:

img

你们知道为什么会这样吗?我在互联网上四处搜索,但一无所获。

是否有任何解决方法可以以相同的方式为这些项目设置动画?谢谢。

最佳答案

备注:我知道这个帖子已经一年多了,但很多人仍然遇到这个问题。

我花了好几个小时才最终深入研究这个问题,解决方案实际上相对容易。

场景

当你调用 ActionBar.setDisplayHomeAsUpEnabled() 或 Toolbar.setNavigationIcon() 时,Toolbar 将根据指定的值动态添加或删除导航 View

public void setNavigationIcon(@Nullable Drawable icon) {
if (icon != null) {
ensureNavButtonView();
if (!isChildOrHidden(mNavButtonView)) {
addSystemView(mNavButtonView, true);
}
} else if (mNavButtonView != null && isChildOrHidden(mNavButtonView)) {
removeView(mNavButtonView);
mHiddenViews.remove(mNavButtonView);
}
if (mNavButtonView != null) {
mNavButtonView.setImageDrawable(icon);
}
}

在 onLayout 中,它会检查导航按钮是否存在并对其进行布局。

protected void onLayout(boolean changed, int l, int t, int r, int b) {

// more code before

if (shouldLayout(mNavButtonView)) {
if (isRtl) {
right = layoutChildRight(mNavButtonView, right, collapsingMargins,
alignmentHeight);
} else {
left = layoutChildLeft(mNavButtonView, left, collapsingMargins,
alignmentHeight);
}
}

// more code after. also mTitleTextView is laid out here
}

在布置每个 View 后,工具栏还会增加左/右位置。这些值用作每个后续 View 的偏移量。

要检查 View 是否应该布局,它使用辅助函数:

private boolean shouldLayout(View view) {
return view != null && view.getParent() == this && view.getVisibility() != GONE;
}

问题

当通过代码或 xml 中的 animateLayoutChanges 设置 layoutTransition 时,我们会稍微改变行为。

让我们从从父项(ViewGroup 代码)中移除子项时发生的事情开始:

private void removeFromArray(int index) {
final View[] children = mChildren;
if (!(mTransitioningViews != null && mTransitioningViews.contains(children[index]))) {
children[index].mParent = null;
}

// more code after
}

你有没有提到当我们设置了过渡时, child 的 parent 没有被清空?这很重要!

另外请记忆一下上面的 shouldLayout 做了什么——它只检查三种情况:

  1. View 不为空
  2. View 的父级是工具栏
  3. View 没有消失

这就是问题的根源 - 导航按钮已从工具栏中删除,但它并不知道这一点。

解决方案

为了解决这个问题,我们需要强制工具栏认为不应布局 View 。理想情况下,重写 shouldLayout 方法会很好,但我们没有这样的奢侈...因此,我们实现此目的的唯一方法是更改​​导航按钮的可见性。

class FixedToolbar(context: Context, attrs: AttributeSet?) : MaterialToolbar(context, attrs) {
companion object {
private val navButtonViewField = Toolbar::class.java.getDeclaredField("mNavButtonView")
.also { it.isAccessible = true }
}

override fun setNavigationIcon(icon: Drawable?) {
super.setNavigationIcon(icon)

(navButtonViewField.get(this) as? View)?.isGone = (icon == null)
}
}

现在工具栏将知道导航按钮不得布局,所有动画将按预期进行。

关于android - 工具栏 animateLayoutChanges 奇怪的行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47231180/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com