TextInputLayout.java revision 388841ca2f07d0da9bbdc66c51abe789e05cf17b
1c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes/* 2c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes * Copyright (C) 2015 The Android Open Source Project 3c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes * 4c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes * Licensed under the Apache License, Version 2.0 (the "License"); 5c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes * you may not use this file except in compliance with the License. 6c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes * You may obtain a copy of the License at 7c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes * 8c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes * http://www.apache.org/licenses/LICENSE-2.0 9c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes * 10c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes * Unless required by applicable law or agreed to in writing, software 11c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes * distributed under the License is distributed on an "AS IS" BASIS, 12c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes * See the License for the specific language governing permissions and 14c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes * limitations under the License. 15c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes */ 16c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes 17c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banespackage android.support.design.widget; 18c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes 19c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banesimport android.content.Context; 20c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banesimport android.content.res.ColorStateList; 21c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banesimport android.content.res.TypedArray; 22c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banesimport android.graphics.Canvas; 23c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banesimport android.graphics.Color; 24c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banesimport android.graphics.Paint; 25388841ca2f07d0da9bbdc66c51abe789e05cf17bChris Banesimport android.graphics.Typeface; 26c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banesimport android.os.Handler; 27c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banesimport android.os.Message; 28c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banesimport android.support.design.R; 29c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banesimport android.support.v4.view.AccessibilityDelegateCompat; 30c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banesimport android.support.v4.view.ViewCompat; 31c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banesimport android.support.v4.view.ViewPropertyAnimatorListenerAdapter; 32c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banesimport android.support.v4.view.accessibility.AccessibilityNodeInfoCompat; 33c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banesimport android.text.Editable; 34c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banesimport android.text.TextUtils; 35c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banesimport android.text.TextWatcher; 36c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banesimport android.util.AttributeSet; 37c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banesimport android.util.TypedValue; 38c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banesimport android.view.Gravity; 39c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banesimport android.view.View; 40c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banesimport android.view.ViewGroup; 41c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banesimport android.view.accessibility.AccessibilityEvent; 42c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banesimport android.view.animation.AccelerateInterpolator; 43c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banesimport android.widget.EditText; 44c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banesimport android.widget.LinearLayout; 45c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banesimport android.widget.TextView; 46c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes 47c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes/** 489fb154338a62edc2c57dc036895199d6f1769400Chris Banes * Layout which wraps an {@link android.widget.EditText} (or descendant) to show a floating label 499fb154338a62edc2c57dc036895199d6f1769400Chris Banes * when the hint is hidden due to the user inputting text. 509fb154338a62edc2c57dc036895199d6f1769400Chris Banes * 519fb154338a62edc2c57dc036895199d6f1769400Chris Banes * Also supports showing an error via {@link #setErrorEnabled(boolean)} and 529fb154338a62edc2c57dc036895199d6f1769400Chris Banes * {@link #setError(CharSequence)}. 53c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes */ 54c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banespublic class TextInputLayout extends LinearLayout { 55c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes 56f44e88b81821e61a65886cc7027617ca8995070bChris Banes private static final int ANIMATION_DURATION = 200; 57c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes private static final int MSG_UPDATE_LABEL = 0; 58c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes 59c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes private EditText mEditText; 60c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes private CharSequence mHint; 61c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes 62c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes private boolean mErrorEnabled; 63c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes private TextView mErrorView; 64c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes private int mErrorTextAppearance; 65c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes 66c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes private ColorStateList mLabelTextColor; 67c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes 68c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes private final CollapsingTextHelper mCollapsingTextHelper; 69c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes private final Handler mHandler; 70c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes 71f44e88b81821e61a65886cc7027617ca8995070bChris Banes private ValueAnimatorCompat mAnimator; 72f44e88b81821e61a65886cc7027617ca8995070bChris Banes 73c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes public TextInputLayout(Context context) { 74c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes this(context, null); 75c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes } 76c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes 77c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes public TextInputLayout(Context context, AttributeSet attrs) { 7844dc3d86d8fa6544d49b2e14f89c9b1f49639dbdChris Banes super(context, attrs); 79c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes 80c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes setOrientation(VERTICAL); 81c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes setWillNotDraw(false); 82c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes 83c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes mCollapsingTextHelper = new CollapsingTextHelper(this); 84c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes mHandler = new Handler(new Handler.Callback() { 85c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes @Override 86c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes public boolean handleMessage(Message message) { 87c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes switch (message.what) { 88c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes case MSG_UPDATE_LABEL: 89c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes updateLabelVisibility(true); 90c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes return true; 91c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes } 92c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes return false; 93c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes } 94c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes }); 95c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes 96c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes mCollapsingTextHelper.setTextSizeInterpolator(AnimationUtils.FAST_OUT_SLOW_IN_INTERPOLATOR); 97c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes mCollapsingTextHelper.setPositionInterpolator(new AccelerateInterpolator()); 98c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes mCollapsingTextHelper.setCollapsedTextVerticalGravity(Gravity.TOP); 99c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes 100c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes final TypedArray a = context.obtainStyledAttributes(attrs, 10144dc3d86d8fa6544d49b2e14f89c9b1f49639dbdChris Banes R.styleable.TextInputLayout, 0, R.style.Widget_Design_TextInputLayout); 102c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes mHint = a.getText(R.styleable.TextInputLayout_android_hint); 103c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes 104c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes final int hintAppearance = a.getResourceId( 105c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes R.styleable.TextInputLayout_hintTextAppearance, -1); 106c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes if (hintAppearance != -1) { 107c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes mCollapsingTextHelper.setCollapsedTextAppearance(hintAppearance); 108c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes } 109c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes 110c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes mErrorTextAppearance = a.getResourceId(R.styleable.TextInputLayout_errorTextAppearance, 0); 111c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes final boolean errorEnabled = a.getBoolean(R.styleable.TextInputLayout_errorEnabled, false); 112c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes 113c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes // We create a ColorStateList using the specified text color, combining it with our 114c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes // theme's textColorHint 115c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes mLabelTextColor = createLabelTextColorStateList( 116c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes mCollapsingTextHelper.getCollapsedTextColor()); 117c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes 118c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes mCollapsingTextHelper.setCollapsedTextColor(mLabelTextColor.getDefaultColor()); 119c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes mCollapsingTextHelper.setExpandedTextColor(mLabelTextColor.getDefaultColor()); 120c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes 121c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes a.recycle(); 122c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes 123c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes if (errorEnabled) { 124c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes setErrorEnabled(true); 125c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes } 126c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes 127c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes if (ViewCompat.getImportantForAccessibility(this) 128c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes == ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_AUTO) { 129c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes // Make sure we're important for accessibility if we haven't been explicitly not 130c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes ViewCompat.setImportantForAccessibility(this, 131c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_YES); 132c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes } 133c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes 134c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes ViewCompat.setAccessibilityDelegate(this, new TextInputAccessibilityDelegate()); 135c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes } 136c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes 137c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes @Override 138c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes public void addView(View child, int index, ViewGroup.LayoutParams params) { 139c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes if (child instanceof EditText) { 140c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes params = setEditText((EditText) child, params); 141c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes super.addView(child, 0, params); 142c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes } else { 143c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes // Carry on adding the View... 144c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes super.addView(child, index, params); 145c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes } 146c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes } 147c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes 148388841ca2f07d0da9bbdc66c51abe789e05cf17bChris Banes /** 149388841ca2f07d0da9bbdc66c51abe789e05cf17bChris Banes * Set the typeface to use for the both the expanded and floating hint. 150388841ca2f07d0da9bbdc66c51abe789e05cf17bChris Banes * 151388841ca2f07d0da9bbdc66c51abe789e05cf17bChris Banes * @param typeface typeface to use, or {@code null} to use the default. 152388841ca2f07d0da9bbdc66c51abe789e05cf17bChris Banes */ 153388841ca2f07d0da9bbdc66c51abe789e05cf17bChris Banes public void setTypeface(Typeface typeface) { 154388841ca2f07d0da9bbdc66c51abe789e05cf17bChris Banes mCollapsingTextHelper.setTypeface(typeface); 155388841ca2f07d0da9bbdc66c51abe789e05cf17bChris Banes } 156388841ca2f07d0da9bbdc66c51abe789e05cf17bChris Banes 157c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes private LayoutParams setEditText(EditText editText, ViewGroup.LayoutParams lp) { 158c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes // If we already have an EditText, throw an exception 159c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes if (mEditText != null) { 160c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes throw new IllegalArgumentException("We already have an EditText, can only have one"); 161c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes } 162c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes mEditText = editText; 163c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes 164388841ca2f07d0da9bbdc66c51abe789e05cf17bChris Banes // Use the EditText's typeface, and it's text size for our expanded text 165388841ca2f07d0da9bbdc66c51abe789e05cf17bChris Banes mCollapsingTextHelper.setTypeface(mEditText.getTypeface()); 166c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes mCollapsingTextHelper.setExpandedTextSize(mEditText.getTextSize()); 167c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes 168c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes // Add a TextWatcher so that we know when the text input has changed 169c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes mEditText.addTextChangedListener(new TextWatcher() { 170c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes @Override 171c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes public void afterTextChanged(Editable s) { 172c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes mHandler.sendEmptyMessage(MSG_UPDATE_LABEL); 173c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes } 174c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes 175c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes @Override 176c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes public void beforeTextChanged(CharSequence s, int start, int count, int after) { 177c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes } 178c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes 179c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes @Override 180c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes public void onTextChanged(CharSequence s, int start, int before, int count) { 181c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes } 182c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes }); 183c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes 184c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes // Add focus listener to the EditText so that we can notify the label that it is activated. 185c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes // Allows the use of a ColorStateList for the text color on the label 186c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes mEditText.setOnFocusChangeListener(new OnFocusChangeListener() { 187c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes @Override 188c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes public void onFocusChange(View view, boolean focused) { 189c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes mHandler.sendEmptyMessage(MSG_UPDATE_LABEL); 190c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes } 191c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes }); 192c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes 193c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes // If we do not have a valid hint, try and retrieve it from the EditText 194c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes if (TextUtils.isEmpty(mHint)) { 195c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes setHint(mEditText.getHint()); 196c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes // Clear the EditText's hint as we will display it ourselves 197c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes mEditText.setHint(null); 198c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes } 199c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes 200c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes if (mErrorView != null) { 201c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes // Add some start/end padding to the error so that it matches the EditText 202c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes ViewCompat.setPaddingRelative(mErrorView, ViewCompat.getPaddingStart(mEditText), 203c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes 0, ViewCompat.getPaddingEnd(mEditText), mEditText.getPaddingBottom()); 204c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes } 205c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes 206c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes // Update the label visibility with no animation 207c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes updateLabelVisibility(false); 208c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes 209c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes // Create a new FrameLayout.LayoutParams so that we can add enough top margin 210c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes // to the EditText so make room for the label 211c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes LayoutParams newLp = new LayoutParams(lp); 212c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes Paint paint = new Paint(); 213388841ca2f07d0da9bbdc66c51abe789e05cf17bChris Banes paint.setTypeface(mCollapsingTextHelper.getTypeface()); 214c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes paint.setTextSize(mCollapsingTextHelper.getExpandedTextSize()); 215c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes newLp.topMargin = (int) -paint.ascent(); 216c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes 217c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes return newLp; 218c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes } 219c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes 220c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes private void updateLabelVisibility(boolean animate) { 221c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes boolean hasText = !TextUtils.isEmpty(mEditText.getText()); 222c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes boolean isFocused = mEditText.isFocused(); 223c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes 224c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes mCollapsingTextHelper.setCollapsedTextColor(mLabelTextColor.getColorForState( 225c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes isFocused ? FOCUSED_STATE_SET : EMPTY_STATE_SET, 226c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes mLabelTextColor.getDefaultColor())); 227c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes 228c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes if (hasText || isFocused) { 229c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes // We should be showing the label so do so if it isn't already 230c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes collapseHint(animate); 231c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes } else { 232c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes // We should not be showing the label so hide it 233c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes expandHint(animate); 234c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes } 235c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes } 236c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes 237c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes /** 238c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes * @return the {@link android.widget.EditText} text input 239c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes */ 240c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes public EditText getEditText() { 241c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes return mEditText; 242c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes } 243c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes 244c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes /** 245c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes * Set the hint to be displayed in the floating label 246c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes */ 247c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes public void setHint(CharSequence hint) { 248c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes mHint = hint; 249c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes mCollapsingTextHelper.setText(hint); 250c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes 251c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED); 252c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes } 253c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes 254c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes /** 255c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes * Whether the error functionality is enabled or not in this layout. Enabling this 256c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes * functionality before setting an error message via {@link #setError(CharSequence)}, will mean 257c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes * that this layout will not change size when an error is displayed. 258c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes */ 259c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes public void setErrorEnabled(boolean enabled) { 260c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes if (mErrorEnabled != enabled) { 261c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes if (enabled) { 262c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes mErrorView = new TextView(getContext()); 263c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes mErrorView.setTextAppearance(getContext(), mErrorTextAppearance); 264c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes mErrorView.setVisibility(INVISIBLE); 265c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes addView(mErrorView); 266c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes 267c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes if (mEditText != null) { 268c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes // Add some start/end padding to the error so that it matches the EditText 269c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes ViewCompat.setPaddingRelative(mErrorView, ViewCompat.getPaddingStart(mEditText), 270c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes 0, ViewCompat.getPaddingEnd(mEditText), mEditText.getPaddingBottom()); 271c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes } 272c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes } else { 273c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes removeView(mErrorView); 274c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes mErrorView = null; 275c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes } 276c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes mErrorEnabled = enabled; 277c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes } 278c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes } 279c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes 280c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes /** 281c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes * Sets an error message that will be displayed below our {@link EditText}. If the 282c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes * {@code error} is {@code null}, the error message will be cleared. 283c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes * <p> 284c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes * If the error functionality has not been enabled via {@link #setErrorEnabled(boolean)}, then 285c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes * it will be automatically enabled if {@code error} is not empty. 286c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes * 287c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes * @param error Error message to display, or null to clear 288c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes */ 289c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes public void setError(CharSequence error) { 290c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes if (!mErrorEnabled) { 291c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes if (TextUtils.isEmpty(error)) { 292c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes // If error isn't enabled, and the error is empty, just return 293c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes return; 294c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes } 295c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes // Else, we'll assume that they want to enable the error functionality 296c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes setErrorEnabled(true); 297c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes } 298c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes 299c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes if (!TextUtils.isEmpty(error)) { 300c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes mErrorView.setText(error); 301c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes mErrorView.setVisibility(VISIBLE); 302c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes ViewCompat.setAlpha(mErrorView, 0f); 303c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes ViewCompat.animate(mErrorView) 304c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes .alpha(1f) 305c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes .setDuration(ANIMATION_DURATION) 306c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes .setInterpolator(AnimationUtils.FAST_OUT_SLOW_IN_INTERPOLATOR) 307c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes .setListener(null) 308c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes .start(); 309c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes } else { 310c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes if (mErrorView.getVisibility() == VISIBLE) { 311c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes ViewCompat.animate(mErrorView) 312c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes .alpha(0f) 313c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes .setDuration(ANIMATION_DURATION) 314c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes .setInterpolator(AnimationUtils.FAST_OUT_SLOW_IN_INTERPOLATOR) 315c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes .setListener(new ViewPropertyAnimatorListenerAdapter() { 316c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes @Override 317c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes public void onAnimationEnd(View view) { 318c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes mErrorView.setText(null); 319c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes mErrorView.setVisibility(INVISIBLE); 320c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes } 321c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes }).start(); 322c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes } 323c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes } 324c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes 325c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED); 326c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes } 327c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes 328c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes @Override 329c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes public void draw(Canvas canvas) { 330c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes super.draw(canvas); 331c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes mCollapsingTextHelper.draw(canvas); 332c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes } 333c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes 334c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes @Override 335c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 336c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes super.onLayout(changed, left, top, right, bottom); 337c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes 338c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes mCollapsingTextHelper.onLayout(changed, left, top, right, bottom); 339c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes 340c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes if (mEditText != null) { 341a611711d69eaf8ba65af12118a96810fc17b4163Chris Banes final int l = mEditText.getLeft() + mEditText.getCompoundPaddingLeft(); 342a611711d69eaf8ba65af12118a96810fc17b4163Chris Banes final int r = mEditText.getRight() - mEditText.getCompoundPaddingRight(); 343c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes 344c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes mCollapsingTextHelper.setExpandedBounds(l, 345a611711d69eaf8ba65af12118a96810fc17b4163Chris Banes mEditText.getTop() + mEditText.getCompoundPaddingTop(), 346a611711d69eaf8ba65af12118a96810fc17b4163Chris Banes r, mEditText.getBottom() - mEditText.getCompoundPaddingBottom()); 347c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes 348c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes // Set the collapsed bounds to be the the full height (minus padding) to match the 349c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes // EditText's editable area 350c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes mCollapsingTextHelper.setCollapsedBounds(l, getPaddingTop(), 351c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes r, bottom - top - getPaddingBottom()); 352c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes } 353c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes } 354c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes 355c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes private void collapseHint(boolean animate) { 356c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes if (animate) { 357c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes animateToExpansionFraction(1f); 358c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes } else { 359c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes mCollapsingTextHelper.setExpansionFraction(1f); 360c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes } 361c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes } 362c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes 363c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes private void expandHint(boolean animate) { 364c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes if (animate) { 365c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes animateToExpansionFraction(0f); 366c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes } else { 367c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes mCollapsingTextHelper.setExpansionFraction(0f); 368c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes } 369c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes } 370c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes 371c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes private void animateToExpansionFraction(final float target) { 372f44e88b81821e61a65886cc7027617ca8995070bChris Banes if (mAnimator == null) { 373f44e88b81821e61a65886cc7027617ca8995070bChris Banes mAnimator = ViewUtils.createAnimator(); 374f44e88b81821e61a65886cc7027617ca8995070bChris Banes mAnimator.setInterpolator(AnimationUtils.LINEAR_INTERPOLATOR); 375f44e88b81821e61a65886cc7027617ca8995070bChris Banes mAnimator.setDuration(ANIMATION_DURATION); 376f44e88b81821e61a65886cc7027617ca8995070bChris Banes mAnimator.setUpdateListener(new ValueAnimatorCompat.AnimatorUpdateListener() { 377f44e88b81821e61a65886cc7027617ca8995070bChris Banes @Override 378f44e88b81821e61a65886cc7027617ca8995070bChris Banes public void onAnimationUpdate(ValueAnimatorCompat animator) { 379f44e88b81821e61a65886cc7027617ca8995070bChris Banes mCollapsingTextHelper.setExpansionFraction(animator.getAnimatedFloatValue()); 380f44e88b81821e61a65886cc7027617ca8995070bChris Banes } 381f44e88b81821e61a65886cc7027617ca8995070bChris Banes }); 382f44e88b81821e61a65886cc7027617ca8995070bChris Banes } else if (mAnimator.isRunning()) { 383f44e88b81821e61a65886cc7027617ca8995070bChris Banes mAnimator.cancel(); 384f44e88b81821e61a65886cc7027617ca8995070bChris Banes } 385c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes 386f44e88b81821e61a65886cc7027617ca8995070bChris Banes mAnimator.setFloatValues(mCollapsingTextHelper.getExpansionFraction(), target); 387f44e88b81821e61a65886cc7027617ca8995070bChris Banes mAnimator.start(); 388c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes } 389c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes 390c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes private ColorStateList createLabelTextColorStateList(int color) { 391c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes final int[][] states = new int[2][]; 392c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes final int[] colors = new int[2]; 393c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes int i = 0; 394c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes 395c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes // Focused 396c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes states[i] = FOCUSED_STATE_SET; 397c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes colors[i] = color; 398c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes i++; 399c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes 400c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes states[i] = EMPTY_STATE_SET; 401c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes colors[i] = getThemeAttrColor(android.R.attr.textColorHint); 402c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes i++; 403c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes 404c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes return new ColorStateList(states, colors); 405c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes } 406c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes 407c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes private int getThemeAttrColor(int attr) { 408c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes TypedValue tv = new TypedValue(); 409c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes if (getContext().getTheme().resolveAttribute(attr, tv, true)) { 410c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes return tv.data; 411c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes } else { 412c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes return Color.MAGENTA; 413c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes } 414c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes } 415c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes 416c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes private class TextInputAccessibilityDelegate extends AccessibilityDelegateCompat { 417c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes @Override 418c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) { 419c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes super.onInitializeAccessibilityEvent(host, event); 420c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes event.setClassName(TextInputLayout.class.getSimpleName()); 421c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes } 422c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes 423c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes @Override 424c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) { 425c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes super.onPopulateAccessibilityEvent(host, event); 426c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes 427c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes final CharSequence text = mCollapsingTextHelper.getText(); 428c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes if (!TextUtils.isEmpty(text)) { 429c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes event.getText().add(text); 430c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes } 431c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes } 432c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes 433c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes @Override 434c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfoCompat info) { 435c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes super.onInitializeAccessibilityNodeInfo(host, info); 436c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes info.setClassName(TextInputLayout.class.getSimpleName()); 437c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes 438c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes final CharSequence text = mCollapsingTextHelper.getText(); 439c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes if (!TextUtils.isEmpty(text)) { 440c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes info.setText(text); 441c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes } 442c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes if (mEditText != null) { 443c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes info.setLabelFor(mEditText); 444c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes } 445c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes final CharSequence error = mErrorView != null ? mErrorView.getText() : null; 446c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes if (!TextUtils.isEmpty(error)) { 447c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes info.setContentInvalid(true); 448c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes info.setError(error); 449c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes } 450c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes } 451c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes } 452c5b63021dfda1dd155775a0b4845c5ca3c70b1b0Chris Banes}