Improve typeface support in the collapsing text widgets

We now handle the collapsed and expanded typefaces
seperately and use them in the appropriate places.
The switch between them is pretty jarring but there's
not much we can do about that, plus most of them time you
should be using the same typeface for both.

BUG: 23882300
Change-Id: If4efee87169472d61bdee98dbada0c120d8830bf
diff --git a/design/api/current.txt b/design/api/current.txt
index 2506089..fa68cc7 100644
--- a/design/api/current.txt
+++ b/design/api/current.txt
@@ -72,20 +72,24 @@
     ctor public CollapsingToolbarLayout(android.content.Context, android.util.AttributeSet);
     ctor public CollapsingToolbarLayout(android.content.Context, android.util.AttributeSet, int);
     method public int getCollapsedTitleGravity();
+    method public android.graphics.Typeface getCollapsedTitleTypeface();
     method public android.graphics.drawable.Drawable getContentScrim();
     method public int getExpandedTitleGravity();
+    method public android.graphics.Typeface getExpandedTitleTypeface();
     method public android.graphics.drawable.Drawable getStatusBarScrim();
     method public java.lang.CharSequence getTitle();
     method public boolean isTitleEnabled();
     method public void setCollapsedTitleGravity(int);
     method public void setCollapsedTitleTextAppearance(int);
     method public void setCollapsedTitleTextColor(int);
+    method public void setCollapsedTitleTypeface(android.graphics.Typeface);
     method public void setContentScrim(android.graphics.drawable.Drawable);
     method public void setContentScrimColor(int);
     method public void setContentScrimResource(int);
     method public void setExpandedTitleColor(int);
     method public void setExpandedTitleGravity(int);
     method public void setExpandedTitleTextAppearance(int);
+    method public void setExpandedTitleTypeface(android.graphics.Typeface);
     method public void setScrimsShown(boolean);
     method public void setScrimsShown(boolean, boolean);
     method public void setStatusBarScrim(android.graphics.drawable.Drawable);
@@ -367,6 +371,7 @@
     method public android.widget.EditText getEditText();
     method public java.lang.CharSequence getError();
     method public java.lang.CharSequence getHint();
+    method public android.graphics.Typeface getTypeface();
     method public boolean isErrorEnabled();
     method public boolean isHintAnimationEnabled();
     method public void setError(java.lang.CharSequence);
diff --git a/design/src/android/support/design/widget/CollapsingTextHelper.java b/design/src/android/support/design/widget/CollapsingTextHelper.java
index 9dc60d4..0375e01 100644
--- a/design/src/android/support/design/widget/CollapsingTextHelper.java
+++ b/design/src/android/support/design/widget/CollapsingTextHelper.java
@@ -72,6 +72,9 @@
     private float mCollapsedDrawX;
     private float mCurrentDrawX;
     private float mCurrentDrawY;
+    private Typeface mCollapsedTypeface;
+    private Typeface mExpandedTypeface;
+    private Typeface mCurrentTypeface;
 
     private CharSequence mText;
     private CharSequence mTextToDraw;
@@ -207,6 +210,10 @@
         mCollapsedShadowRadius = a.getFloat(R.styleable.TextAppearance_android_shadowRadius, 0);
         a.recycle();
 
+        if (Build.VERSION.SDK_INT >= 16) {
+            mCollapsedTypeface = readFontFamilyTypeface(resId);
+        }
+
         recalculate();
     }
 
@@ -226,21 +233,52 @@
         mExpandedShadowRadius = a.getFloat(R.styleable.TextAppearance_android_shadowRadius, 0);
         a.recycle();
 
+        if (Build.VERSION.SDK_INT >= 16) {
+            mExpandedTypeface = readFontFamilyTypeface(resId);
+        }
+
         recalculate();
     }
 
