CollapsingToolbarLayout+Toolbar的伸缩标题不居中问题解决

问题

CollapsingToolbarLayout 伸缩标题收起时标题文字不居中显示,就算设置了contentInsetLeft=0后仍然不居中,测量大概向右偏移了20px,如图所示

在这里插入图片描述

![在这里插入图片描述](https://img-blog.csdnimg.cn/20201125165704378.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzIzMjMwMzAz,size_16,color_FFFFFF,t_70#pic_center

布局如下:

 <android.support.design.widget.CoordinatorLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <android.support.design.widget.AppBarLayout
            android:layout_width="match_parent"
            android:layout_height="120dp">

            <android.support.design.widget.CollapsingToolbarLayout
                android:id="@+id/collapsing_layout"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                app:expandedTitleGravity="left|bottom"
                app:collapsedTitleGravity="center_horizontal"
                app:layout_scrollFlags="scroll|exitUntilCollapsed|enterAlwaysCollapsed|snap"
                android:minHeight="44dp"
                app:title="测试标题">
                
                <android.support.v7.widget.Toolbar
                    android:id="@+id/toolbar"
                    android:layout_width="match_parent"
                    android:layout_height="48dp"
                    app:contentInsetLeft="0dp"
                    app:contentInsetStart="0dp"
                    app:layout_collapseMode="pin"/>

            </android.support.design.widget.CollapsingToolbarLayout>
        </android.support.design.widget.AppBarLayout>
        .....
    </android.support.design.widget.CoordinatorLayout>

解决方案:

设置ToolBar的属性

app:titleMargin=“0dp”

app:titleMarginStart=“0dp”
app:titleMarginEnd=“0dp”

原因

CollapsingToolbarLayout的标题伸缩效果主要是靠其在draw方法中通过类:CollapsingTextHelper 自定义绘制效果形成的

    @Override
    public void draw(Canvas canvas) {
        super.draw(canvas);
        ...
        // Let the collapsing text helper draw its text
        if (mCollapsingTitleEnabled && mDrawCollapsingTitle) {
            mCollapsingTextHelper.draw(canvas);
        }
        ....
    }

CollapsingTextHelper:draw()

    public void draw(Canvas canvas) {
        final int saveCount = canvas.save();

        if (mTextToDraw != null && mDrawTitle) {
            //标题当前缩放系数下,文本绘制坐标
            float x = mCurrentDrawX;
            float y = mCurrentDrawY;
                ....
                //正式绘制
                canvas.drawText(mTextToDraw, 0, mTextToDraw.length(), x, y, mTextPaint);
        }

    }

该问题最主要的是X轴的位置偏移,所以我们主要关注mCurrentDrawX这个值是如何计算出来的。全局搜索代码,只有一处对该属性进行赋值

    private void calculateOffsets(final float fraction) {
        //通过fraction系数,计算文字的绘制位置
        mCurrentDrawX = lerp(mExpandedDrawX, mCollapsedDrawX, fraction,
                mPositionInterpolator);
        
    }

其中,我们只需要关注两个值:

mExpandedDrawX - 标题完全展开时,文字x轴的绘制坐标

mCollapsedDrawX - 标题完全收起来时,文字x轴的绘制坐标

这两个值都是在方法calcualteBaseOffset方法中计算出来的

    private void calculateBaseOffsets() {
        calculateUsingTextSize(mCollapsedTextSize);
        float width = mTextToDraw != null ?
                mTextPaint.measureText(mTextToDraw, 0, mTextToDraw.length()) : 0;
        final int collapsedAbsGravity = GravityCompat.getAbsoluteGravity(mCollapsedTextGravity,
                mIsRtl ? ViewCompat.LAYOUT_DIRECTION_RTL : ViewCompat.LAYOUT_DIRECTION_LTR);
        
        switch (collapsedAbsGravity & GravityCompat.RELATIVE_HORIZONTAL_GRAVITY_MASK) {
            case Gravity.CENTER_HORIZONTAL:
                //当前布局方式,收起来时,让标题居中显示,走这里
                mCollapsedDrawX = mCollapsedBounds.centerX() - (width / 2);
                break;
        }


    }

通过Debug,我观察到 mCollapsedBounds 的值有异常,显示为:Rect(10, 199 - 1090, 305),我的手机屏幕宽度才是1080,它向右完全偏移了10像素

全局搜索,找到修改 mCollapsedBounds 值的位置为:setCollapsedBounds() 方法,该方法是在CollapsingToolbarLayout的onLayout方法中被调用的

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
                final boolean isRtl = ViewCompat.getLayoutDirection(this)
                        == ViewCompat.LAYOUT_DIRECTION_RTL;
                //这里设置了完全收缩时的标题内容显示范围
                //左右两边的值都加上了mToolbar的titleMarginStart和titleMarginEnd
                mCollapsingTextHelper.setCollapsedBounds(
                        mTmpRect.left + (isRtl
                                ? mToolbar.getTitleMarginEnd()
                                : mToolbar.getTitleMarginStart()),
                        mTmpRect.top + maxOffset + mToolbar.getTitleMarginTop(),
                        mTmpRect.right + (isRtl
                                ? mToolbar.getTitleMarginStart()
                                : mToolbar.getTitleMarginEnd()),
                        mTmpRect.bottom + maxOffset - mToolbar.getTitleMarginBottom());
    }

跟踪到这里,大概就能猜到,偏移的值应该都是通过Toobar的titleMarginStarttitleMarginEnd加上

又是一顿Debug操作,果然两个titleMargin的值都是10,这样我们在ToolBar中找到设置该值的方法或属性,都修改成0即可解决问题。

但是,我在布局中,完全没有设置这两个值,且看了他的源码,默认的值也都是0,那么这些值是从哪里来呢?

在Toolbar的构造函数中,有通过属性获取该值的代码:

int titleMargin = a.getDimensionPixelOffset(R.styleable.Toolbar_titleMargin, 0);

但是我在布局中又没有设置这个属性,猜测是在使用的主题中对这个属性设置了默认值,通过主题继承关系,找到对应的代码:

<style name="Base.V7.Widget.AppCompat.Toolbar" parent="android:Widget">
        <item name="titleMargin">4dp</item>
    </style>

titleMargin = 4dp,在我的手机屏幕下,刚好是10px, 此消彼长之下就是20了

结束
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值