问题
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的titleMarginStart
和titleMarginEnd
加上
又是一顿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了