diff --git a/api/current.txt b/api/current.txt index 6d2e9bad6..b808dba65 100644 --- a/api/current.txt +++ b/api/current.txt @@ -432,12 +432,14 @@ package android.support.design.widget { method public boolean isCounterEnabled(); method public boolean isErrorEnabled(); method public boolean isHintAnimationEnabled(); + method public boolean isHintEnabled(); method public void setCounterEnabled(boolean); method public void setCounterMaxLength(int); method public void setError(java.lang.CharSequence); method public void setErrorEnabled(boolean); method public void setHint(java.lang.CharSequence); method public void setHintAnimationEnabled(boolean); + method public void setHintEnabled(boolean); method public void setHintTextAppearance(int); method public void setTypeface(android.graphics.Typeface); } diff --git a/res/values/attrs.xml b/res/values/attrs.xml index 0179ec7c8..3079180a8 100644 --- a/res/values/attrs.xml +++ b/res/values/attrs.xml @@ -162,6 +162,8 @@ + + diff --git a/src/android/support/design/widget/TextInputLayout.java b/src/android/support/design/widget/TextInputLayout.java index 402878cd7..162643e5d 100644 --- a/src/android/support/design/widget/TextInputLayout.java +++ b/src/android/support/design/widget/TextInputLayout.java @@ -61,6 +61,8 @@ public class TextInputLayout extends LinearLayout { private static final int INVALID_MAX_LENGTH = -1; private EditText mEditText; + + private boolean mHintEnabled; private CharSequence mHint; private Paint mTmpPaint; @@ -111,6 +113,7 @@ public class TextInputLayout extends LinearLayout { final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TextInputLayout, defStyleAttr, R.style.Widget_Design_TextInputLayout); + mHintEnabled = a.getBoolean(R.styleable.TextInputLayout_hintEnabled, true); setHint(a.getText(R.styleable.TextInputLayout_android_hint)); mHintAnimationEnabled = a.getBoolean( R.styleable.TextInputLayout_hintAnimationEnabled, true); @@ -198,7 +201,7 @@ public class TextInputLayout extends LinearLayout { mEditText.addTextChangedListener(new TextWatcher() { @Override public void afterTextChanged(Editable s) { - updateLabelVisibility(true); + updateLabelState(true); if (mCounterEnabled) { updateCounter(s.length()); } @@ -216,8 +219,8 @@ public class TextInputLayout extends LinearLayout { mDefaultTextColor = mEditText.getHintTextColors(); } - // If we do not have a valid hint, try and retrieve it from the EditText - if (TextUtils.isEmpty(mHint)) { + // If we do not have a valid hint, try and retrieve it from the EditText, if enabled + if (mHintEnabled && TextUtils.isEmpty(mHint)) { setHint(mEditText.getHint()); // Clear the EditText's hint as we will display it ourselves mEditText.setHint(null); @@ -232,7 +235,7 @@ public class TextInputLayout extends LinearLayout { } // Update the label visibility with no animation - updateLabelVisibility(false); + updateLabelState(false); } private LayoutParams updateEditTextMargin(ViewGroup.LayoutParams lp) { @@ -240,17 +243,21 @@ public class TextInputLayout extends LinearLayout { // to the EditText so make room for the label LayoutParams llp = lp instanceof LayoutParams ? (LayoutParams) lp : new LayoutParams(lp); - if (mTmpPaint == null) { - mTmpPaint = new Paint(); + if (mHintEnabled) { + if (mTmpPaint == null) { + mTmpPaint = new Paint(); + } + mTmpPaint.setTypeface(mCollapsingTextHelper.getCollapsedTypeface()); + mTmpPaint.setTextSize(mCollapsingTextHelper.getCollapsedTextSize()); + llp.topMargin = (int) -mTmpPaint.ascent(); + } else { + llp.topMargin = 0; } - mTmpPaint.setTypeface(mCollapsingTextHelper.getCollapsedTypeface()); - mTmpPaint.setTextSize(mCollapsingTextHelper.getCollapsedTextSize()); - llp.topMargin = (int) -mTmpPaint.ascent(); return llp; } - private void updateLabelVisibility(boolean animate) { + private void updateLabelState(boolean animate) { final boolean hasText = mEditText != null && !TextUtils.isEmpty(mEditText.getText()); final boolean isFocused = arrayContains(getDrawableState(), android.R.attr.state_focused); final boolean isErrorShowing = !TextUtils.isEmpty(getError()); @@ -287,25 +294,89 @@ public class TextInputLayout extends LinearLayout { } /** - * Set the hint to be displayed in the floating label + * Set the hint to be displayed in the floating label, if enabled. + * + * @see #setHintEnabled(boolean) * * @attr ref android.support.design.R.styleable#TextInputLayout_android_hint */ public void setHint(@Nullable CharSequence hint) { + if (mHintEnabled) { + setHintInternal(hint); + sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED); + } + } + + private void setHintInternal(CharSequence hint) { mHint = hint; mCollapsingTextHelper.setText(hint); - - sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED); } /** - * Returns the hint which is displayed in the floating label. + * Returns the hint which is displayed in the floating label, if enabled. + * + * @return the hint, or null if there isn't one set, or the hint is not enabled. * * @attr ref android.support.design.R.styleable#TextInputLayout_android_hint */ @Nullable public CharSequence getHint() { - return mHint; + return mHintEnabled ? mHint : null; + } + + /** + * Sets whether the floating label functionality is enabled or not in this layout. + * + *

If enabled, any non-empty hint in the child EditText will be moved into the floating + * hint, and its existing hint will be cleared. If disabled, then any non-empty floating hint + * in this layout will be moved into the EditText, and this layout's hint will be cleared.

+ * + * @see #setHint(CharSequence) + * @see #isHintEnabled() + * + * @attr ref android.support.design.R.styleable#TextInputLayout_hintEnabled + */ + public void setHintEnabled(boolean enabled) { + if (enabled != mHintEnabled) { + mHintEnabled = enabled; + + final CharSequence editTextHint = mEditText.getHint(); + if (!mHintEnabled) { + if (!TextUtils.isEmpty(mHint) && TextUtils.isEmpty(editTextHint)) { + // If the hint is disabled, but we have a hint set, and the EditText doesn't, + // pass it through... + mEditText.setHint(mHint); + } + // Now clear out any set hint + setHintInternal(null); + } else { + if (!TextUtils.isEmpty(editTextHint)) { + // If the hint is now enabled and the EditText has one set, we'll use it if + // we don't already have one, and clear the EditText's + if (TextUtils.isEmpty(mHint)) { + setHint(editTextHint); + } + mEditText.setHint(null); + } + } + + // Now update the EditText top margin + if (mEditText != null) { + final LayoutParams lp = updateEditTextMargin(mEditText.getLayoutParams()); + mEditText.setLayoutParams(lp); + } + } + } + + /** + * Returns whether the floating label functionality is enabled or not in this layout. + * + * @see #setHintEnabled(boolean) + * + * @attr ref android.support.design.R.styleable#TextInputLayout_hintEnabled + */ + public boolean isHintEnabled() { + return mHintEnabled; } /** @@ -318,7 +389,7 @@ public class TextInputLayout extends LinearLayout { mFocusedTextColor = ColorStateList.valueOf(mCollapsingTextHelper.getCollapsedTextColor()); if (mEditText != null) { - updateLabelVisibility(false); + updateLabelState(false); // Text size might have changed so update the top margin LayoutParams lp = updateEditTextMargin(mEditText.getLayoutParams()); @@ -442,7 +513,7 @@ public class TextInputLayout extends LinearLayout { // Set the EditText's background tint to the error color mErrorShown = true; updateEditTextBackground(); - updateLabelVisibility(true); + updateLabelState(true); } else { if (mErrorView.getVisibility() == VISIBLE) { ViewCompat.animate(mErrorView) @@ -454,7 +525,7 @@ public class TextInputLayout extends LinearLayout { public void onAnimationEnd(View view) { view.setVisibility(INVISIBLE); - updateLabelVisibility(true); + updateLabelState(true); } }).start(); @@ -547,7 +618,7 @@ public class TextInputLayout extends LinearLayout { length, mCounterMaxLength)); } if (mEditText != null && wasCounterOverflowed != mCounterOverflowed) { - updateLabelVisibility(false); + updateLabelState(false); updateEditTextBackground(); } } @@ -609,14 +680,17 @@ public class TextInputLayout extends LinearLayout { @Override public void draw(Canvas canvas) { super.draw(canvas); - mCollapsingTextHelper.draw(canvas); + + if (mHintEnabled) { + mCollapsingTextHelper.draw(canvas); + } } @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); - if (mEditText != null) { + if (mHintEnabled && mEditText != null) { final int l = mEditText.getLeft() + mEditText.getCompoundPaddingLeft(); final int r = mEditText.getRight() - mEditText.getCompoundPaddingRight(); @@ -637,7 +711,7 @@ public class TextInputLayout extends LinearLayout { public void refreshDrawableState() { super.refreshDrawableState(); // Drawable state has changed so see if we need to update the label - updateLabelVisibility(ViewCompat.isLaidOut(this)); + updateLabelState(ViewCompat.isLaidOut(this)); } private void collapseHint(boolean animate) {