TextInputLayout: Different color for hint label when not focused

前端 未结 1 490
被撕碎了的回忆
被撕碎了的回忆 2021-02-04 07:53

What I want to do:

When using an EditText embedded in a TextInputLayout I want to ...

  1. Set the Color of the label to GREEN when it\'s de-focu
相关标签:
1条回答
  • 2021-02-04 08:35

    I had a similar problem: I needed to implement a text input layout in which the label has different colours for empty (when there is no text entered in the edit text), "filled" and focused state. My main problem was how to differentiate between the empty and the filled state as setting a different colour for the focused state was already easy using selectors. In the end I decided to define a custom "empty text" state and implement my custom text input layout (which extends the normal text input layout).

    Here is some code:

    In res/values/attrs.xml:

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
    
    ...
    
        <!-- Custom state for the text input layout to determine whether the label is shown above some text or not -->
        <declare-styleable name="EmptyTextState">
            <attr name="state_empty_text" format="boolean"/>
        </declare-styleable>
    
    </resources>
    

    The custom text input layout:

    public class EmptyStateTextInputLayout extends TextInputLayout {
        private boolean emptyText = true;
        private static final int[] EMPTY_TEXT_STATE = new int[]{R.attr.state_empty_text};
    
        public EmptyStateTextInputLayout(Context context) {
            super(context);
        }
    
        public EmptyStateTextInputLayout(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
    
        public EmptyStateTextInputLayout(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
        }
    
        @Override
        protected int[] onCreateDrawableState(int extraSpace) {
            int[] state = super.onCreateDrawableState(extraSpace + 1);
            if (emptyText) {
                mergeDrawableStates(state, EMPTY_TEXT_STATE);
            }
            return state;
        }
    
        public void setEmptyTextState(boolean emptyTextState) {
            this.emptyText = emptyTextState;
            refreshDrawableState();
        }
    
        @Override
        public void addView(View child, int index, ViewGroup.LayoutParams params) {
            if (child instanceof EditText) {
                EditText editText = (EditText) child;
                if (!TextUtils.isEmpty(editText.getText())) {
                    setEmptyTextState(false);
                }
                editText.addTextChangedListener(new TextWatcher() {
                    @Override
                    public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
    
                    }
    
                    @Override
                    public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
    
                    }
    
                    @Override
                    public void afterTextChanged(Editable editable) {
                        if (!TextUtils.isEmpty(editable)) {
                            setEmptyTextState(false);
                        } else {
                            setEmptyTextState(true);
                        }
                    }
                });
            }
            super.addView(child, index, params);
        }
    }
    

    XML selector to set the colour of label in different states (res/color/input_field_floating_label.xml):

    <?xml version="1.0" encoding="utf-8"?>
    <selector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto">
        <item android:color="@color/focused_text_color" android:state_focused="true" />
        <item android:color="@color/placeholder_color" app:state_empty_text="true"/>
        <item android:color="@color/primary_text_color"/> <!-- default color -->
    </selector>
    

    Style for the input text layout (in res/values/styles.xml):

    <style name="EditTextLayout">
        ...
        <item name="android:textColorHint">@color/input_field_floating_label</item>
    </style>
    

    Theme and style for the edit text (still in res/values/styles.xml):

    <style name="EditTextTheme">
        ...
        <item name="android:textColorHint">@color/input_field_floating_label</item>
    </style>
    
    <style name="EditText">
        <item name="android:theme">@style/EditTextTheme</item>
        ...
    </style>
    

    Usage:

    <com.package.path.widget.EmptyStateTextInputLayout
                style="@style/DarkEditTextLayout"
                android:layout_height="wrap_content"
                android:layout_width="match_parent"
                ...
                >
    
                <EditText
                    style="@style/EditText"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content" />
    </com.package.path.widget.EmptyStateTextInputLayout>
    

    I recommend this blog post to get an idea of working with custom states: http://code.neenbedankt.com/example-of-custom-states-in-android-components/

    0 讨论(0)
提交回复
热议问题