-    void setTypeface(Typeface typeface) {
-        if (typeface == null) {
-            typeface = Typeface.DEFAULT;
+    private Typeface readFontFamilyTypeface(int resId) {
+        final TypedArray a = mView.getContext().obtainStyledAttributes(resId,
+                new int[]{android.R.attr.fontFamily});
+        try {
+            final String family = a.getString(0);
+            if (family != null) {
+                return Typeface.create(family, Typeface.NORMAL);
+            }
+        } finally {
+            a.recycle();
         }
-        if (mTextPaint.getTypeface() != typeface) {
-            mTextPaint.setTypeface(typeface);
+        return null;
+    }
+
+    void setCollapsedTypeface(Typeface typeface) {
+        if (mCollapsedTypeface != typeface) {
+            mCollapsedTypeface = typeface;
             recalculate();
         }
     }
 
-    Typeface getTypeface() {
-        return mTextPaint.getTypeface();
+    void setExpandedTypeface(Typeface typeface) {
+        if (mExpandedTypeface != typeface) {
+            mExpandedTypeface = typeface;
+            recalculate();
+        }
+    }
+
+    void setTypefaces(Typeface typeface) {
+        mCollapsedTypeface = mExpandedTypeface = typeface;
+        recalculate();
+    }
+
+    Typeface getCollapsedTypeface() {
+        return mCollapsedTypeface != null ? mCollapsedTypeface : Typeface.DEFAULT;
+    }
+
+    Typeface getExpandedTypeface() {
+        return mExpandedTypeface != null ? mExpandedTypeface : Typeface.DEFAULT;
     }
 
     /**
@@ -305,6 +343,7 @@
     private void calculateBaseOffsets() {
         // We then calculate the collapsed text size, using the same logic
         mTextPaint.setTextSize(mCollapsedTextSize);
+        mTextPaint.setTypeface(mCollapsedTypeface);
         float width = mTextToDraw != null ?
                 mTextPaint.measureText(mTextToDraw, 0, mTextToDraw.length()) : 0;
         final int collapsedAbsGravity = GravityCompat.getAbsoluteGravity(mCollapsedTextGravity,
@@ -337,6 +376,7 @@
         }
 
         mTextPaint.setTextSize(mExpandedTextSize);
+        mTextPaint.setTypeface(mExpandedTypeface);
         width = mTextToDraw != null
                 ? mTextPaint.measureText(mTextToDraw, 0, mTextToDraw.length()) : 0;
         final int expandedAbsGravity = GravityCompat.getAbsoluteGravity(mExpandedTextGravity,
@@ -450,9 +490,17 @@
             availableWidth = mCollapsedBounds.width();
             newTextSize = mCollapsedTextSize;
             mScale = 1f;
+            if (mCurrentTypeface != mCollapsedTypeface) {
+                mCurrentTypeface = mCollapsedTypeface;
+                updateDrawText = true;
+            }
         } else {
             availableWidth = mExpandedBounds.width();
             newTextSize = mExpandedTextSize;
+            if (mCurrentTypeface != mExpandedTypeface) {
+                mCurrentTypeface = mExpandedTypeface;
+                updateDrawText = true;
+            }
 
             if (isClose(textSize, mExpandedTextSize)) {
                 // If we're close to the expanded text size, snap to it and use a scale of 1
@@ -464,13 +512,14 @@
         }
 
         if (availableWidth > 0) {
-            updateDrawText = (mCurrentTextSize != newTextSize) || mBoundsChanged;
+            updateDrawText = (mCurrentTextSize != newTextSize) || mBoundsChanged || updateDrawText;
             mCurrentTextSize = newTextSize;
             mBoundsChanged = false;
         }
 
         if (mTextToDraw == null || updateDrawText) {
             mTextPaint.setTextSize(mCurrentTextSize);
+            mTextPaint.setTypeface(mCurrentTypeface);
 
             // If we don't currently have text to draw, or the text size has changed, ellipsize...
             final CharSequence title = TextUtils.ellipsize(mText, mTextPaint,
diff --git a/design/src/android/support/design/widget/CollapsingToolbarLayout.java b/design/src/android/support/design/widget/CollapsingToolbarLayout.java
index 3f5382e..1844034 100644
--- a/design/src/android/support/design/widget/CollapsingToolbarLayout.java
+++ b/design/src/android/support/design/widget/CollapsingToolbarLayout.java
@@ -20,12 +20,14 @@
 import android.content.res.TypedArray;
 import android.graphics.Canvas;
 import android.graphics.Rect;
+import android.graphics.Typeface;
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
 import android.os.Build;
 import android.support.annotation.ColorInt;
 import android.support.annotation.DrawableRes;
 import android.support.annotation.IntDef;
+import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
 import android.support.annotation.StyleRes;
 import android.support.design.R;
@@ -731,6 +733,40 @@
     }
 
     /**
+     * Set the typeface to use for the collapsed title.
+     *
+     * @param typeface typeface to use, or {@code null} to use the default.
+     */
+    public void setCollapsedTitleTypeface(@Nullable Typeface typeface) {
+        mCollapsingTextHelper.setCollapsedTypeface(typeface);
+    }
+
+    /**
+     * Returns the typeface used for the collapsed title.
+     */
+    @NonNull
+    public Typeface getCollapsedTitleTypeface() {
+        return mCollapsingTextHelper.getCollapsedTypeface();
+    }
+
+    /**
+     * Set the typeface to use for the expanded title.
+     *
+     * @param typeface typeface to use, or {@code null} to use the default.
+     */
+    public void setExpandedTitleTypeface(@Nullable Typeface typeface) {
+        mCollapsingTextHelper.setExpandedTypeface(typeface);
+    }
+
+    /**
+     * Returns the typeface used for the expanded title.
+     */
+    @NonNull
+    public Typeface getExpandedTitleTypeface() {
+        return mCollapsingTextHelper.getExpandedTypeface();
+    }
+
+    /**
      * The additional offset used to define when to trigger the scrim visibility change.
      */
     final int getScrimTriggerOffset() {
diff --git a/design/src/android/support/design/widget/TextInputLayout.java b/design/src/android/support/design/widget/TextInputLayout.java
index 3fb8b65..bbeadee 100644
--- a/design/src/android/support/design/widget/TextInputLayout.java
+++ b/design/src/android/support/design/widget/TextInputLayout.java
@@ -23,6 +23,7 @@
 import android.graphics.Color;
 import android.graphics.Paint;
 import android.graphics.Typeface;
+import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
 import android.support.annotation.StyleRes;
 import android.support.design.R;
@@ -142,12 +143,21 @@
     }
 
     /**
-     * Set the typeface to use for the both the expanded and floating hint.
+     * Set the typeface to use for both the expanded and floating hint.
      *
      * @param typeface typeface to use, or {@code null} to use the default.
      */
     public void setTypeface(@Nullable Typeface typeface) {
-        mCollapsingTextHelper.setTypeface(typeface);
+        mCollapsingTextHelper.setTypefaces(typeface);
+    }
+
+    /**
+     * Returns the typeface used for both the expanded and floating hint.
+     */
+    @NonNull
+    public Typeface getTypeface() {
+        // This could be either the collapsed or expanded
+        return mCollapsingTextHelper.getCollapsedTypeface();
     }
 
     private void setEditText(EditText editText) {
@@ -158,7 +168,7 @@
         mEditText = editText;
 
         // Use the EditText's typeface, and it's text size for our expanded text
-        mCollapsingTextHelper.setTypeface(mEditText.getTypeface());
+        mCollapsingTextHelper.setTypefaces(mEditText.getTypeface());
         mCollapsingTextHelper.setExpandedTextSize(mEditText.getTextSize());
         mCollapsingTextHelper.setExpandedTextGravity(mEditText.getGravity());
 
@@ -206,7 +216,7 @@
         if (mTmpPaint == null) {
             mTmpPaint = new Paint();
         }
-        mTmpPaint.setTypeface(mCollapsingTextHelper.getTypeface());
+        mTmpPaint.setTypeface(mCollapsingTextHelper.getCollapsedTypeface());
         mTmpPaint.setTextSize(mCollapsingTextHelper.getCollapsedTextSize());
         llp.topMargin = (int) -mTmpPaint.ascent();