@@ -174,7 +174,10 @@ public class CollapsingToolbarLayout extends FrameLayout {
174174
175175 @ Nullable WindowInsetsCompat lastInsets ;
176176 private int topInsetApplied = 0 ;
177- private boolean forceApplySystemWindowInsetTop = false ;
177+ private boolean forceApplySystemWindowInsetTop ;
178+
179+ private int extraMultilineHeight = 0 ;
180+ private boolean extraMultilineHeightEnabled ;
178181
179182 public CollapsingToolbarLayout (@ NonNull Context context ) {
180183 this (context , null );
@@ -278,6 +281,9 @@ public CollapsingToolbarLayout(@NonNull Context context, @Nullable AttributeSet
278281 forceApplySystemWindowInsetTop =
279282 a .getBoolean (R .styleable .CollapsingToolbarLayout_forceApplySystemWindowInsetTop , false );
280283
284+ extraMultilineHeightEnabled =
285+ a .getBoolean (R .styleable .CollapsingToolbarLayout_extraMultilineHeightEnabled , false );
286+
281287 a .recycle ();
282288
283289 setWillNotDraw (false );
@@ -525,11 +531,27 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
525531 // If we have a top inset and we're set to wrap_content height or force apply,
526532 // we need to make sure we add the top inset to our height, therefore we re-measure
527533 topInsetApplied = topInset ;
528- heightMeasureSpec =
529- MeasureSpec .makeMeasureSpec (getMeasuredHeight () + topInset , MeasureSpec .EXACTLY );
534+ int newHeight = getMeasuredHeight () + topInset ;
535+ heightMeasureSpec = MeasureSpec .makeMeasureSpec (newHeight , MeasureSpec .EXACTLY );
530536 super .onMeasure (widthMeasureSpec , heightMeasureSpec );
531537 }
532538
539+ if (extraMultilineHeightEnabled && collapsingTextHelper .getMaxLines () > 1 ) {
540+ // Need to update title and bounds in order to calculate line count and text height.
541+ updateTitleFromToolbarIfNeeded ();
542+ updateTextBounds (0 , 0 , getMeasuredWidth (), getMeasuredHeight (), /* forceRecalculate= */ true );
543+
544+ int lineCount = collapsingTextHelper .getLineCount ();
545+ if (lineCount > 1 ) {
546+ // Add extra height based on the amount of height beyond the first line of title text.
547+ int expandedTextHeight = Math .round (collapsingTextHelper .getExpandedTextFullHeight ());
548+ extraMultilineHeight = expandedTextHeight * (lineCount - 1 );
549+ int newHeight = getMeasuredHeight () + extraMultilineHeight ;
550+ heightMeasureSpec = MeasureSpec .makeMeasureSpec (newHeight , MeasureSpec .EXACTLY );
551+ super .onMeasure (widthMeasureSpec , heightMeasureSpec );
552+ }
553+ }
554+
533555 // Set our minimum height to enable proper AppBarLayout collapsing
534556 if (toolbar != null ) {
535557 if (toolbarDirectChild == null || toolbarDirectChild == this ) {
@@ -564,14 +586,28 @@ protected void onLayout(boolean changed, int left, int top, int right, int botto
564586 getViewOffsetHelper (getChildAt (i )).onViewLayout ();
565587 }
566588
589+ updateTextBounds (left , top , right , bottom , /* forceRecalculate= */ false );
590+
591+ updateTitleFromToolbarIfNeeded ();
592+
593+ updateScrimVisibility ();
594+
595+ // Apply any view offsets, this should be done at the very end of layout
596+ for (int i = 0 , z = getChildCount (); i < z ; i ++) {
597+ getViewOffsetHelper (getChildAt (i )).applyOffsets ();
598+ }
599+ }
600+
601+ private void updateTextBounds (
602+ int left , int top , int right , int bottom , boolean forceRecalculate ) {
567603 // Update the collapsed bounds by getting its transformed bounds
568604 if (collapsingTitleEnabled && dummyView != null ) {
569605 // We only draw the title if the dummy view is being displayed (Toolbar removes
570606 // views if there is no space)
571607 drawCollapsingTitle =
572608 ViewCompat .isAttachedToWindow (dummyView ) && dummyView .getVisibility () == VISIBLE ;
573609
574- if (drawCollapsingTitle ) {
610+ if (drawCollapsingTitle || forceRecalculate ) {
575611 final boolean isRtl =
576612 ViewCompat .getLayoutDirection (this ) == ViewCompat .LAYOUT_DIRECTION_RTL ;
577613
@@ -586,23 +622,18 @@ protected void onLayout(boolean changed, int left, int top, int right, int botto
586622 bottom - top - expandedMarginBottom );
587623
588624 // Now recalculate using the new bounds
589- collapsingTextHelper .recalculate ();
625+ collapsingTextHelper .recalculate (forceRecalculate );
590626 }
591627 }
628+ }
592629
630+ private void updateTitleFromToolbarIfNeeded () {
593631 if (toolbar != null ) {
594632 if (collapsingTitleEnabled && TextUtils .isEmpty (collapsingTextHelper .getText ())) {
595633 // If we do not currently have a title, try and grab it from the Toolbar
596634 setTitle (getToolbarTitle (toolbar ));
597635 }
598636 }
599-
600- updateScrimVisibility ();
601-
602- // Apply any view offsets, this should be done at the very end of layout
603- for (int i = 0 , z = getChildCount (); i < z ; i ++) {
604- getViewOffsetHelper (getChildAt (i )).applyOffsets ();
605- }
606637 }
607638
608639 private void updateCollapsedBounds (boolean isRtl ) {
@@ -1334,6 +1365,24 @@ public boolean isForceApplySystemWindowInsetTop() {
13341365 return forceApplySystemWindowInsetTop ;
13351366 }
13361367
1368+ /**
1369+ * Sets whether extra height should be added when the title text spans across multiple lines.
1370+ * Experimental Feature.
1371+ */
1372+ @ RestrictTo (LIBRARY_GROUP )
1373+ public void setExtraMultilineHeightEnabled (boolean extraMultilineHeightEnabled ) {
1374+ this .extraMultilineHeightEnabled = extraMultilineHeightEnabled ;
1375+ }
1376+
1377+ /**
1378+ * Gets whether extra height should be added when the title text spans across multiple lines.
1379+ * Experimental Feature.
1380+ */
1381+ @ RestrictTo (LIBRARY_GROUP )
1382+ public boolean isExtraMultilineHeightEnabled () {
1383+ return extraMultilineHeightEnabled ;
1384+ }
1385+
13371386 /**
13381387 * Set the amount of visible height in pixels used to define when to trigger a scrim visibility
13391388 * change.
@@ -1362,7 +1411,7 @@ public void setScrimVisibleHeightTrigger(@IntRange(from = 0) final int height) {
13621411 public int getScrimVisibleHeightTrigger () {
13631412 if (scrimVisibleHeightTrigger >= 0 ) {
13641413 // If we have one explicitly set, return it
1365- return scrimVisibleHeightTrigger + topInsetApplied ;
1414+ return scrimVisibleHeightTrigger + topInsetApplied + extraMultilineHeight ;
13661415 }
13671416
13681417 // Otherwise we'll use the default computed value
0 commit comments