如何动态调整折叠工具栏的内容

时间:2018-02-19 23:18:05

标签: android material-design android-collapsingtoolbarlayout

我想知道是否有任何方式可以动态调整CollapsingToolbarLayout的内容?我在折叠工具栏中有一个视图,当工具栏折叠时会被部分遮盖:

enter image description here

如您所见,顶部的徽标被掩盖(“读者”中的“d”)。这是因为在我的布局XML中,我将底部边距设置为20dp,无论工具栏是展开还是折叠,此边距都保持不变。

我的想法是根据折叠工具栏是否展开(使用20dp底部边距)或折叠(将底部边距设置为0dp)动态调整底部边距。 AppBarLayout有一个OnOffsetChangeListener,所以我认为这是实现这一目标的好方法。

据我了解,为了调整徽标的边距,我需要以编程方式调整包含徽标的LayoutParams的{​​{1}}。我试图在这里这样做:

ImageView

问题是走这条路,我的边缘因某种原因没有被应用。 final ImageView logo = (ImageView) mRootView.findViewById(R.id.fragment_article_detail_logo); final CollapsingToolbarLayout.LayoutParams layoutParams = (CollapsingToolbarLayout.LayoutParams) logo.getLayoutParams(); AppBarLayout appBarLayout = (AppBarLayout) mRootView.findViewById(R.id.fragment_article_detail_app_bar_layout); // This is the total range of the AppBarLayout int scrollRange = appBarLayout.getTotalScrollRange(); // If scrollRange is negative, then that means that the app bar is completely collapsed final int collapsedOffset = scrollRange * -1; appBarLayout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() { @Override public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) { // If the app bar is completely collapsed, we want to remove the bottom margin if (verticalOffset == collapsedOffset) { layoutParams.setMargins(layoutParams.leftMargin, layoutParams.topMargin, layoutParams.rightMargin, 0); logo.setLayoutParams(layoutParams); logo.requestLayout(); } // If the app bar is fully expanded, we'll apply the bottom margin else if (verticalOffset == 0){ layoutParams.setMargins(layoutParams.leftMargin, layoutParams.topMargin, layoutParams.rightMargin, getBottomMargin()); logo.setLayoutParams(layoutParams); logo.requestLayout(); } } }); 方法用于返回底部边距的数量:

getBottomMargin()

即使我在XML中应用我的边距,以及在Java中动态调整它,我的徽标也没有正确应用左边距或下边距:

enter image description here

仅供参考,问题前面的屏幕截图是在动态尝试调整徽标的边距之前。

所以我的主要问题是:我在这里做错了什么?我可以通过我采取的方法实现我希望的目标吗?我知道最简单的方法是将徽标的高度和宽度调整为小于private int getBottomMargin() { Resources resources = getResources(); return (int) TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, resources.getDimension(R.dimen.app_bar_logo_bottom_margin), resources.getDisplayMetrics()); } 的值。但是,我觉得有更好的方法可以做到这一点(使徽标更小似乎太容易了)。

如果它有帮助,这是我的布局XML的一部分,其中包含wrap_contentAppBarLayout

CollapsingToolbarLayout

1 个答案:

答案 0 :(得分:0)

我实际上能够让自己开始工作。我对OnOffsetChangedListener以及getBottomMargin()

进行了一些更改
mLogo = (ImageView) mRootView.findViewById(R.id.fragment_article_detail_logo);
final CollapsingToolbarLayout.LayoutParams layoutParams = (CollapsingToolbarLayout.LayoutParams) mLogo.getLayoutParams();

AppBarLayout appBarLayout = (AppBarLayout) mRootView.findViewById(R.id.fragment_article_detail_app_bar_layout);
appBarLayout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() {
    @Override
    public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {

        // If toolbar is collapsed, we'll remove the bottom margin
        if (Math.abs(verticalOffset) == appBarLayout.getTotalScrollRange()){
            layoutParams.setMargins(layoutParams.leftMargin, layoutParams.topMargin, layoutParams.rightMargin, 0);
            mLogo.setLayoutParams(layoutParams);
        }

        /*
        Otherwise, we'll add the bottom margin back in. I could have kept just as a plain
        else statement. However, scrolling started to feel jittery since this was being
        called each time app bar is being expanded. The additional if() has been added to
        ensure that the bottom margin is only added once.
         */
        else if (layoutParams.bottomMargin != getBottomMargin()) {
            layoutParams.setMargins(layoutParams.leftMargin, layoutParams.topMargin, layoutParams.rightMargin, getBottomMargin());
            mLogo.setLayoutParams(layoutParams);
        }
    }
});

我之前尝试的问题是:

int scrollRange = appBarLayout.getTotalScrollRange();
final int collapsedOffset = scrollRange * -1;

这些变量是在onOffsetChanged()之外设置的,或者更确切地说是在OnOffsetChangedListener添加到AppBarLayout之前。我不太了解Android框架如何布局UI。但是,我知道的一件事是,它会进行多次尝试来布局UI,直到所有内容都正确定位。当我调试我之前的尝试时,scrollRange始终为0(这使collapsedOffset本身也为0)。我的猜测是,当我设置这些变量时,应用栏还没有完全布局,所以这可能是导致它们始终为0的原因。虽然我并不完全确定。

我做的另一项更改是getBottomMargin()

private int getBottomMargin() {

    return getResources().getDimensionPixelSize(R.dimen.app_bar_logo_bottom_margin);
}

我不确定getBottomMargin()的其他版本为什么不起作用。但无论出于何种原因,它使得底部边缘比实际应该大得多。

这些是我之前对此实施的最重要的更改。如果有人想知道如何提高效率,或者调整到底部边距是一个更平滑的过渡,请提供您的意见。希望这可以帮助其他有需要的人:)