Changing tint color of Android EditText programmatically

后端 未结 5 669
孤城傲影
孤城傲影 2021-02-03 22:07

I am trying to change the tinting color of an EditText View programmatically during runtime. Basically i want to change what you would usually apply as ?attr/

5条回答
  •  粉色の甜心
    2021-02-03 22:38

    I wrote a small component to achieve this behavior.

    Few important notes:

    • Old school setColorFilter method is used
    • To make tint work, first switch focus to other view, then tint EditText background drawable

    Usage

    ErrorLabelLayout layoutPassError = (ErrorLabelLayout) findViewById(R.id.layoutPasswordError)
    layoutPassError.setError("Password_is_wrong");
    // when you want to clear error e.g. in on text changed method
    layoutPassError.clearError();
    

    XML

    
    
        
    
    

    Source

    public class ErrorLabelLayout extends LinearLayout implements ViewGroup.OnHierarchyChangeListener {
    
        private static final int ERROR_LABEL_TEXT_SIZE = 12;
        private static final int ERROR_LABEL_PADDING = 4;
    
        private TextView mErrorLabel;
        private Drawable mDrawable;
        private int mErrorColor;
    
        public ErrorLabelLayout(Context context) {
            super(context);
            initView();
        }
    
        public ErrorLabelLayout(Context context, AttributeSet attrs) {
            super(context, attrs);
            initView();
        }
    
        public ErrorLabelLayout(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            initView();
        }
    
        private void initView() {
            setOnHierarchyChangeListener(this);
            setOrientation(VERTICAL);
            mErrorColor = Color.parseColor("#D32F2F");
            initErrorLabel();
        }
    
        private void initErrorLabel() {
            mErrorLabel = new TextView(getContext());
            mErrorLabel.setFocusable(true);
            mErrorLabel.setFocusableInTouchMode(true);
            mErrorLabel.setTextSize(ERROR_LABEL_TEXT_SIZE);
            mErrorLabel.setTextColor(mErrorColor);
            mErrorLabel.setPadding(dipsToPix(ERROR_LABEL_PADDING), 0, dipsToPix(ERROR_LABEL_PADDING), 0);
        }
    
        public void setErrorColor(int color) {
            mErrorColor = color;
            mErrorLabel.setTextColor(mErrorColor);
        }
    
        public void clearError() {
            mErrorLabel.setVisibility(INVISIBLE);
            mDrawable.clearColorFilter();
        }
    
        public void setError(String text) {
            mErrorLabel.setVisibility(VISIBLE);
            mErrorLabel.setText(text);
            // changing focus from EditText to error label, necessary for Android L only
            // EditText background Drawable is not tinted, until EditText remains focus
            mErrorLabel.requestFocus();
            // tint drawable
            mDrawable.setColorFilter(mErrorColor, PorterDuff.Mode.SRC_ATOP);
        }
    
        @Override
        public void onChildViewAdded(View parent, View child) {
            int childCount = getChildCount();
            if (childCount == 1) {
                mDrawable = getChildAt(0).getBackground();
                addView(mErrorLabel);
            }
        }
    
        @Override
        public void onChildViewRemoved(View parent, View child) {
        }
    
        private int dipsToPix(float dps) {
            return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
                    dps, getResources().getDisplayMetrics());
        }
    }
    

    Tested on API 16 / 21 with com.android.support:appcompat-v7:22.1.1 library.

提交回复
热议问题