Android中使CollapsingToolbarLayout的标题居中设置

Android中使CollapsingToolbarLayout的标题居中设置

Android小彩虹2021-08-15 17:51:17210A+A-

问题描述

我们直接来看以下代码:

<com.google.android.material.appbar.CollapsingToolbarLayout app:collapsedTitleGravity="center_horizontal"/>

在上边的代码中,我将collapsedTitleGravity的值设置为center_horizontal,意思是想让标题文字在折叠后能够居中显示,但是呢,差强人意,来看看这狗屎效果(见下边会动的图),没错,标题往右边偏移的很厉害:

解决办法

  1. 由于我引入的是Android X版本,因此呢,以下代码中,对于反射用到的变量可能与大家真实SDK环境不相同,这个请自行到你们使用中的那个support包中查看源码,找到正确的变量名引用。
  2. 看解决问题的代码:
collapsingToolbarLayout.addOnLayoutChangeListener(new View.OnLayoutChangeListener()
        {
            @Override
            public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
                if (oldBottom == bottom)
                {
                    collapsingToolbarLayout.removeOnLayoutChangeListener(this);
                    try
                    {
                        // 请注意参数字符串‘collapsingTextHelper’,这里对应都是Android X版本中CollapsingToolbarLayout类中声明的CollapsingTextHelper类的变量名
                        // 由于collapsingTextHelper是不对外提供获取的,因此,这里需要用到反射来获取这个对象
                        Field field = collapsingToolbarLayout.getClass().getDeclaredField("collapsingTextHelper");
                        field.setAccessible(true);
                        CollapsingTextHelper collapsingTextHelper = (CollapsingTextHelper) field.get(collapsingToolbarLayout);
                        field.setAccessible(false);
                        // 请注意‘collapsedBounds’是CollapsingTextHelper类中声明的Rect的变量名
                        // 这里是要获取原collapsedBounds的边界数值
                        Field collapsedBoundsField = field.getType().getDeclaredField("collapsedBounds");
                        collapsedBoundsField.setAccessible(true);
                        // 获取到原collapsedBounds的边界数值
                        Rect oldRect = (Rect) collapsedBoundsField.get(collapsingTextHelper);
                        collapsedBoundsField.setAccessible(false);
                        // 设置新的边界数值
                        collapsingTextHelper.setCollapsedBounds(0, oldRect.top, right, oldRect.bottom);
                        collapsingTextHelper.recalculate();
                    } catch (NoSuchFieldException | IllegalAccessException e)
                    {
                        e.printStackTrace();
                    }
                }
            }
        });

来,再看看新的效果,如愿以偿:

问题分析

有心的同学肯定会问了,为什么呢? 我们来一步步分析下

  1. 首先查看并分析下CollapsingToolbarLayout的部分源码:
if (this.collapsingTitleEnabled && this.dummyView != null) {
            this.drawCollapsingTitle = ViewCompat.isAttachedToWindow(this.dummyView) && this.dummyView.getVisibility() == 0;
            if (this.drawCollapsingTitle) {
                boolean isRtl = ViewCompat.getLayoutDirection(this) == 1;
                z = this.getMaxOffsetForPinChild((View)(this.toolbarDirectChild != null ? this.toolbarDirectChild : this.toolbar));
                DescendantOffsetUtils.getDescendantRect(this, this.dummyView, this.tmpRect);
                this.collapsingTextHelper.setCollapsedBounds(this.tmpRect.left + (isRtl ? this.toolbar.getTitleMarginEnd() : this.toolbar.getTitleMarginStart()), this.tmpRect.top + z + this.toolbar.getTitleMarginTop(), this.tmpRect.right + (isRtl ? this.toolbar.getTitleMarginStart() : this.toolbar.getTitleMarginEnd()), this.tmpRect.bottom + z - this.toolbar.getTitleMarginBottom());
                this.collapsingTextHelper.setExpandedBounds(isRtl ? this.expandedMarginEnd : this.expandedMarginStart, this.tmpRect.top + this.expandedMarginTop, right - left - (isRtl ? this.expandedMarginStart : this.expandedMarginEnd), bottom - top - this.expandedMarginBottom);
                this.collapsingTextHelper.recalculate();
            }
        }

重点看这一行:

this.collapsingTextHelper.setCollapsedBounds(this.tmpRect.left + (isRtl ? this.toolbar.getTitleMarginEnd() : this.toolbar.getTitleMarginStart()), this.tmpRect.top + z + this.toolbar.getTitleMarginTop(), this.tmpRect.right + (isRtl ? this.toolbar.getTitleMarginStart() : this.toolbar.getTitleMarginEnd()), this.tmpRect.bottom + z - this.toolbar.getTitleMarginBottom());

从字面意思来看,这是设置一个折叠后的边界范围,那么,是什么边界范围呢? 如果全面查看了CollapsingToolbarLayout的源码,我们会发现,CollapsingToolbarLayout的标题实际上是用画布来绘制出来的,因此我认为,这个边界就是这块画布的尺寸。那么到现在为止呢,我们可以认定,标题一定是是通过这块画布画出来的,而这块画布是有边界的,它的边界就是通过上边这行代码进行计算得来的。 那...我是不是可以重新设置一下画布的尺寸,就可以随意更改标题被绘制的位置了?答案已经很清楚,那么接下来,我要想办法去修改这块画布的尺寸。

  1. 分析这块画布的计算过程,以及如何才能修改它。

未完待续 ...

点击这里复制本文地址 以上内容由权冠洲的博客整理呈现,请务必在转载分享时注明本文地址!如对内容有疑问,请联系我们,谢谢!

支持Ctrl+Enter提交

联系我们| 本站介绍| 留言建议 | 交换友链 | 域名展示
本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除

权冠洲的博客 © All Rights Reserved.  Copyright quanguanzhou.top All Rights Reserved
苏公网安备 32030302000848号   苏ICP备20033101号-1
本网站由 提供CDN/云存储服务

联系我们