[go: nahoru, domu]

1a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes/*
2a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * Copyright (C) 2015 The Android Open Source Project
3a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes *
4a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * Licensed under the Apache License, Version 2.0 (the "License");
5a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * you may not use this file except in compliance with the License.
6a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * You may obtain a copy of the License at
7a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes *
8a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes *      http://www.apache.org/licenses/LICENSE-2.0
9a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes *
10a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * Unless required by applicable law or agreed to in writing, software
11a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * distributed under the License is distributed on an "AS IS" BASIS,
12a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * See the License for the specific language governing permissions and
14a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * limitations under the License.
15a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes */
16a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes
17a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banespackage android.support.design.widget;
18a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes
19a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banesimport android.content.Context;
20a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banesimport android.content.res.TypedArray;
21a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banesimport android.graphics.Canvas;
22a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banesimport android.graphics.Rect;
23d29e79fa09f428c510d1d9ca758dbda35a323f71Chris Banesimport android.graphics.Typeface;
246ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banesimport android.graphics.drawable.ColorDrawable;
256ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banesimport android.graphics.drawable.Drawable;
261701feace5652372dd2fe1913f74169a12e2c940Chris Banesimport android.support.annotation.ColorInt;
276ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banesimport android.support.annotation.DrawableRes;
2850dfc33a565c4aefe6d5e844c93aa24a74cb80b3Chris Banesimport android.support.annotation.IntDef;
296df5bb9903307734ed05a5135c7812fb9b6d43c8Chris Banesimport android.support.annotation.IntRange;
30d29e79fa09f428c510d1d9ca758dbda35a323f71Chris Banesimport android.support.annotation.NonNull;
316ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banesimport android.support.annotation.Nullable;
321701feace5652372dd2fe1913f74169a12e2c940Chris Banesimport android.support.annotation.StyleRes;
33a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banesimport android.support.design.R;
346ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banesimport android.support.v4.content.ContextCompat;
35bcb330de0c625b371010bada2a51363fc37b52ccChris Banesimport android.support.v4.graphics.drawable.DrawableCompat;
365c7d7bbceeaebc46dc2e4b2135cc330414f716d4Chris Banesimport android.support.v4.view.GravityCompat;
37a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banesimport android.support.v4.view.ViewCompat;
386ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banesimport android.support.v4.view.WindowInsetsCompat;
39a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banesimport android.support.v7.widget.Toolbar;
4031075a61da61f1f0184ee909a70b1efcd7cee807Chris Banesimport android.text.TextUtils;
41a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banesimport android.util.AttributeSet;
42a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banesimport android.view.Gravity;
43a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banesimport android.view.View;
44a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banesimport android.view.ViewGroup;
45631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banesimport android.view.ViewParent;
46a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banesimport android.widget.FrameLayout;
47a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes
4850dfc33a565c4aefe6d5e844c93aa24a74cb80b3Chris Banesimport java.lang.annotation.Retention;
4950dfc33a565c4aefe6d5e844c93aa24a74cb80b3Chris Banesimport java.lang.annotation.RetentionPolicy;
5050dfc33a565c4aefe6d5e844c93aa24a74cb80b3Chris Banes
51a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes/**
52a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * CollapsingToolbarLayout is a wrapper for {@link Toolbar} which implements a collapsing app bar.
53a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * It is designed to be used as a direct child of a {@link AppBarLayout}.
54a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * CollapsingToolbarLayout contains the following features:
55a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes *
564837e2d38e11a8e85a2718e4620f73d32dcde184Chris Banes * <h4>Collapsing title</h4>
57a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * A title which is larger when the layout is fully visible but collapses and becomes smaller as
58a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * the layout is scrolled off screen. You can set the title to display via
59a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * {@link #setTitle(CharSequence)}. The title appearance can be tweaked via the
60a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * {@code collapsedTextAppearance} and {@code expandedTextAppearance} attributes.
61a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes *
624837e2d38e11a8e85a2718e4620f73d32dcde184Chris Banes * <h4>Content scrim</h4>
63a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * A full-bleed scrim which is show or hidden when the scroll position has hit a certain threshold.
646ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes * You can change this via {@link #setContentScrim(Drawable)}.
65a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes *
664837e2d38e11a8e85a2718e4620f73d32dcde184Chris Banes * <h4>Status bar scrim</h4>
6779208cc336926148978ccb49861f986fada745e0Chris Banes * A scrim which is show or hidden behind the status bar when the scroll position has hit a certain
6879208cc336926148978ccb49861f986fada745e0Chris Banes * threshold. You can change this via {@link #setStatusBarScrim(Drawable)}. This only works
6917ed3263761329f6aa6796941358c41001fff325Chris Banes * on {@link android.os.Build.VERSION_CODES#LOLLIPOP LOLLIPOP} devices when we set to fit system
7017ed3263761329f6aa6796941358c41001fff325Chris Banes * windows.
7179208cc336926148978ccb49861f986fada745e0Chris Banes *
724837e2d38e11a8e85a2718e4620f73d32dcde184Chris Banes * <h4>Parallax scrolling children</h4>
73a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * Child views can opt to be scrolled within this layout in a parallax fashion.
74a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * See {@link LayoutParams#COLLAPSE_MODE_PARALLAX} and
75a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * {@link LayoutParams#setParallaxMultiplier(float)}.
76a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes *
774837e2d38e11a8e85a2718e4620f73d32dcde184Chris Banes * <h4>Pinned position children</h4>
78a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * Child views can opt to be pinned in space globally. This is useful when implementing a
79a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * collapsing as it allows the {@link Toolbar} to be fixed in place even though this layout is
80a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * moving. See {@link LayoutParams#COLLAPSE_MODE_PIN}.
81a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes *
824837e2d38e11a8e85a2718e4620f73d32dcde184Chris Banes * <p><strong>Do not manually add views to the Toolbar at run time</strong>.
834837e2d38e11a8e85a2718e4620f73d32dcde184Chris Banes * We will add a 'dummy view' to the Toolbar which allows us to work out the available space
844837e2d38e11a8e85a2718e4620f73d32dcde184Chris Banes * for the title. This can interfere with any views which you add.</p>
854837e2d38e11a8e85a2718e4620f73d32dcde184Chris Banes *
86a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * @attr ref android.support.design.R.styleable#CollapsingToolbarLayout_collapsedTitleTextAppearance
87a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * @attr ref android.support.design.R.styleable#CollapsingToolbarLayout_expandedTitleTextAppearance
886ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes * @attr ref android.support.design.R.styleable#CollapsingToolbarLayout_contentScrim
89a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * @attr ref android.support.design.R.styleable#CollapsingToolbarLayout_expandedTitleMargin
90a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * @attr ref android.support.design.R.styleable#CollapsingToolbarLayout_expandedTitleMarginStart
91a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * @attr ref android.support.design.R.styleable#CollapsingToolbarLayout_expandedTitleMarginEnd
92a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * @attr ref android.support.design.R.styleable#CollapsingToolbarLayout_expandedTitleMarginBottom
936ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes * @attr ref android.support.design.R.styleable#CollapsingToolbarLayout_statusBarScrim
9479208cc336926148978ccb49861f986fada745e0Chris Banes * @attr ref android.support.design.R.styleable#CollapsingToolbarLayout_toolbarId
95a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes */
96631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banespublic class CollapsingToolbarLayout extends FrameLayout {
97a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes
986df5bb9903307734ed05a5135c7812fb9b6d43c8Chris Banes    private static final int DEFAULT_SCRIM_ANIMATION_DURATION = 600;
99a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes
10079208cc336926148978ccb49861f986fada745e0Chris Banes    private boolean mRefreshToolbar = true;
10179208cc336926148978ccb49861f986fada745e0Chris Banes    private int mToolbarId;
102a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes    private Toolbar mToolbar;
1034837e2d38e11a8e85a2718e4620f73d32dcde184Chris Banes    private View mToolbarDirectChild;
104a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes    private View mDummyView;
105a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes
10634550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes    private int mExpandedMarginStart;
10779208cc336926148978ccb49861f986fada745e0Chris Banes    private int mExpandedMarginTop;
10834550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes    private int mExpandedMarginEnd;
109a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes    private int mExpandedMarginBottom;
110a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes
11179208cc336926148978ccb49861f986fada745e0Chris Banes    private final Rect mTmpRect = new Rect();
112a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes    private final CollapsingTextHelper mCollapsingTextHelper;
1131701feace5652372dd2fe1913f74169a12e2c940Chris Banes    private boolean mCollapsingTitleEnabled;
114c06ea511ab9d97ed62ec10f10262f1c34b1905f0Chris Banes    private boolean mDrawCollapsingTitle;
115a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes
1166ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes    private Drawable mContentScrim;
1176ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes    private Drawable mStatusBarScrim;
1186ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes    private int mScrimAlpha;
1196ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes    private boolean mScrimsAreShown;
120f44e88b81821e61a65886cc7027617ca8995070bChris Banes    private ValueAnimatorCompat mScrimAnimator;
121e852801f9258e00f89da48918b58a6e933643ab9Aurimas Liutikas    private long mScrimAnimationDuration;
1226df5bb9903307734ed05a5135c7812fb9b6d43c8Chris Banes    private int mScrimVisibleHeightTrigger = -1;
123a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes
124631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes    private AppBarLayout.OnOffsetChangedListener mOnOffsetChangedListener;
125631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes
1266ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes    private int mCurrentOffset;
1276ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes
1286ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes    private WindowInsetsCompat mLastInsets;
1296ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes
130a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes    public CollapsingToolbarLayout(Context context) {
131a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        this(context, null);
132a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes    }
133a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes
134a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes    public CollapsingToolbarLayout(Context context, AttributeSet attrs) {
135b3ba94bf8b5cdae24e5a09a83813d72f2e2d8c1aChris Banes        this(context, attrs, 0);
136a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes    }
137a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes
138a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes    public CollapsingToolbarLayout(Context context, AttributeSet attrs, int defStyleAttr) {
139a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        super(context, attrs, defStyleAttr);
140a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes
141809bb62055ad42b88f3a69308be222801b89fbd9Chris Banes        ThemeUtils.checkAppCompatTheme(context);
142809bb62055ad42b88f3a69308be222801b89fbd9Chris Banes
143a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        mCollapsingTextHelper = new CollapsingTextHelper(this);
144a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        mCollapsingTextHelper.setTextSizeInterpolator(AnimationUtils.DECELERATE_INTERPOLATOR);
145a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes
146a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        TypedArray a = context.obtainStyledAttributes(attrs,
147a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes                R.styleable.CollapsingToolbarLayout, defStyleAttr,
148a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes                R.style.Widget_Design_CollapsingToolbar);
149a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes
1505c7d7bbceeaebc46dc2e4b2135cc330414f716d4Chris Banes        mCollapsingTextHelper.setExpandedTextGravity(
1515c7d7bbceeaebc46dc2e4b2135cc330414f716d4Chris Banes                a.getInt(R.styleable.CollapsingToolbarLayout_expandedTitleGravity,
1525c7d7bbceeaebc46dc2e4b2135cc330414f716d4Chris Banes                        GravityCompat.START | Gravity.BOTTOM));
1535c7d7bbceeaebc46dc2e4b2135cc330414f716d4Chris Banes        mCollapsingTextHelper.setCollapsedTextGravity(
1545c7d7bbceeaebc46dc2e4b2135cc330414f716d4Chris Banes                a.getInt(R.styleable.CollapsingToolbarLayout_collapsedTitleGravity,
1555c7d7bbceeaebc46dc2e4b2135cc330414f716d4Chris Banes                        GravityCompat.START | Gravity.CENTER_VERTICAL));
1565c7d7bbceeaebc46dc2e4b2135cc330414f716d4Chris Banes
15734550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes        mExpandedMarginStart = mExpandedMarginTop = mExpandedMarginEnd = mExpandedMarginBottom =
158a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes                a.getDimensionPixelSize(R.styleable.CollapsingToolbarLayout_expandedTitleMargin, 0);
159a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes
160a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        if (a.hasValue(R.styleable.CollapsingToolbarLayout_expandedTitleMarginStart)) {
16134550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes            mExpandedMarginStart = a.getDimensionPixelSize(
162a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes                    R.styleable.CollapsingToolbarLayout_expandedTitleMarginStart, 0);
163a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        }
164a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        if (a.hasValue(R.styleable.CollapsingToolbarLayout_expandedTitleMarginEnd)) {
16534550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes            mExpandedMarginEnd = a.getDimensionPixelSize(
166a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes                    R.styleable.CollapsingToolbarLayout_expandedTitleMarginEnd, 0);
167a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        }
16879208cc336926148978ccb49861f986fada745e0Chris Banes        if (a.hasValue(R.styleable.CollapsingToolbarLayout_expandedTitleMarginTop)) {
16979208cc336926148978ccb49861f986fada745e0Chris Banes            mExpandedMarginTop = a.getDimensionPixelSize(
17079208cc336926148978ccb49861f986fada745e0Chris Banes                    R.styleable.CollapsingToolbarLayout_expandedTitleMarginTop, 0);
17179208cc336926148978ccb49861f986fada745e0Chris Banes        }
172a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        if (a.hasValue(R.styleable.CollapsingToolbarLayout_expandedTitleMarginBottom)) {
173a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes            mExpandedMarginBottom = a.getDimensionPixelSize(
174a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes                    R.styleable.CollapsingToolbarLayout_expandedTitleMarginBottom, 0);
175a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        }
176a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes
1771701feace5652372dd2fe1913f74169a12e2c940Chris Banes        mCollapsingTitleEnabled = a.getBoolean(
1781701feace5652372dd2fe1913f74169a12e2c940Chris Banes                R.styleable.CollapsingToolbarLayout_titleEnabled, true);
1791701feace5652372dd2fe1913f74169a12e2c940Chris Banes        setTitle(a.getText(R.styleable.CollapsingToolbarLayout_title));
1801701feace5652372dd2fe1913f74169a12e2c940Chris Banes
1819934230aa2959ee9f1802aa81fd21e25030b0d10Chris Banes        // First load the default text appearances
1829934230aa2959ee9f1802aa81fd21e25030b0d10Chris Banes        mCollapsingTextHelper.setExpandedTextAppearance(
1839934230aa2959ee9f1802aa81fd21e25030b0d10Chris Banes                R.style.TextAppearance_Design_CollapsingToolbar_Expanded);
1849934230aa2959ee9f1802aa81fd21e25030b0d10Chris Banes        mCollapsingTextHelper.setCollapsedTextAppearance(
1856759b1021d8198ad1d239bb30e5a102b99624bceAdam Lesinski                android.support.v7.appcompat.R.style.TextAppearance_AppCompat_Widget_ActionBar_Title);
1869934230aa2959ee9f1802aa81fd21e25030b0d10Chris Banes
1879934230aa2959ee9f1802aa81fd21e25030b0d10Chris Banes        // Now overlay any custom text appearances
1889934230aa2959ee9f1802aa81fd21e25030b0d10Chris Banes        if (a.hasValue(R.styleable.CollapsingToolbarLayout_expandedTitleTextAppearance)) {
1899934230aa2959ee9f1802aa81fd21e25030b0d10Chris Banes            mCollapsingTextHelper.setExpandedTextAppearance(
1909934230aa2959ee9f1802aa81fd21e25030b0d10Chris Banes                    a.getResourceId(
1919934230aa2959ee9f1802aa81fd21e25030b0d10Chris Banes                            R.styleable.CollapsingToolbarLayout_expandedTitleTextAppearance, 0));
1929934230aa2959ee9f1802aa81fd21e25030b0d10Chris Banes        }
1939934230aa2959ee9f1802aa81fd21e25030b0d10Chris Banes        if (a.hasValue(R.styleable.CollapsingToolbarLayout_collapsedTitleTextAppearance)) {
1949934230aa2959ee9f1802aa81fd21e25030b0d10Chris Banes            mCollapsingTextHelper.setCollapsedTextAppearance(
1959934230aa2959ee9f1802aa81fd21e25030b0d10Chris Banes                    a.getResourceId(
1969934230aa2959ee9f1802aa81fd21e25030b0d10Chris Banes                            R.styleable.CollapsingToolbarLayout_collapsedTitleTextAppearance, 0));
1979934230aa2959ee9f1802aa81fd21e25030b0d10Chris Banes        }
198a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes
1996df5bb9903307734ed05a5135c7812fb9b6d43c8Chris Banes        mScrimVisibleHeightTrigger = a.getInt(
2006df5bb9903307734ed05a5135c7812fb9b6d43c8Chris Banes                R.styleable.CollapsingToolbarLayout_scrimVisibleHeightTrigger, -1);
2016df5bb9903307734ed05a5135c7812fb9b6d43c8Chris Banes
2026df5bb9903307734ed05a5135c7812fb9b6d43c8Chris Banes        mScrimAnimationDuration = a.getInt(
2036df5bb9903307734ed05a5135c7812fb9b6d43c8Chris Banes                R.styleable.CollapsingToolbarLayout_scrimAnimationDuration,
2046df5bb9903307734ed05a5135c7812fb9b6d43c8Chris Banes                DEFAULT_SCRIM_ANIMATION_DURATION);
2056df5bb9903307734ed05a5135c7812fb9b6d43c8Chris Banes
2066ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes        setContentScrim(a.getDrawable(R.styleable.CollapsingToolbarLayout_contentScrim));
2076ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes        setStatusBarScrim(a.getDrawable(R.styleable.CollapsingToolbarLayout_statusBarScrim));
208a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes
20979208cc336926148978ccb49861f986fada745e0Chris Banes        mToolbarId = a.getResourceId(R.styleable.CollapsingToolbarLayout_toolbarId, -1);
21079208cc336926148978ccb49861f986fada745e0Chris Banes
211a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        a.recycle();
212a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes
213a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        setWillNotDraw(false);
2146ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes
2156ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes        ViewCompat.setOnApplyWindowInsetsListener(this,
2166ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes                new android.support.v4.view.OnApplyWindowInsetsListener() {
2176ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes                    @Override
2186ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes                    public WindowInsetsCompat onApplyWindowInsets(View v,
2196ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes                            WindowInsetsCompat insets) {
22017ed3263761329f6aa6796941358c41001fff325Chris Banes                        return setWindowInsets(insets);
2216ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes                    }
2226ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes                });
223a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes    }
224a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes
225a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes    @Override
226631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes    protected void onAttachedToWindow() {
227631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes        super.onAttachedToWindow();
228631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes
229631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes        // Add an OnOffsetChangedListener if possible
230631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes        final ViewParent parent = getParent();
231631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes        if (parent instanceof AppBarLayout) {
232631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes            if (mOnOffsetChangedListener == null) {
233631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes                mOnOffsetChangedListener = new OffsetUpdateListener();
234631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes            }
235631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes            ((AppBarLayout) parent).addOnOffsetChangedListener(mOnOffsetChangedListener);
236631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes        }
23717ed3263761329f6aa6796941358c41001fff325Chris Banes
23817ed3263761329f6aa6796941358c41001fff325Chris Banes        // We're attached, so lets request an inset dispatch
23917ed3263761329f6aa6796941358c41001fff325Chris Banes        ViewCompat.requestApplyInsets(this);
240631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes    }
241631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes
242631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes    @Override
243631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes    protected void onDetachedFromWindow() {
244631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes        // Remove our OnOffsetChangedListener if possible and it exists
245631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes        final ViewParent parent = getParent();
246631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes        if (mOnOffsetChangedListener != null && parent instanceof AppBarLayout) {
247631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes            ((AppBarLayout) parent).removeOnOffsetChangedListener(mOnOffsetChangedListener);
248631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes        }
249631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes
250631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes        super.onDetachedFromWindow();
251631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes    }
252631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes
25317ed3263761329f6aa6796941358c41001fff325Chris Banes    private WindowInsetsCompat setWindowInsets(WindowInsetsCompat insets) {
25417ed3263761329f6aa6796941358c41001fff325Chris Banes        if (mLastInsets != insets) {
25517ed3263761329f6aa6796941358c41001fff325Chris Banes            mLastInsets = insets;
25617ed3263761329f6aa6796941358c41001fff325Chris Banes            requestLayout();
25717ed3263761329f6aa6796941358c41001fff325Chris Banes        }
25817ed3263761329f6aa6796941358c41001fff325Chris Banes        return insets.consumeSystemWindowInsets();
25917ed3263761329f6aa6796941358c41001fff325Chris Banes    }
26017ed3263761329f6aa6796941358c41001fff325Chris Banes
261631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes    @Override
262a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes    public void draw(Canvas canvas) {
263a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        super.draw(canvas);
264a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes
26550dfc33a565c4aefe6d5e844c93aa24a74cb80b3Chris Banes        // If we don't have a toolbar, the scrim will be not be drawn in drawChild() below.
26650dfc33a565c4aefe6d5e844c93aa24a74cb80b3Chris Banes        // Instead, we draw it here, before our collapsing text.
26779208cc336926148978ccb49861f986fada745e0Chris Banes        ensureToolbar();
2686ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes        if (mToolbar == null && mContentScrim != null && mScrimAlpha > 0) {
2696ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes            mContentScrim.mutate().setAlpha(mScrimAlpha);
2706ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes            mContentScrim.draw(canvas);
27150dfc33a565c4aefe6d5e844c93aa24a74cb80b3Chris Banes        }
27250dfc33a565c4aefe6d5e844c93aa24a74cb80b3Chris Banes
2734837e2d38e11a8e85a2718e4620f73d32dcde184Chris Banes        // Let the collapsing text helper draw its text
274c06ea511ab9d97ed62ec10f10262f1c34b1905f0Chris Banes        if (mCollapsingTitleEnabled && mDrawCollapsingTitle) {
2751701feace5652372dd2fe1913f74169a12e2c940Chris Banes            mCollapsingTextHelper.draw(canvas);
2761701feace5652372dd2fe1913f74169a12e2c940Chris Banes        }
2776ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes
2786ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes        // Now draw the status bar scrim
2796ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes        if (mStatusBarScrim != null && mScrimAlpha > 0) {
2806ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes            final int topInset = mLastInsets != null ? mLastInsets.getSystemWindowInsetTop() : 0;
2816ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes            if (topInset > 0) {
2826ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes                mStatusBarScrim.setBounds(0, -mCurrentOffset, getWidth(),
2836ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes                        topInset - mCurrentOffset);
2846ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes                mStatusBarScrim.mutate().setAlpha(mScrimAlpha);
2856ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes                mStatusBarScrim.draw(canvas);
2866ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes            }
2876ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes        }
288a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes    }
289a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes
290a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes    @Override
291a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes    protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
292a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        // This is a little weird. Our scrim needs to be behind the Toolbar (if it is present),
293a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        // but in front of any other children which are behind it. To do this we intercept the
294a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        // drawChild() call, and draw our scrim first when drawing the toolbar
29579208cc336926148978ccb49861f986fada745e0Chris Banes        ensureToolbar();
2966ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes        if (child == mToolbar && mContentScrim != null && mScrimAlpha > 0) {
2976ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes            mContentScrim.mutate().setAlpha(mScrimAlpha);
2986ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes            mContentScrim.draw(canvas);
299a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        }
30050dfc33a565c4aefe6d5e844c93aa24a74cb80b3Chris Banes
301a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        // Carry on drawing the child...
302a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        return super.drawChild(canvas, child, drawingTime);
303a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes    }
304a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes
305a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes    @Override
3066ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
3076ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes        super.onSizeChanged(w, h, oldw, oldh);
3086ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes        if (mContentScrim != null) {
3096ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes            mContentScrim.setBounds(0, 0, w, h);
3106ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes        }
3116ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes    }
3126ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes
31379208cc336926148978ccb49861f986fada745e0Chris Banes    private void ensureToolbar() {
31479208cc336926148978ccb49861f986fada745e0Chris Banes        if (!mRefreshToolbar) {
31579208cc336926148978ccb49861f986fada745e0Chris Banes            return;
31679208cc336926148978ccb49861f986fada745e0Chris Banes        }
31779208cc336926148978ccb49861f986fada745e0Chris Banes
3184837e2d38e11a8e85a2718e4620f73d32dcde184Chris Banes        // First clear out the current Toolbar
3194837e2d38e11a8e85a2718e4620f73d32dcde184Chris Banes        mToolbar = null;
3204837e2d38e11a8e85a2718e4620f73d32dcde184Chris Banes        mToolbarDirectChild = null;
32179208cc336926148978ccb49861f986fada745e0Chris Banes
3224837e2d38e11a8e85a2718e4620f73d32dcde184Chris Banes        if (mToolbarId != -1) {
3234837e2d38e11a8e85a2718e4620f73d32dcde184Chris Banes            // If we have an ID set, try and find it and it's direct parent to us
3244837e2d38e11a8e85a2718e4620f73d32dcde184Chris Banes            mToolbar = (Toolbar) findViewById(mToolbarId);
3254837e2d38e11a8e85a2718e4620f73d32dcde184Chris Banes            if (mToolbar != null) {
3264837e2d38e11a8e85a2718e4620f73d32dcde184Chris Banes                mToolbarDirectChild = findDirectChild(mToolbar);
32779208cc336926148978ccb49861f986fada745e0Chris Banes            }
32879208cc336926148978ccb49861f986fada745e0Chris Banes        }
32979208cc336926148978ccb49861f986fada745e0Chris Banes
3304837e2d38e11a8e85a2718e4620f73d32dcde184Chris Banes        if (mToolbar == null) {
3314837e2d38e11a8e85a2718e4620f73d32dcde184Chris Banes            // If we don't have an ID, or couldn't find a Toolbar with the correct ID, try and find
3324837e2d38e11a8e85a2718e4620f73d32dcde184Chris Banes            // one from our direct children
3334837e2d38e11a8e85a2718e4620f73d32dcde184Chris Banes            Toolbar toolbar = null;
3344837e2d38e11a8e85a2718e4620f73d32dcde184Chris Banes            for (int i = 0, count = getChildCount(); i < count; i++) {
3354837e2d38e11a8e85a2718e4620f73d32dcde184Chris Banes                final View child = getChildAt(i);
3364837e2d38e11a8e85a2718e4620f73d32dcde184Chris Banes                if (child instanceof Toolbar) {
3374837e2d38e11a8e85a2718e4620f73d32dcde184Chris Banes                    toolbar = (Toolbar) child;
3384837e2d38e11a8e85a2718e4620f73d32dcde184Chris Banes                    break;
3394837e2d38e11a8e85a2718e4620f73d32dcde184Chris Banes                }
3404837e2d38e11a8e85a2718e4620f73d32dcde184Chris Banes            }
3414837e2d38e11a8e85a2718e4620f73d32dcde184Chris Banes            mToolbar = toolbar;
34279208cc336926148978ccb49861f986fada745e0Chris Banes        }
34379208cc336926148978ccb49861f986fada745e0Chris Banes
3441701feace5652372dd2fe1913f74169a12e2c940Chris Banes        updateDummyView();
34579208cc336926148978ccb49861f986fada745e0Chris Banes        mRefreshToolbar = false;
34679208cc336926148978ccb49861f986fada745e0Chris Banes    }
34779208cc336926148978ccb49861f986fada745e0Chris Banes
3484837e2d38e11a8e85a2718e4620f73d32dcde184Chris Banes    /**
3494837e2d38e11a8e85a2718e4620f73d32dcde184Chris Banes     * Returns the direct child of this layout, which itself is the ancestor of the
3504837e2d38e11a8e85a2718e4620f73d32dcde184Chris Banes     * given view.
3514837e2d38e11a8e85a2718e4620f73d32dcde184Chris Banes     */
3524837e2d38e11a8e85a2718e4620f73d32dcde184Chris Banes    private View findDirectChild(final View descendant) {
3534837e2d38e11a8e85a2718e4620f73d32dcde184Chris Banes        View directChild = descendant;
3544837e2d38e11a8e85a2718e4620f73d32dcde184Chris Banes        for (ViewParent p = descendant.getParent(); p != this && p != null; p = p.getParent()) {
3554837e2d38e11a8e85a2718e4620f73d32dcde184Chris Banes            if (p instanceof View) {
3564837e2d38e11a8e85a2718e4620f73d32dcde184Chris Banes                directChild = (View) p;
3574837e2d38e11a8e85a2718e4620f73d32dcde184Chris Banes            }
3584837e2d38e11a8e85a2718e4620f73d32dcde184Chris Banes        }
3594837e2d38e11a8e85a2718e4620f73d32dcde184Chris Banes        return directChild;
3604837e2d38e11a8e85a2718e4620f73d32dcde184Chris Banes    }
3614837e2d38e11a8e85a2718e4620f73d32dcde184Chris Banes
3621701feace5652372dd2fe1913f74169a12e2c940Chris Banes    private void updateDummyView() {
3631701feace5652372dd2fe1913f74169a12e2c940Chris Banes        if (!mCollapsingTitleEnabled && mDummyView != null) {
3641701feace5652372dd2fe1913f74169a12e2c940Chris Banes            // If we have a dummy view and we have our title disabled, remove it from its parent
3651701feace5652372dd2fe1913f74169a12e2c940Chris Banes            final ViewParent parent = mDummyView.getParent();
3661701feace5652372dd2fe1913f74169a12e2c940Chris Banes            if (parent instanceof ViewGroup) {
3671701feace5652372dd2fe1913f74169a12e2c940Chris Banes                ((ViewGroup) parent).removeView(mDummyView);
3681701feace5652372dd2fe1913f74169a12e2c940Chris Banes            }
3691701feace5652372dd2fe1913f74169a12e2c940Chris Banes        }
3701701feace5652372dd2fe1913f74169a12e2c940Chris Banes        if (mCollapsingTitleEnabled && mToolbar != null) {
3711701feace5652372dd2fe1913f74169a12e2c940Chris Banes            if (mDummyView == null) {
3721701feace5652372dd2fe1913f74169a12e2c940Chris Banes                mDummyView = new View(getContext());
3731701feace5652372dd2fe1913f74169a12e2c940Chris Banes            }
3741701feace5652372dd2fe1913f74169a12e2c940Chris Banes            if (mDummyView.getParent() == null) {
3751701feace5652372dd2fe1913f74169a12e2c940Chris Banes                mToolbar.addView(mDummyView, LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
3761701feace5652372dd2fe1913f74169a12e2c940Chris Banes            }
3771701feace5652372dd2fe1913f74169a12e2c940Chris Banes        }
3781701feace5652372dd2fe1913f74169a12e2c940Chris Banes    }
3791701feace5652372dd2fe1913f74169a12e2c940Chris Banes
3806ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes    @Override
381fdd6ec4abeb9100944ea5c043ebc07a707cb4764Jens Ole Lauridsen    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
382fdd6ec4abeb9100944ea5c043ebc07a707cb4764Jens Ole Lauridsen        ensureToolbar();
383fdd6ec4abeb9100944ea5c043ebc07a707cb4764Jens Ole Lauridsen        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
384fdd6ec4abeb9100944ea5c043ebc07a707cb4764Jens Ole Lauridsen    }
385fdd6ec4abeb9100944ea5c043ebc07a707cb4764Jens Ole Lauridsen
386fdd6ec4abeb9100944ea5c043ebc07a707cb4764Jens Ole Lauridsen    @Override
387a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
388a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        super.onLayout(changed, left, top, right, bottom);
389a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes
39079aa418487cdefb85d3c1fac32d6403a1ac6057dChris Banes        // Update the collapsed bounds by getting it's transformed bounds. This needs to be done
39179aa418487cdefb85d3c1fac32d6403a1ac6057dChris Banes        // before the children are offset below
39279aa418487cdefb85d3c1fac32d6403a1ac6057dChris Banes        if (mCollapsingTitleEnabled && mDummyView != null) {
393c06ea511ab9d97ed62ec10f10262f1c34b1905f0Chris Banes            // We only draw the title if the dummy view is being displayed (Toolbar removes
394c06ea511ab9d97ed62ec10f10262f1c34b1905f0Chris Banes            // views if there is no space)
3956b0726e90aa7c4657f5bf7459fadbaf58905c3c8Chris Banes            mDrawCollapsingTitle = ViewCompat.isAttachedToWindow(mDummyView)
3966b0726e90aa7c4657f5bf7459fadbaf58905c3c8Chris Banes                    && mDummyView.getVisibility() == VISIBLE;
397c06ea511ab9d97ed62ec10f10262f1c34b1905f0Chris Banes
398c06ea511ab9d97ed62ec10f10262f1c34b1905f0Chris Banes            if (mDrawCollapsingTitle) {
399b1d11409409e0d166360397adfd1e765bef49591Chris Banes                final boolean isRtl = ViewCompat.getLayoutDirection(this)
400b1d11409409e0d166360397adfd1e765bef49591Chris Banes                        == ViewCompat.LAYOUT_DIRECTION_RTL;
401b1d11409409e0d166360397adfd1e765bef49591Chris Banes
402b1d11409409e0d166360397adfd1e765bef49591Chris Banes                // Update the collapsed bounds
4034837e2d38e11a8e85a2718e4620f73d32dcde184Chris Banes                int bottomOffset = 0;
4044837e2d38e11a8e85a2718e4620f73d32dcde184Chris Banes                if (mToolbarDirectChild != null && mToolbarDirectChild != this) {
4054837e2d38e11a8e85a2718e4620f73d32dcde184Chris Banes                    final LayoutParams lp = (LayoutParams) mToolbarDirectChild.getLayoutParams();
4064837e2d38e11a8e85a2718e4620f73d32dcde184Chris Banes                    bottomOffset = lp.bottomMargin;
4074837e2d38e11a8e85a2718e4620f73d32dcde184Chris Banes                }
408c06ea511ab9d97ed62ec10f10262f1c34b1905f0Chris Banes                ViewGroupUtils.getDescendantRect(this, mDummyView, mTmpRect);
409b1d11409409e0d166360397adfd1e765bef49591Chris Banes                mCollapsingTextHelper.setCollapsedBounds(
410b1d11409409e0d166360397adfd1e765bef49591Chris Banes                        mTmpRect.left + (isRtl
411b1d11409409e0d166360397adfd1e765bef49591Chris Banes                                ? mToolbar.getTitleMarginEnd()
412b1d11409409e0d166360397adfd1e765bef49591Chris Banes                                : mToolbar.getTitleMarginStart()),
413874a5968599b8c53212ff49af5c047b1211b547aChris Banes                        bottom + mToolbar.getTitleMarginTop() - mTmpRect.height() - bottomOffset,
414b1d11409409e0d166360397adfd1e765bef49591Chris Banes                        mTmpRect.right + (isRtl
415b1d11409409e0d166360397adfd1e765bef49591Chris Banes                                ? mToolbar.getTitleMarginStart()
416b1d11409409e0d166360397adfd1e765bef49591Chris Banes                                : mToolbar.getTitleMarginEnd()),
417874a5968599b8c53212ff49af5c047b1211b547aChris Banes                        bottom - bottomOffset - mToolbar.getTitleMarginBottom());
41834550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes
419c06ea511ab9d97ed62ec10f10262f1c34b1905f0Chris Banes                // Update the expanded bounds
420c06ea511ab9d97ed62ec10f10262f1c34b1905f0Chris Banes                mCollapsingTextHelper.setExpandedBounds(
42134550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes                        isRtl ? mExpandedMarginEnd : mExpandedMarginStart,
422c06ea511ab9d97ed62ec10f10262f1c34b1905f0Chris Banes                        mTmpRect.bottom + mExpandedMarginTop,
42334550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes                        right - left - (isRtl ? mExpandedMarginStart : mExpandedMarginEnd),
424c06ea511ab9d97ed62ec10f10262f1c34b1905f0Chris Banes                        bottom - top - mExpandedMarginBottom);
425c06ea511ab9d97ed62ec10f10262f1c34b1905f0Chris Banes                // Now recalculate using the new bounds
426c06ea511ab9d97ed62ec10f10262f1c34b1905f0Chris Banes                mCollapsingTextHelper.recalculate();
427c06ea511ab9d97ed62ec10f10262f1c34b1905f0Chris Banes            }
42879aa418487cdefb85d3c1fac32d6403a1ac6057dChris Banes        }
42979aa418487cdefb85d3c1fac32d6403a1ac6057dChris Banes
430a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        // Update our child view offset helpers
431a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        for (int i = 0, z = getChildCount(); i < z; i++) {
43279208cc336926148978ccb49861f986fada745e0Chris Banes            final View child = getChildAt(i);
43379208cc336926148978ccb49861f986fada745e0Chris Banes
43479208cc336926148978ccb49861f986fada745e0Chris Banes            if (mLastInsets != null && !ViewCompat.getFitsSystemWindows(child)) {
43579208cc336926148978ccb49861f986fada745e0Chris Banes                final int insetTop = mLastInsets.getSystemWindowInsetTop();
43679208cc336926148978ccb49861f986fada745e0Chris Banes                if (child.getTop() < insetTop) {
43779208cc336926148978ccb49861f986fada745e0Chris Banes                    // If the child isn't set to fit system windows but is drawing within the inset
43879208cc336926148978ccb49861f986fada745e0Chris Banes                    // offset it down
43917ed3263761329f6aa6796941358c41001fff325Chris Banes                    ViewCompat.offsetTopAndBottom(child, insetTop);
44079208cc336926148978ccb49861f986fada745e0Chris Banes                }
44179208cc336926148978ccb49861f986fada745e0Chris Banes            }
44279208cc336926148978ccb49861f986fada745e0Chris Banes
44379208cc336926148978ccb49861f986fada745e0Chris Banes            getViewOffsetHelper(child).onViewLayout();
444a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        }
445a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes
446a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        // Finally, set our minimum height to enable proper AppBarLayout collapsing
44779208cc336926148978ccb49861f986fada745e0Chris Banes        if (mToolbar != null) {
4481701feace5652372dd2fe1913f74169a12e2c940Chris Banes            if (mCollapsingTitleEnabled && TextUtils.isEmpty(mCollapsingTextHelper.getText())) {
44931075a61da61f1f0184ee909a70b1efcd7cee807Chris Banes                // If we do not currently have a title, try and grab it from the Toolbar
45031075a61da61f1f0184ee909a70b1efcd7cee807Chris Banes                mCollapsingTextHelper.setText(mToolbar.getTitle());
45131075a61da61f1f0184ee909a70b1efcd7cee807Chris Banes            }
4524837e2d38e11a8e85a2718e4620f73d32dcde184Chris Banes            if (mToolbarDirectChild == null || mToolbarDirectChild == this) {
4534837e2d38e11a8e85a2718e4620f73d32dcde184Chris Banes                setMinimumHeight(getHeightWithMargins(mToolbar));
4544837e2d38e11a8e85a2718e4620f73d32dcde184Chris Banes            } else {
4554837e2d38e11a8e85a2718e4620f73d32dcde184Chris Banes                setMinimumHeight(getHeightWithMargins(mToolbarDirectChild));
4564837e2d38e11a8e85a2718e4620f73d32dcde184Chris Banes            }
4574837e2d38e11a8e85a2718e4620f73d32dcde184Chris Banes        }
4584837e2d38e11a8e85a2718e4620f73d32dcde184Chris Banes    }
4594837e2d38e11a8e85a2718e4620f73d32dcde184Chris Banes
4604837e2d38e11a8e85a2718e4620f73d32dcde184Chris Banes    private static int getHeightWithMargins(@NonNull final View view) {
4614837e2d38e11a8e85a2718e4620f73d32dcde184Chris Banes        final ViewGroup.LayoutParams lp = view.getLayoutParams();
4624837e2d38e11a8e85a2718e4620f73d32dcde184Chris Banes        if (lp instanceof MarginLayoutParams) {
4634837e2d38e11a8e85a2718e4620f73d32dcde184Chris Banes            final MarginLayoutParams mlp = (MarginLayoutParams) lp;
4644837e2d38e11a8e85a2718e4620f73d32dcde184Chris Banes            return view.getHeight() + mlp.topMargin + mlp.bottomMargin;
46579208cc336926148978ccb49861f986fada745e0Chris Banes        }
4664837e2d38e11a8e85a2718e4620f73d32dcde184Chris Banes        return view.getHeight();
467a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes    }
468a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes
469a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes    private static ViewOffsetHelper getViewOffsetHelper(View view) {
470a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        ViewOffsetHelper offsetHelper = (ViewOffsetHelper) view.getTag(R.id.view_offset_helper);
471a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        if (offsetHelper == null) {
472a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes            offsetHelper = new ViewOffsetHelper(view);
473a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes            view.setTag(R.id.view_offset_helper, offsetHelper);
474a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        }
475a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        return offsetHelper;
476a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes    }
477a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes
478a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes    /**
4791701feace5652372dd2fe1913f74169a12e2c940Chris Banes     * Sets the title to be displayed by this view, if enabled.
480a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes     *
4811701feace5652372dd2fe1913f74169a12e2c940Chris Banes     * @see #setTitleEnabled(boolean)
4821701feace5652372dd2fe1913f74169a12e2c940Chris Banes     * @see #getTitle()
4831701feace5652372dd2fe1913f74169a12e2c940Chris Banes     *
4841701feace5652372dd2fe1913f74169a12e2c940Chris Banes     * @attr ref R.styleable#CollapsingToolbarLayout_title
485a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes     */
4861701feace5652372dd2fe1913f74169a12e2c940Chris Banes    public void setTitle(@Nullable CharSequence title) {
487a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        mCollapsingTextHelper.setText(title);
488a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes    }
489a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes
4901701feace5652372dd2fe1913f74169a12e2c940Chris Banes    /**
4911701feace5652372dd2fe1913f74169a12e2c940Chris Banes     * Returns the title currently being displayed by this view. If the title is not enabled, then
4921701feace5652372dd2fe1913f74169a12e2c940Chris Banes     * this will return {@code null}.
4931701feace5652372dd2fe1913f74169a12e2c940Chris Banes     *
4941701feace5652372dd2fe1913f74169a12e2c940Chris Banes     * @attr ref R.styleable#CollapsingToolbarLayout_title
4951701feace5652372dd2fe1913f74169a12e2c940Chris Banes     */
4961701feace5652372dd2fe1913f74169a12e2c940Chris Banes    @Nullable
4971701feace5652372dd2fe1913f74169a12e2c940Chris Banes    public CharSequence getTitle() {
4981701feace5652372dd2fe1913f74169a12e2c940Chris Banes        return mCollapsingTitleEnabled ? mCollapsingTextHelper.getText() : null;
4991701feace5652372dd2fe1913f74169a12e2c940Chris Banes    }
5001701feace5652372dd2fe1913f74169a12e2c940Chris Banes
5011701feace5652372dd2fe1913f74169a12e2c940Chris Banes    /**
5021701feace5652372dd2fe1913f74169a12e2c940Chris Banes     * Sets whether this view should display its own title.
5031701feace5652372dd2fe1913f74169a12e2c940Chris Banes     *
5041701feace5652372dd2fe1913f74169a12e2c940Chris Banes     * <p>The title displayed by this view will shrink and grow based on the scroll offset.</p>
5051701feace5652372dd2fe1913f74169a12e2c940Chris Banes     *
5061701feace5652372dd2fe1913f74169a12e2c940Chris Banes     * @see #setTitle(CharSequence)
5071701feace5652372dd2fe1913f74169a12e2c940Chris Banes     * @see #isTitleEnabled()
5081701feace5652372dd2fe1913f74169a12e2c940Chris Banes     *
5091701feace5652372dd2fe1913f74169a12e2c940Chris Banes     * @attr ref R.styleable#CollapsingToolbarLayout_titleEnabled
5101701feace5652372dd2fe1913f74169a12e2c940Chris Banes     */
5111701feace5652372dd2fe1913f74169a12e2c940Chris Banes    public void setTitleEnabled(boolean enabled) {
5121701feace5652372dd2fe1913f74169a12e2c940Chris Banes        if (enabled != mCollapsingTitleEnabled) {
5131701feace5652372dd2fe1913f74169a12e2c940Chris Banes            mCollapsingTitleEnabled = enabled;
5141701feace5652372dd2fe1913f74169a12e2c940Chris Banes            updateDummyView();
5151701feace5652372dd2fe1913f74169a12e2c940Chris Banes            requestLayout();
5161701feace5652372dd2fe1913f74169a12e2c940Chris Banes        }
5171701feace5652372dd2fe1913f74169a12e2c940Chris Banes    }
5181701feace5652372dd2fe1913f74169a12e2c940Chris Banes
5191701feace5652372dd2fe1913f74169a12e2c940Chris Banes    /**
5201701feace5652372dd2fe1913f74169a12e2c940Chris Banes     * Returns whether this view is currently displaying its own title.
5211701feace5652372dd2fe1913f74169a12e2c940Chris Banes     *
5221701feace5652372dd2fe1913f74169a12e2c940Chris Banes     * @see #setTitleEnabled(boolean)
5231701feace5652372dd2fe1913f74169a12e2c940Chris Banes     *
5241701feace5652372dd2fe1913f74169a12e2c940Chris Banes     * @attr ref R.styleable#CollapsingToolbarLayout_titleEnabled
5251701feace5652372dd2fe1913f74169a12e2c940Chris Banes     */
5261701feace5652372dd2fe1913f74169a12e2c940Chris Banes    public boolean isTitleEnabled() {
5271701feace5652372dd2fe1913f74169a12e2c940Chris Banes        return mCollapsingTitleEnabled;
5281701feace5652372dd2fe1913f74169a12e2c940Chris Banes    }
5291701feace5652372dd2fe1913f74169a12e2c940Chris Banes
530e9f1ca9247c94f9073403fd6777403ae5b94e77aChris Banes    /**
531e9f1ca9247c94f9073403fd6777403ae5b94e77aChris Banes     * Set whether the content scrim and/or status bar scrim should be shown or not. Any change
532e9f1ca9247c94f9073403fd6777403ae5b94e77aChris Banes     * in the vertical scroll may overwrite this value. Any visibility change will be animated if
533e9f1ca9247c94f9073403fd6777403ae5b94e77aChris Banes     * this view has already been laid out.
534e9f1ca9247c94f9073403fd6777403ae5b94e77aChris Banes     *
535e9f1ca9247c94f9073403fd6777403ae5b94e77aChris Banes     * @param shown whether the scrims should be shown
536e9f1ca9247c94f9073403fd6777403ae5b94e77aChris Banes     *
537e9f1ca9247c94f9073403fd6777403ae5b94e77aChris Banes     * @see #getStatusBarScrim()
538e9f1ca9247c94f9073403fd6777403ae5b94e77aChris Banes     * @see #getContentScrim()
539e9f1ca9247c94f9073403fd6777403ae5b94e77aChris Banes     */
540e9f1ca9247c94f9073403fd6777403ae5b94e77aChris Banes    public void setScrimsShown(boolean shown) {
541e9f1ca9247c94f9073403fd6777403ae5b94e77aChris Banes        setScrimsShown(shown, ViewCompat.isLaidOut(this) && !isInEditMode());
542a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes    }
543a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes
544e9f1ca9247c94f9073403fd6777403ae5b94e77aChris Banes    /**
545e9f1ca9247c94f9073403fd6777403ae5b94e77aChris Banes     * Set whether the content scrim and/or status bar scrim should be shown or not. Any change
546e9f1ca9247c94f9073403fd6777403ae5b94e77aChris Banes     * in the vertical scroll may overwrite this value.
547e9f1ca9247c94f9073403fd6777403ae5b94e77aChris Banes     *
548e9f1ca9247c94f9073403fd6777403ae5b94e77aChris Banes     * @param shown whether the scrims should be shown
549e9f1ca9247c94f9073403fd6777403ae5b94e77aChris Banes     * @param animate whether to animate the visibility change
550e9f1ca9247c94f9073403fd6777403ae5b94e77aChris Banes     *
551e9f1ca9247c94f9073403fd6777403ae5b94e77aChris Banes     * @see #getStatusBarScrim()
552e9f1ca9247c94f9073403fd6777403ae5b94e77aChris Banes     * @see #getContentScrim()
553e9f1ca9247c94f9073403fd6777403ae5b94e77aChris Banes     */
554e9f1ca9247c94f9073403fd6777403ae5b94e77aChris Banes    public void setScrimsShown(boolean shown, boolean animate) {
555e9f1ca9247c94f9073403fd6777403ae5b94e77aChris Banes        if (mScrimsAreShown != shown) {
556e9f1ca9247c94f9073403fd6777403ae5b94e77aChris Banes            if (animate) {
557e9f1ca9247c94f9073403fd6777403ae5b94e77aChris Banes                animateScrim(shown ? 0xFF : 0x0);
5582b4b6274ed8c85c98489f67ddc8b7410c218e289Jens Ole Lauridsen            } else {
559e9f1ca9247c94f9073403fd6777403ae5b94e77aChris Banes                setScrimAlpha(shown ? 0xFF : 0x0);
5602b4b6274ed8c85c98489f67ddc8b7410c218e289Jens Ole Lauridsen            }
561e9f1ca9247c94f9073403fd6777403ae5b94e77aChris Banes            mScrimsAreShown = shown;
562f44e88b81821e61a65886cc7027617ca8995070bChris Banes        }
563f44e88b81821e61a65886cc7027617ca8995070bChris Banes    }
564f44e88b81821e61a65886cc7027617ca8995070bChris Banes
565f44e88b81821e61a65886cc7027617ca8995070bChris Banes    private void animateScrim(int targetAlpha) {
56679208cc336926148978ccb49861f986fada745e0Chris Banes        ensureToolbar();
567f44e88b81821e61a65886cc7027617ca8995070bChris Banes        if (mScrimAnimator == null) {
568f44e88b81821e61a65886cc7027617ca8995070bChris Banes            mScrimAnimator = ViewUtils.createAnimator();
5696df5bb9903307734ed05a5135c7812fb9b6d43c8Chris Banes            mScrimAnimator.setDuration(mScrimAnimationDuration);
5703a30d0eaba58dd961cf2ae9be3a7d0b9754a031eChris Banes            mScrimAnimator.setInterpolator(
5713a30d0eaba58dd961cf2ae9be3a7d0b9754a031eChris Banes                    targetAlpha > mScrimAlpha
5723a30d0eaba58dd961cf2ae9be3a7d0b9754a031eChris Banes                            ? AnimationUtils.FAST_OUT_LINEAR_IN_INTERPOLATOR
5733a30d0eaba58dd961cf2ae9be3a7d0b9754a031eChris Banes                            : AnimationUtils.LINEAR_OUT_SLOW_IN_INTERPOLATOR);
574f44e88b81821e61a65886cc7027617ca8995070bChris Banes            mScrimAnimator.setUpdateListener(new ValueAnimatorCompat.AnimatorUpdateListener() {
575f44e88b81821e61a65886cc7027617ca8995070bChris Banes                @Override
576f44e88b81821e61a65886cc7027617ca8995070bChris Banes                public void onAnimationUpdate(ValueAnimatorCompat animator) {
5772b4b6274ed8c85c98489f67ddc8b7410c218e289Jens Ole Lauridsen                    setScrimAlpha(animator.getAnimatedIntValue());
57850dfc33a565c4aefe6d5e844c93aa24a74cb80b3Chris Banes                }
579f44e88b81821e61a65886cc7027617ca8995070bChris Banes            });
580f44e88b81821e61a65886cc7027617ca8995070bChris Banes        } else if (mScrimAnimator.isRunning()) {
581f44e88b81821e61a65886cc7027617ca8995070bChris Banes            mScrimAnimator.cancel();
582f44e88b81821e61a65886cc7027617ca8995070bChris Banes        }
583a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes
5846ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes        mScrimAnimator.setIntValues(mScrimAlpha, targetAlpha);
585f44e88b81821e61a65886cc7027617ca8995070bChris Banes        mScrimAnimator.start();
586a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes    }
587a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes
5882b4b6274ed8c85c98489f67ddc8b7410c218e289Jens Ole Lauridsen    private void setScrimAlpha(int alpha) {
5892b4b6274ed8c85c98489f67ddc8b7410c218e289Jens Ole Lauridsen        if (alpha != mScrimAlpha) {
5902b4b6274ed8c85c98489f67ddc8b7410c218e289Jens Ole Lauridsen            final Drawable contentScrim = mContentScrim;
5912b4b6274ed8c85c98489f67ddc8b7410c218e289Jens Ole Lauridsen            if (contentScrim != null && mToolbar != null) {
5922b4b6274ed8c85c98489f67ddc8b7410c218e289Jens Ole Lauridsen                ViewCompat.postInvalidateOnAnimation(mToolbar);
5932b4b6274ed8c85c98489f67ddc8b7410c218e289Jens Ole Lauridsen            }
5942b4b6274ed8c85c98489f67ddc8b7410c218e289Jens Ole Lauridsen            mScrimAlpha = alpha;
5952b4b6274ed8c85c98489f67ddc8b7410c218e289Jens Ole Lauridsen            ViewCompat.postInvalidateOnAnimation(CollapsingToolbarLayout.this);
5962b4b6274ed8c85c98489f67ddc8b7410c218e289Jens Ole Lauridsen        }
5972b4b6274ed8c85c98489f67ddc8b7410c218e289Jens Ole Lauridsen    }
5982b4b6274ed8c85c98489f67ddc8b7410c218e289Jens Ole Lauridsen
599a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes    /**
6006ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes     * Set the drawable to use for the content scrim from resources. Providing null will disable
6016ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes     * the scrim functionality.
602a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes     *
6036ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes     * @param drawable the drawable to display
604a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes     *
6056ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes     * @attr ref R.styleable#CollapsingToolbarLayout_contentScrim
6066ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes     * @see #getContentScrim()
607a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes     */
6086ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes    public void setContentScrim(@Nullable Drawable drawable) {
6096ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes        if (mContentScrim != drawable) {
6106ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes            if (mContentScrim != null) {
6116ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes                mContentScrim.setCallback(null);
6126ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes            }
613bcb330de0c625b371010bada2a51363fc37b52ccChris Banes            mContentScrim = drawable != null ? drawable.mutate() : null;
614bcb330de0c625b371010bada2a51363fc37b52ccChris Banes            if (mContentScrim != null) {
615bcb330de0c625b371010bada2a51363fc37b52ccChris Banes                mContentScrim.setBounds(0, 0, getWidth(), getHeight());
616bcb330de0c625b371010bada2a51363fc37b52ccChris Banes                mContentScrim.setCallback(this);
617bcb330de0c625b371010bada2a51363fc37b52ccChris Banes                mContentScrim.setAlpha(mScrimAlpha);
618e9f1ca9247c94f9073403fd6777403ae5b94e77aChris Banes            }
6196ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes            ViewCompat.postInvalidateOnAnimation(this);
6206ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes        }
621a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes    }
622a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes
623a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes    /**
6246ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes     * Set the color to use for the content scrim.
625a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes     *
6266ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes     * @param color the color to display
627a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes     *
6286ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes     * @attr ref R.styleable#CollapsingToolbarLayout_contentScrim
6296ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes     * @see #getContentScrim()
630a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes     */
6311701feace5652372dd2fe1913f74169a12e2c940Chris Banes    public void setContentScrimColor(@ColorInt int color) {
6326ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes        setContentScrim(new ColorDrawable(color));
633a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes    }
634a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes
635a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes    /**
6366ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes     * Set the drawable to use for the content scrim from resources.
637a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes     *
6386ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes     * @param resId drawable resource id
6396ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes     *
6406ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes     * @attr ref R.styleable#CollapsingToolbarLayout_contentScrim
6416ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes     * @see #getContentScrim()
642a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes     */
6436ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes    public void setContentScrimResource(@DrawableRes int resId) {
6446ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes        setContentScrim(ContextCompat.getDrawable(getContext(), resId));
6456ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes
6466ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes    }
6476ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes
6486ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes    /**
6496ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes     * Returns the drawable which is used for the foreground scrim.
6506ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes     *
6516ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes     * @attr ref R.styleable#CollapsingToolbarLayout_contentScrim
6526ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes     * @see #setContentScrim(Drawable)
6536ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes     */
654bcb330de0c625b371010bada2a51363fc37b52ccChris Banes    @Nullable
6556ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes    public Drawable getContentScrim() {
6566ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes        return mContentScrim;
6576ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes    }
6586ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes
6596ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes    /**
6606ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes     * Set the drawable to use for the status bar scrim from resources.
6616ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes     * Providing null will disable the scrim functionality.
6626ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes     *
6636ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes     * <p>This scrim is only shown when we have been given a top system inset.</p>
6646ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes     *
6656ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes     * @param drawable the drawable to display
6666ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes     *
6676ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes     * @attr ref R.styleable#CollapsingToolbarLayout_statusBarScrim
6686ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes     * @see #getStatusBarScrim()
6696ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes     */
6706ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes    public void setStatusBarScrim(@Nullable Drawable drawable) {
6716ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes        if (mStatusBarScrim != drawable) {
6726ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes            if (mStatusBarScrim != null) {
6736ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes                mStatusBarScrim.setCallback(null);
6746ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes            }
675bcb330de0c625b371010bada2a51363fc37b52ccChris Banes            mStatusBarScrim = drawable != null ? drawable.mutate() : null;
676bcb330de0c625b371010bada2a51363fc37b52ccChris Banes            if (mStatusBarScrim != null) {
677bcb330de0c625b371010bada2a51363fc37b52ccChris Banes                if (mStatusBarScrim.isStateful()) {
678bcb330de0c625b371010bada2a51363fc37b52ccChris Banes                    mStatusBarScrim.setState(getDrawableState());
679bcb330de0c625b371010bada2a51363fc37b52ccChris Banes                }
680bcb330de0c625b371010bada2a51363fc37b52ccChris Banes                DrawableCompat.setLayoutDirection(mStatusBarScrim,
681bcb330de0c625b371010bada2a51363fc37b52ccChris Banes                        ViewCompat.getLayoutDirection(this));
682bcb330de0c625b371010bada2a51363fc37b52ccChris Banes                mStatusBarScrim.setVisible(getVisibility() == VISIBLE, false);
683bcb330de0c625b371010bada2a51363fc37b52ccChris Banes                mStatusBarScrim.setCallback(this);
684bcb330de0c625b371010bada2a51363fc37b52ccChris Banes                mStatusBarScrim.setAlpha(mScrimAlpha);
685bcb330de0c625b371010bada2a51363fc37b52ccChris Banes            }
6866ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes            ViewCompat.postInvalidateOnAnimation(this);
6876ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes        }
6886ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes    }
6896ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes
690bcb330de0c625b371010bada2a51363fc37b52ccChris Banes    @Override
691bcb330de0c625b371010bada2a51363fc37b52ccChris Banes    protected void drawableStateChanged() {
692bcb330de0c625b371010bada2a51363fc37b52ccChris Banes        super.drawableStateChanged();
693bcb330de0c625b371010bada2a51363fc37b52ccChris Banes
694bcb330de0c625b371010bada2a51363fc37b52ccChris Banes        final int[] state = getDrawableState();
695bcb330de0c625b371010bada2a51363fc37b52ccChris Banes        boolean changed = false;
696bcb330de0c625b371010bada2a51363fc37b52ccChris Banes
697bcb330de0c625b371010bada2a51363fc37b52ccChris Banes        Drawable d = mStatusBarScrim;
698bcb330de0c625b371010bada2a51363fc37b52ccChris Banes        if (d != null && d.isStateful()) {
699bcb330de0c625b371010bada2a51363fc37b52ccChris Banes            changed |= d.setState(state);
700bcb330de0c625b371010bada2a51363fc37b52ccChris Banes        }
701bcb330de0c625b371010bada2a51363fc37b52ccChris Banes        d = mContentScrim;
702bcb330de0c625b371010bada2a51363fc37b52ccChris Banes        if (d != null && d.isStateful()) {
703bcb330de0c625b371010bada2a51363fc37b52ccChris Banes            changed |= d.setState(state);
704bcb330de0c625b371010bada2a51363fc37b52ccChris Banes        }
705bcb330de0c625b371010bada2a51363fc37b52ccChris Banes
706bcb330de0c625b371010bada2a51363fc37b52ccChris Banes        if (changed) {
707bcb330de0c625b371010bada2a51363fc37b52ccChris Banes            invalidate();
708bcb330de0c625b371010bada2a51363fc37b52ccChris Banes        }
709bcb330de0c625b371010bada2a51363fc37b52ccChris Banes    }
710bcb330de0c625b371010bada2a51363fc37b52ccChris Banes
711bcb330de0c625b371010bada2a51363fc37b52ccChris Banes    @Override
712bcb330de0c625b371010bada2a51363fc37b52ccChris Banes    protected boolean verifyDrawable(Drawable who) {
713bcb330de0c625b371010bada2a51363fc37b52ccChris Banes        return super.verifyDrawable(who) || who == mContentScrim || who == mStatusBarScrim;
714bcb330de0c625b371010bada2a51363fc37b52ccChris Banes    }
715bcb330de0c625b371010bada2a51363fc37b52ccChris Banes
716bcb330de0c625b371010bada2a51363fc37b52ccChris Banes    @Override
717bcb330de0c625b371010bada2a51363fc37b52ccChris Banes    public void setVisibility(int visibility) {
718bcb330de0c625b371010bada2a51363fc37b52ccChris Banes        super.setVisibility(visibility);
719bcb330de0c625b371010bada2a51363fc37b52ccChris Banes
720bcb330de0c625b371010bada2a51363fc37b52ccChris Banes        final boolean visible = visibility == VISIBLE;
721bcb330de0c625b371010bada2a51363fc37b52ccChris Banes        if (mStatusBarScrim != null && mStatusBarScrim.isVisible() != visible) {
722bcb330de0c625b371010bada2a51363fc37b52ccChris Banes            mStatusBarScrim.setVisible(visible, false);
723bcb330de0c625b371010bada2a51363fc37b52ccChris Banes        }
724bcb330de0c625b371010bada2a51363fc37b52ccChris Banes        if (mContentScrim != null && mContentScrim.isVisible() != visible) {
725bcb330de0c625b371010bada2a51363fc37b52ccChris Banes            mContentScrim.setVisible(visible, false);
726bcb330de0c625b371010bada2a51363fc37b52ccChris Banes        }
727bcb330de0c625b371010bada2a51363fc37b52ccChris Banes    }
728bcb330de0c625b371010bada2a51363fc37b52ccChris Banes
7296ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes    /**
7306ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes     * Set the color to use for the status bar scrim.
7316ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes     *
7326ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes     * <p>This scrim is only shown when we have been given a top system inset.</p>
7336ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes     *
7346ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes     * @param color the color to display
7356ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes     *
7366ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes     * @attr ref R.styleable#CollapsingToolbarLayout_statusBarScrim
7376ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes     * @see #getStatusBarScrim()
7386ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes     */
7391701feace5652372dd2fe1913f74169a12e2c940Chris Banes    public void setStatusBarScrimColor(@ColorInt int color) {
7406ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes        setStatusBarScrim(new ColorDrawable(color));
7416ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes    }
7426ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes
7436ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes    /**
7446ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes     * Set the drawable to use for the content scrim from resources.
7456ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes     *
7466ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes     * @param resId drawable resource id
7476ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes     *
7486ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes     * @attr ref R.styleable#CollapsingToolbarLayout_statusBarScrim
7496ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes     * @see #getStatusBarScrim()
7506ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes     */
7516ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes    public void setStatusBarScrimResource(@DrawableRes int resId) {
7526ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes        setStatusBarScrim(ContextCompat.getDrawable(getContext(), resId));
7536ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes    }
7546ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes
7556ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes    /**
7566ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes     * Returns the drawable which is used for the status bar scrim.
7576ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes     *
7586ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes     * @attr ref R.styleable#CollapsingToolbarLayout_statusBarScrim
7596ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes     * @see #setStatusBarScrim(Drawable)
7606ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes     */
761bcb330de0c625b371010bada2a51363fc37b52ccChris Banes    @Nullable
7626ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes    public Drawable getStatusBarScrim() {
7636ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes        return mStatusBarScrim;
764a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes    }
765a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes
766a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes    /**
767a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes     * Sets the text color and size for the collapsed title from the specified
768a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes     * TextAppearance resource.
769a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes     *
770a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes     * @attr ref android.support.design.R.styleable#CollapsingToolbarLayout_collapsedTitleTextAppearance
771a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes     */
7721701feace5652372dd2fe1913f74169a12e2c940Chris Banes    public void setCollapsedTitleTextAppearance(@StyleRes int resId) {
773a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        mCollapsingTextHelper.setCollapsedTextAppearance(resId);
774a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes    }
775a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes
776a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes    /**
777a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes     * Sets the text color of the collapsed title.
778a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes     *
779a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes     * @param color The new text color in ARGB format
780a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes     */
7811701feace5652372dd2fe1913f74169a12e2c940Chris Banes    public void setCollapsedTitleTextColor(@ColorInt int color) {
782a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        mCollapsingTextHelper.setCollapsedTextColor(color);
783a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes    }
784a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes
785a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes    /**
7865c7d7bbceeaebc46dc2e4b2135cc330414f716d4Chris Banes     * Sets the horizontal alignment of the collapsed title and the vertical gravity that will
7875c7d7bbceeaebc46dc2e4b2135cc330414f716d4Chris Banes     * be used when there is extra space in the collapsed bounds beyond what is required for
7885c7d7bbceeaebc46dc2e4b2135cc330414f716d4Chris Banes     * the title itself.
7895c7d7bbceeaebc46dc2e4b2135cc330414f716d4Chris Banes     *
7905c7d7bbceeaebc46dc2e4b2135cc330414f716d4Chris Banes     * @attr ref android.support.design.R.styleable#CollapsingToolbarLayout_collapsedTitleGravity
7915c7d7bbceeaebc46dc2e4b2135cc330414f716d4Chris Banes     */
7925c7d7bbceeaebc46dc2e4b2135cc330414f716d4Chris Banes    public void setCollapsedTitleGravity(int gravity) {
793cd7313d4cdb81d0abaf9dc7aefc6ebadea899ab5Chris Banes        mCollapsingTextHelper.setCollapsedTextGravity(gravity);
7945c7d7bbceeaebc46dc2e4b2135cc330414f716d4Chris Banes    }
7955c7d7bbceeaebc46dc2e4b2135cc330414f716d4Chris Banes
7965c7d7bbceeaebc46dc2e4b2135cc330414f716d4Chris Banes    /**
7975c7d7bbceeaebc46dc2e4b2135cc330414f716d4Chris Banes     * Returns the horizontal and vertical alignment for title when collapsed.
7985c7d7bbceeaebc46dc2e4b2135cc330414f716d4Chris Banes     *
7995c7d7bbceeaebc46dc2e4b2135cc330414f716d4Chris Banes     * @attr ref android.support.design.R.styleable#CollapsingToolbarLayout_collapsedTitleGravity
8005c7d7bbceeaebc46dc2e4b2135cc330414f716d4Chris Banes     */
8015c7d7bbceeaebc46dc2e4b2135cc330414f716d4Chris Banes    public int getCollapsedTitleGravity() {
8025c7d7bbceeaebc46dc2e4b2135cc330414f716d4Chris Banes        return mCollapsingTextHelper.getCollapsedTextGravity();
8035c7d7bbceeaebc46dc2e4b2135cc330414f716d4Chris Banes    }
8045c7d7bbceeaebc46dc2e4b2135cc330414f716d4Chris Banes
8055c7d7bbceeaebc46dc2e4b2135cc330414f716d4Chris Banes    /**
806a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes     * Sets the text color and size for the expanded title from the specified
807a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes     * TextAppearance resource.
808a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes     *
809a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes     * @attr ref android.support.design.R.styleable#CollapsingToolbarLayout_expandedTitleTextAppearance
810a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes     */
8111701feace5652372dd2fe1913f74169a12e2c940Chris Banes    public void setExpandedTitleTextAppearance(@StyleRes int resId) {
812a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        mCollapsingTextHelper.setExpandedTextAppearance(resId);
813a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes    }
814a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes
815a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes    /**
816a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes     * Sets the text color of the expanded title.
817a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes     *
818a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes     * @param color The new text color in ARGB format
819a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes     */
8201701feace5652372dd2fe1913f74169a12e2c940Chris Banes    public void setExpandedTitleColor(@ColorInt int color) {
821a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        mCollapsingTextHelper.setExpandedTextColor(color);
822a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes    }
823a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes
8246ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes    /**
8255c7d7bbceeaebc46dc2e4b2135cc330414f716d4Chris Banes     * Sets the horizontal alignment of the expanded title and the vertical gravity that will
8265c7d7bbceeaebc46dc2e4b2135cc330414f716d4Chris Banes     * be used when there is extra space in the expanded bounds beyond what is required for
8275c7d7bbceeaebc46dc2e4b2135cc330414f716d4Chris Banes     * the title itself.
8285c7d7bbceeaebc46dc2e4b2135cc330414f716d4Chris Banes     *
8295c7d7bbceeaebc46dc2e4b2135cc330414f716d4Chris Banes     * @attr ref android.support.design.R.styleable#CollapsingToolbarLayout_expandedTitleGravity
8305c7d7bbceeaebc46dc2e4b2135cc330414f716d4Chris Banes     */
8315c7d7bbceeaebc46dc2e4b2135cc330414f716d4Chris Banes    public void setExpandedTitleGravity(int gravity) {
8325c7d7bbceeaebc46dc2e4b2135cc330414f716d4Chris Banes        mCollapsingTextHelper.setExpandedTextGravity(gravity);
8335c7d7bbceeaebc46dc2e4b2135cc330414f716d4Chris Banes    }
8345c7d7bbceeaebc46dc2e4b2135cc330414f716d4Chris Banes
8355c7d7bbceeaebc46dc2e4b2135cc330414f716d4Chris Banes    /**
8365c7d7bbceeaebc46dc2e4b2135cc330414f716d4Chris Banes     * Returns the horizontal and vertical alignment for title when expanded.
8375c7d7bbceeaebc46dc2e4b2135cc330414f716d4Chris Banes     *
8385c7d7bbceeaebc46dc2e4b2135cc330414f716d4Chris Banes     * @attr ref android.support.design.R.styleable#CollapsingToolbarLayout_expandedTitleGravity
8395c7d7bbceeaebc46dc2e4b2135cc330414f716d4Chris Banes     */
8405c7d7bbceeaebc46dc2e4b2135cc330414f716d4Chris Banes    public int getExpandedTitleGravity() {
8415c7d7bbceeaebc46dc2e4b2135cc330414f716d4Chris Banes        return mCollapsingTextHelper.getExpandedTextGravity();
8425c7d7bbceeaebc46dc2e4b2135cc330414f716d4Chris Banes    }
8435c7d7bbceeaebc46dc2e4b2135cc330414f716d4Chris Banes
8445c7d7bbceeaebc46dc2e4b2135cc330414f716d4Chris Banes    /**
845d29e79fa09f428c510d1d9ca758dbda35a323f71Chris Banes     * Set the typeface to use for the collapsed title.
846d29e79fa09f428c510d1d9ca758dbda35a323f71Chris Banes     *
847d29e79fa09f428c510d1d9ca758dbda35a323f71Chris Banes     * @param typeface typeface to use, or {@code null} to use the default.
848d29e79fa09f428c510d1d9ca758dbda35a323f71Chris Banes     */
849d29e79fa09f428c510d1d9ca758dbda35a323f71Chris Banes    public void setCollapsedTitleTypeface(@Nullable Typeface typeface) {
850d29e79fa09f428c510d1d9ca758dbda35a323f71Chris Banes        mCollapsingTextHelper.setCollapsedTypeface(typeface);
851d29e79fa09f428c510d1d9ca758dbda35a323f71Chris Banes    }
852d29e79fa09f428c510d1d9ca758dbda35a323f71Chris Banes
853d29e79fa09f428c510d1d9ca758dbda35a323f71Chris Banes    /**
854d29e79fa09f428c510d1d9ca758dbda35a323f71Chris Banes     * Returns the typeface used for the collapsed title.
855d29e79fa09f428c510d1d9ca758dbda35a323f71Chris Banes     */
856d29e79fa09f428c510d1d9ca758dbda35a323f71Chris Banes    @NonNull
857d29e79fa09f428c510d1d9ca758dbda35a323f71Chris Banes    public Typeface getCollapsedTitleTypeface() {
858d29e79fa09f428c510d1d9ca758dbda35a323f71Chris Banes        return mCollapsingTextHelper.getCollapsedTypeface();
859d29e79fa09f428c510d1d9ca758dbda35a323f71Chris Banes    }
860d29e79fa09f428c510d1d9ca758dbda35a323f71Chris Banes
861d29e79fa09f428c510d1d9ca758dbda35a323f71Chris Banes    /**
862d29e79fa09f428c510d1d9ca758dbda35a323f71Chris Banes     * Set the typeface to use for the expanded title.
863d29e79fa09f428c510d1d9ca758dbda35a323f71Chris Banes     *
864d29e79fa09f428c510d1d9ca758dbda35a323f71Chris Banes     * @param typeface typeface to use, or {@code null} to use the default.
865d29e79fa09f428c510d1d9ca758dbda35a323f71Chris Banes     */
866d29e79fa09f428c510d1d9ca758dbda35a323f71Chris Banes    public void setExpandedTitleTypeface(@Nullable Typeface typeface) {
867d29e79fa09f428c510d1d9ca758dbda35a323f71Chris Banes        mCollapsingTextHelper.setExpandedTypeface(typeface);
868d29e79fa09f428c510d1d9ca758dbda35a323f71Chris Banes    }
869d29e79fa09f428c510d1d9ca758dbda35a323f71Chris Banes
870d29e79fa09f428c510d1d9ca758dbda35a323f71Chris Banes    /**
871d29e79fa09f428c510d1d9ca758dbda35a323f71Chris Banes     * Returns the typeface used for the expanded title.
872d29e79fa09f428c510d1d9ca758dbda35a323f71Chris Banes     */
873d29e79fa09f428c510d1d9ca758dbda35a323f71Chris Banes    @NonNull
874d29e79fa09f428c510d1d9ca758dbda35a323f71Chris Banes    public Typeface getExpandedTitleTypeface() {
875d29e79fa09f428c510d1d9ca758dbda35a323f71Chris Banes        return mCollapsingTextHelper.getExpandedTypeface();
876d29e79fa09f428c510d1d9ca758dbda35a323f71Chris Banes    }
877d29e79fa09f428c510d1d9ca758dbda35a323f71Chris Banes
878d29e79fa09f428c510d1d9ca758dbda35a323f71Chris Banes    /**
87934550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes     * Sets the expanded title margins.
88034550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes     *
88134550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes     * @param start the starting title margin in pixels
88234550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes     * @param top the top title margin in pixels
88334550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes     * @param end the ending title margin in pixels
88434550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes     * @param bottom the bottom title margin in pixels
88534550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes     *
88634550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes     * @see #getExpandedTitleMarginStart()
88734550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes     * @see #getExpandedTitleMarginTop()
88834550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes     * @see #getExpandedTitleMarginEnd()
88934550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes     * @see #getExpandedTitleMarginBottom()
89034550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes     * @attr ref android.support.design.R.styleable#CollapsingToolbarLayout_expandedTitleMargin
89134550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes     */
89234550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes    public void setExpandedTitleMargin(int start, int top, int end, int bottom) {
89334550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes        mExpandedMarginStart = start;
89434550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes        mExpandedMarginTop = top;
89534550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes        mExpandedMarginEnd = end;
89634550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes        mExpandedMarginBottom = bottom;
89734550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes        requestLayout();
89834550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes    }
89934550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes
90034550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes    /**
90134550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes     * @return the starting expanded title margin in pixels
90234550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes     *
90334550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes     * @see #setExpandedTitleMarginStart(int)
90434550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes     * @attr ref android.support.design.R.styleable#CollapsingToolbarLayout_expandedTitleMarginStart
90534550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes     */
90634550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes    public int getExpandedTitleMarginStart() {
90734550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes        return mExpandedMarginStart;
90834550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes    }
90934550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes
91034550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes    /**
91134550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes     * Sets the starting expanded title margin in pixels.
91234550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes     *
91334550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes     * @param margin the starting title margin in pixels
91434550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes     * @see #getExpandedTitleMarginStart()
91534550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes     * @attr ref android.support.design.R.styleable#CollapsingToolbarLayout_expandedTitleMarginStart
91634550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes     */
91734550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes    public void setExpandedTitleMarginStart(int margin) {
91834550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes        mExpandedMarginStart = margin;
91934550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes        requestLayout();
92034550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes    }
92134550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes
92234550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes    /**
92334550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes     * @return the top expanded title margin in pixels
92434550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes     * @see #setExpandedTitleMarginTop(int)
92534550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes     * @attr ref android.support.design.R.styleable#CollapsingToolbarLayout_expandedTitleMarginTop
92634550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes     */
92734550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes    public int getExpandedTitleMarginTop() {
92834550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes        return mExpandedMarginTop;
92934550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes    }
93034550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes
93134550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes    /**
93234550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes     * Sets the top expanded title margin in pixels.
93334550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes     *
93434550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes     * @param margin the top title margin in pixels
93534550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes     * @see #getExpandedTitleMarginTop()
93634550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes     * @attr ref android.support.design.R.styleable#CollapsingToolbarLayout_expandedTitleMarginTop
93734550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes     */
93834550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes    public void setExpandedTitleMarginTop(int margin) {
93934550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes        mExpandedMarginTop = margin;
94034550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes        requestLayout();
94134550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes    }
94234550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes
94334550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes    /**
94434550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes     * @return the ending expanded title margin in pixels
94534550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes     * @see #setExpandedTitleMarginEnd(int)
94634550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes     * @attr ref android.support.design.R.styleable#CollapsingToolbarLayout_expandedTitleMarginEnd
94734550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes     */
94834550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes    public int getExpandedTitleMarginEnd() {
94934550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes        return mExpandedMarginEnd;
95034550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes    }
95134550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes
95234550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes    /**
95334550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes     * Sets the ending expanded title margin in pixels.
95434550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes     *
95534550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes     * @param margin the ending title margin in pixels
95634550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes     * @see #getExpandedTitleMarginEnd()
95734550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes     * @attr ref android.support.design.R.styleable#CollapsingToolbarLayout_expandedTitleMarginEnd
95834550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes     */
95934550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes    public void setExpandedTitleMarginEnd(int margin) {
96034550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes        mExpandedMarginEnd = margin;
96134550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes        requestLayout();
96234550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes    }
96334550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes
96434550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes    /**
96534550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes     * @return the bottom expanded title margin in pixels
96634550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes     * @see #setExpandedTitleMarginBottom(int)
96734550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes     * @attr ref android.support.design.R.styleable#CollapsingToolbarLayout_expandedTitleMarginBottom
96834550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes     */
96934550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes    public int getExpandedTitleMarginBottom() {
97034550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes        return mExpandedMarginBottom;
97134550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes    }
97234550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes
97334550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes    /**
97434550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes     * Sets the bottom expanded title margin in pixels.
97534550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes     *
97634550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes     * @param margin the bottom title margin in pixels
97734550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes     * @see #getExpandedTitleMarginBottom()
97834550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes     * @attr ref android.support.design.R.styleable#CollapsingToolbarLayout_expandedTitleMarginBottom
97934550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes     */
98034550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes    public void setExpandedTitleMarginBottom(int margin) {
98134550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes        mExpandedMarginBottom = margin;
98234550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes        requestLayout();
98334550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes    }
98434550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes
98534550bb9e60e8935f2007ffea069c5bacd971e36Chris Banes    /**
9866df5bb9903307734ed05a5135c7812fb9b6d43c8Chris Banes     * Set the amount of visible height in pixels used to define when to trigger a scrim
9876df5bb9903307734ed05a5135c7812fb9b6d43c8Chris Banes     * visibility change.
9886df5bb9903307734ed05a5135c7812fb9b6d43c8Chris Banes     *
9896df5bb9903307734ed05a5135c7812fb9b6d43c8Chris Banes     * <p>If the visible height of this view is less than the given value, the scrims will be
9906df5bb9903307734ed05a5135c7812fb9b6d43c8Chris Banes     * made visible, otherwise they are hidden.</p>
9916df5bb9903307734ed05a5135c7812fb9b6d43c8Chris Banes     *
9926df5bb9903307734ed05a5135c7812fb9b6d43c8Chris Banes     * @param height value in pixels used to define when to trigger a scrim visibility change
9936df5bb9903307734ed05a5135c7812fb9b6d43c8Chris Banes     *
9946df5bb9903307734ed05a5135c7812fb9b6d43c8Chris Banes     * @attr ref android.support.design.R.styleable#CollapsingToolbarLayout_scrimVisibleHeightTrigger
9956df5bb9903307734ed05a5135c7812fb9b6d43c8Chris Banes     */
9966df5bb9903307734ed05a5135c7812fb9b6d43c8Chris Banes    public void setScrimVisibleHeightTrigger(@IntRange(from = 0) final int height) {
9976df5bb9903307734ed05a5135c7812fb9b6d43c8Chris Banes        if (mScrimVisibleHeightTrigger != height) {
9986df5bb9903307734ed05a5135c7812fb9b6d43c8Chris Banes            mScrimVisibleHeightTrigger = height;
9996df5bb9903307734ed05a5135c7812fb9b6d43c8Chris Banes            // Update the scrim visibilty
10006df5bb9903307734ed05a5135c7812fb9b6d43c8Chris Banes            updateScrimVisibility();
10016df5bb9903307734ed05a5135c7812fb9b6d43c8Chris Banes        }
10026df5bb9903307734ed05a5135c7812fb9b6d43c8Chris Banes    }
10036df5bb9903307734ed05a5135c7812fb9b6d43c8Chris Banes
10046df5bb9903307734ed05a5135c7812fb9b6d43c8Chris Banes    /**
10056df5bb9903307734ed05a5135c7812fb9b6d43c8Chris Banes     * Returns the amount of visible height in pixels used to define when to trigger a scrim
10066df5bb9903307734ed05a5135c7812fb9b6d43c8Chris Banes     * visibility change.
10076df5bb9903307734ed05a5135c7812fb9b6d43c8Chris Banes     *
10086df5bb9903307734ed05a5135c7812fb9b6d43c8Chris Banes     * @see #setScrimTriggerOffset(int)
10096df5bb9903307734ed05a5135c7812fb9b6d43c8Chris Banes     */
10106df5bb9903307734ed05a5135c7812fb9b6d43c8Chris Banes    public int getScrimVisibleHeightTrigger() {
10116df5bb9903307734ed05a5135c7812fb9b6d43c8Chris Banes        if (mScrimVisibleHeightTrigger >= 0) {
10126df5bb9903307734ed05a5135c7812fb9b6d43c8Chris Banes            // If we have one explictly set, return it
10136df5bb9903307734ed05a5135c7812fb9b6d43c8Chris Banes            return mScrimVisibleHeightTrigger;
10146df5bb9903307734ed05a5135c7812fb9b6d43c8Chris Banes        }
10156df5bb9903307734ed05a5135c7812fb9b6d43c8Chris Banes
10166df5bb9903307734ed05a5135c7812fb9b6d43c8Chris Banes        // Otherwise we'll use the default computed value
10176df5bb9903307734ed05a5135c7812fb9b6d43c8Chris Banes        final int insetTop = mLastInsets != null ? mLastInsets.getSystemWindowInsetTop() : 0;
10186df5bb9903307734ed05a5135c7812fb9b6d43c8Chris Banes
10196df5bb9903307734ed05a5135c7812fb9b6d43c8Chris Banes        final int minHeight = ViewCompat.getMinimumHeight(this);
10206df5bb9903307734ed05a5135c7812fb9b6d43c8Chris Banes        if (minHeight > 0) {
10216df5bb9903307734ed05a5135c7812fb9b6d43c8Chris Banes            // If we have a minHeight set, lets use 2 * minHeight (capped at our height)
10226df5bb9903307734ed05a5135c7812fb9b6d43c8Chris Banes            return Math.min((minHeight * 2) + insetTop, getHeight());
10236df5bb9903307734ed05a5135c7812fb9b6d43c8Chris Banes        }
10246df5bb9903307734ed05a5135c7812fb9b6d43c8Chris Banes
10256df5bb9903307734ed05a5135c7812fb9b6d43c8Chris Banes        // If we reach here then we don't have a min height set. Instead we'll take a
10266df5bb9903307734ed05a5135c7812fb9b6d43c8Chris Banes        // guess at 1/3 of our height being visible
10276df5bb9903307734ed05a5135c7812fb9b6d43c8Chris Banes        return getHeight() / 3;
10286df5bb9903307734ed05a5135c7812fb9b6d43c8Chris Banes    }
10296df5bb9903307734ed05a5135c7812fb9b6d43c8Chris Banes
10306df5bb9903307734ed05a5135c7812fb9b6d43c8Chris Banes    /**
10316df5bb9903307734ed05a5135c7812fb9b6d43c8Chris Banes     * Set the duration used for scrim visibility animations.
10326df5bb9903307734ed05a5135c7812fb9b6d43c8Chris Banes     *
10336df5bb9903307734ed05a5135c7812fb9b6d43c8Chris Banes     * @param duration the duration to use in milliseconds
10346df5bb9903307734ed05a5135c7812fb9b6d43c8Chris Banes     *
10356df5bb9903307734ed05a5135c7812fb9b6d43c8Chris Banes     * @attr ref android.support.design.R.styleable#CollapsingToolbarLayout_scrimAnimationDuration
10366df5bb9903307734ed05a5135c7812fb9b6d43c8Chris Banes     */
10379ee6a3fbb89698ebd7c26d4a86e2892a37a0d87aAurimas Liutikas    public void setScrimAnimationDuration(@IntRange(from = 0) final long duration) {
10386df5bb9903307734ed05a5135c7812fb9b6d43c8Chris Banes        mScrimAnimationDuration = duration;
10396df5bb9903307734ed05a5135c7812fb9b6d43c8Chris Banes    }
10406df5bb9903307734ed05a5135c7812fb9b6d43c8Chris Banes
10416df5bb9903307734ed05a5135c7812fb9b6d43c8Chris Banes    /**
10426df5bb9903307734ed05a5135c7812fb9b6d43c8Chris Banes     * Returns the duration in milliseconds used for scrim visibility animations.
10436ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes     */
1044e852801f9258e00f89da48918b58a6e933643ab9Aurimas Liutikas    public long getScrimAnimationDuration() {
10456df5bb9903307734ed05a5135c7812fb9b6d43c8Chris Banes        return mScrimAnimationDuration;
1046a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes    }
1047a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes
1048a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes    @Override
1049a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes    protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
1050a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        return p instanceof LayoutParams;
1051a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes    }
1052a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes
1053a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes    @Override
1054a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes    protected LayoutParams generateDefaultLayoutParams() {
1055a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        return new LayoutParams(super.generateDefaultLayoutParams());
1056a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes    }
1057a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes
1058a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes    @Override
1059a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes    public FrameLayout.LayoutParams generateLayoutParams(AttributeSet attrs) {
1060a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        return new LayoutParams(getContext(), attrs);
1061a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes    }
1062a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes
1063a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes    @Override
1064a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes    protected FrameLayout.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
1065a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        return new LayoutParams(p);
1066a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes    }
1067a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes
1068a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes    public static class LayoutParams extends FrameLayout.LayoutParams {
1069a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes
1070a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        private static final float DEFAULT_PARALLAX_MULTIPLIER = 0.5f;
1071a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes
107250dfc33a565c4aefe6d5e844c93aa24a74cb80b3Chris Banes        /** @hide */
107350dfc33a565c4aefe6d5e844c93aa24a74cb80b3Chris Banes        @IntDef({
107450dfc33a565c4aefe6d5e844c93aa24a74cb80b3Chris Banes                COLLAPSE_MODE_OFF,
107550dfc33a565c4aefe6d5e844c93aa24a74cb80b3Chris Banes                COLLAPSE_MODE_PIN,
107650dfc33a565c4aefe6d5e844c93aa24a74cb80b3Chris Banes                COLLAPSE_MODE_PARALLAX
107750dfc33a565c4aefe6d5e844c93aa24a74cb80b3Chris Banes        })
107850dfc33a565c4aefe6d5e844c93aa24a74cb80b3Chris Banes        @Retention(RetentionPolicy.SOURCE)
107950dfc33a565c4aefe6d5e844c93aa24a74cb80b3Chris Banes        @interface CollapseMode {}
108050dfc33a565c4aefe6d5e844c93aa24a74cb80b3Chris Banes
1081a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        /**
1082a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes         * The view will act as normal with no collapsing behavior.
1083a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes         */
1084a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        public static final int COLLAPSE_MODE_OFF = 0;
1085a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes
1086a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        /**
1087a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes         * The view will pin in place until it reaches the bottom of the
1088a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes         * {@link CollapsingToolbarLayout}.
1089a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes         */
1090a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        public static final int COLLAPSE_MODE_PIN = 1;
1091a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes
1092a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        /**
1093a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes         * The view will scroll in a parallax fashion. See {@link #setParallaxMultiplier(float)}
1094a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes         * to change the multiplier used.
1095a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes         */
1096a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        public static final int COLLAPSE_MODE_PARALLAX = 2;
1097a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes
1098a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        int mCollapseMode = COLLAPSE_MODE_OFF;
1099a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        float mParallaxMult = DEFAULT_PARALLAX_MULTIPLIER;
1100a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes
1101a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        public LayoutParams(Context c, AttributeSet attrs) {
1102a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes            super(c, attrs);
1103a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes
1104a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes            TypedArray a = c.obtainStyledAttributes(attrs,
1105c6cbbb50a06ec08e6888bd1c3dfd7fdf588d9db5Chris Banes                    R.styleable.CollapsingToolbarLayout_Layout);
1106a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes            mCollapseMode = a.getInt(
1107c6cbbb50a06ec08e6888bd1c3dfd7fdf588d9db5Chris Banes                    R.styleable.CollapsingToolbarLayout_Layout_layout_collapseMode,
1108a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes                    COLLAPSE_MODE_OFF);
1109a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes            setParallaxMultiplier(a.getFloat(
1110c6cbbb50a06ec08e6888bd1c3dfd7fdf588d9db5Chris Banes                    R.styleable.CollapsingToolbarLayout_Layout_layout_collapseParallaxMultiplier,
1111a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes                    DEFAULT_PARALLAX_MULTIPLIER));
1112a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes            a.recycle();
1113a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        }
1114a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes
1115a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        public LayoutParams(int width, int height) {
1116a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes            super(width, height);
1117a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        }
1118a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes
1119a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        public LayoutParams(int width, int height, int gravity) {
1120a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes            super(width, height, gravity);
1121a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        }
1122a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes
1123a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        public LayoutParams(ViewGroup.LayoutParams p) {
1124a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes            super(p);
1125a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        }
1126a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes
1127a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        public LayoutParams(MarginLayoutParams source) {
1128a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes            super(source);
1129a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        }
1130a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes
1131a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        public LayoutParams(FrameLayout.LayoutParams source) {
1132a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes            super(source);
1133a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        }
1134a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes
1135a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        /**
1136a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes         * Set the collapse mode.
1137a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes         *
1138a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes         * @param collapseMode one of {@link #COLLAPSE_MODE_OFF}, {@link #COLLAPSE_MODE_PIN}
1139a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes         *                     or {@link #COLLAPSE_MODE_PARALLAX}.
1140a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes         */
114150dfc33a565c4aefe6d5e844c93aa24a74cb80b3Chris Banes        public void setCollapseMode(@CollapseMode int collapseMode) {
1142a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes            mCollapseMode = collapseMode;
1143a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        }
1144a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes
1145a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        /**
114650dfc33a565c4aefe6d5e844c93aa24a74cb80b3Chris Banes         * Returns the requested collapse mode.
114750dfc33a565c4aefe6d5e844c93aa24a74cb80b3Chris Banes         *
114850dfc33a565c4aefe6d5e844c93aa24a74cb80b3Chris Banes         * @return the current mode. One of {@link #COLLAPSE_MODE_OFF}, {@link #COLLAPSE_MODE_PIN}
114950dfc33a565c4aefe6d5e844c93aa24a74cb80b3Chris Banes         * or {@link #COLLAPSE_MODE_PARALLAX}.
115050dfc33a565c4aefe6d5e844c93aa24a74cb80b3Chris Banes         */
115150dfc33a565c4aefe6d5e844c93aa24a74cb80b3Chris Banes        @CollapseMode
115250dfc33a565c4aefe6d5e844c93aa24a74cb80b3Chris Banes        public int getCollapseMode() {
115350dfc33a565c4aefe6d5e844c93aa24a74cb80b3Chris Banes            return mCollapseMode;
115450dfc33a565c4aefe6d5e844c93aa24a74cb80b3Chris Banes        }
115550dfc33a565c4aefe6d5e844c93aa24a74cb80b3Chris Banes
115650dfc33a565c4aefe6d5e844c93aa24a74cb80b3Chris Banes        /**
115750dfc33a565c4aefe6d5e844c93aa24a74cb80b3Chris Banes         * Set the parallax scroll multiplier used in conjunction with
1158a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes         * {@link #COLLAPSE_MODE_PARALLAX}. A value of {@code 0.0} indicates no movement at all,
1159a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes         * {@code 1.0f} indicates normal scroll movement.
1160a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes         *
1161a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes         * @param multiplier the multiplier.
116250dfc33a565c4aefe6d5e844c93aa24a74cb80b3Chris Banes         *
116350dfc33a565c4aefe6d5e844c93aa24a74cb80b3Chris Banes         * @see #getParallaxMultiplier()
1164a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes         */
1165a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        public void setParallaxMultiplier(float multiplier) {
1166a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes            mParallaxMult = multiplier;
1167a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        }
116850dfc33a565c4aefe6d5e844c93aa24a74cb80b3Chris Banes
116950dfc33a565c4aefe6d5e844c93aa24a74cb80b3Chris Banes        /**
117050dfc33a565c4aefe6d5e844c93aa24a74cb80b3Chris Banes         * Returns the parallax scroll multiplier used in conjunction with
117150dfc33a565c4aefe6d5e844c93aa24a74cb80b3Chris Banes         * {@link #COLLAPSE_MODE_PARALLAX}.
117250dfc33a565c4aefe6d5e844c93aa24a74cb80b3Chris Banes         *
117350dfc33a565c4aefe6d5e844c93aa24a74cb80b3Chris Banes         * @see #setParallaxMultiplier(float)
117450dfc33a565c4aefe6d5e844c93aa24a74cb80b3Chris Banes         */
117550dfc33a565c4aefe6d5e844c93aa24a74cb80b3Chris Banes        public float getParallaxMultiplier() {
117650dfc33a565c4aefe6d5e844c93aa24a74cb80b3Chris Banes            return mParallaxMult;
117750dfc33a565c4aefe6d5e844c93aa24a74cb80b3Chris Banes        }
1178a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes    }
1179631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes
11806df5bb9903307734ed05a5135c7812fb9b6d43c8Chris Banes    /**
11816df5bb9903307734ed05a5135c7812fb9b6d43c8Chris Banes     * Show or hide the scrims if needed
11826df5bb9903307734ed05a5135c7812fb9b6d43c8Chris Banes     */
11836df5bb9903307734ed05a5135c7812fb9b6d43c8Chris Banes    final void updateScrimVisibility() {
11846df5bb9903307734ed05a5135c7812fb9b6d43c8Chris Banes        if (mContentScrim != null || mStatusBarScrim != null) {
11856df5bb9903307734ed05a5135c7812fb9b6d43c8Chris Banes            setScrimsShown(getHeight() + mCurrentOffset < getScrimVisibleHeightTrigger());
11866df5bb9903307734ed05a5135c7812fb9b6d43c8Chris Banes        }
11876df5bb9903307734ed05a5135c7812fb9b6d43c8Chris Banes    }
11886df5bb9903307734ed05a5135c7812fb9b6d43c8Chris Banes
1189631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes    private class OffsetUpdateListener implements AppBarLayout.OnOffsetChangedListener {
1190631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes        @Override
1191631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes        public void onOffsetChanged(AppBarLayout layout, int verticalOffset) {
11926ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes            mCurrentOffset = verticalOffset;
11936ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes
11946ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes            final int insetTop = mLastInsets != null ? mLastInsets.getSystemWindowInsetTop() : 0;
1195631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes
1196631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes            for (int i = 0, z = getChildCount(); i < z; i++) {
1197631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes                final View child = getChildAt(i);
1198631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes                final LayoutParams lp = (LayoutParams) child.getLayoutParams();
1199631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes                final ViewOffsetHelper offsetHelper = getViewOffsetHelper(child);
1200631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes
1201631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes                switch (lp.mCollapseMode) {
1202631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes                    case LayoutParams.COLLAPSE_MODE_PIN:
12036ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes                        if (getHeight() - insetTop + verticalOffset >= child.getHeight()) {
1204631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes                            offsetHelper.setTopAndBottomOffset(-verticalOffset);
1205631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes                        }
1206631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes                        break;
1207631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes                    case LayoutParams.COLLAPSE_MODE_PARALLAX:
1208631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes                        offsetHelper.setTopAndBottomOffset(
1209631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes                                Math.round(-verticalOffset * lp.mParallaxMult));
1210631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes                        break;
1211631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes                }
1212631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes            }
1213631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes
12146ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes            // Show or hide the scrims if needed
12156df5bb9903307734ed05a5135c7812fb9b6d43c8Chris Banes            updateScrimVisibility();
1216631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes
12176ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes            if (mStatusBarScrim != null && insetTop > 0) {
12186ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes                ViewCompat.postInvalidateOnAnimation(CollapsingToolbarLayout.this);
12196ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes            }
12206ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes
1221631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes            // Update the collapsing text's fraction
1222631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes            final int expandRange = getHeight() - ViewCompat.getMinimumHeight(
12236ba61c5c79fe025036593c9daf79cb65299bb0b6Chris Banes                    CollapsingToolbarLayout.this) - insetTop;
1224631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes            mCollapsingTextHelper.setExpansionFraction(
1225631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes                    Math.abs(verticalOffset) / (float) expandRange);
1226631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes        }
1227631f64ec9c6255f38a7f746d7949b6a537c1180fChris Banes    }
1228a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes}
1229