morristech
9/11/2017 - 11:36 AM

Material Design - Text field input - Over/under character or word count (android.support.design.widget.TextInputLayout) http://www.google.co

Material Design - Text field input - Over/under character or word count (android.support.design.widget.TextInputLayout) http://www.google.com/design/spec/patterns/errors.html#errors-user-input-errors

import android.graphics.Color;
import android.support.design.widget.TextInputLayout;
import android.text.Editable;
import android.text.Layout;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.TextWatcher;
import android.text.style.AlignmentSpan;
import android.text.style.ForegroundColorSpan;


/**
 * Material Design Guidlines:
 * http://www.google.com/design/spec/patterns/errors.html#errors-user-input-errors
 * see section headed "Text field input - Over/under character or word count"
 *
 * @author Simon Lightfoot <simon@demondevelopers.com>
 */
public class CharacterCountErrorWatcher
	implements TextWatcher
{
	private final TextInputLayout mTextInputLayout;
	private final ForegroundColorSpan mNormalTextAppearance;
	private final AlignmentSpan mAlignmentSpan = new AlignmentSpan.Standard(Layout.Alignment.ALIGN_OPPOSITE);
	private final SpannableStringBuilder mErrorText = new SpannableStringBuilder();
	private int mMinLen;
	private int mMaxLen;

	public CharacterCountErrorWatcher(TextInputLayout textInputLayout, int minLen, int maxLen)
	{
		mTextInputLayout = textInputLayout;
		mNormalTextAppearance = new ForegroundColorSpan(Color.GRAY);
		mMinLen = minLen;
		mMaxLen = maxLen;
		updateErrorText();
	}

	private void updateErrorText()
	{
		mErrorText.clear();
		mErrorText.clearSpans();
		final int length = mTextInputLayout.getEditText().length();
		if(length > 0){
			mErrorText.append(String.valueOf(length));
			mErrorText.append(" / ");
			mErrorText.append(String.valueOf(mMaxLen));
			mErrorText.setSpan(mAlignmentSpan, 0, mErrorText.length(),
				Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
			if(hasValidLength()){
				mErrorText.setSpan(mNormalTextAppearance, 0, mErrorText.length(),
					Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
			}
		}
		mTextInputLayout.setError(mErrorText);
	}

	public boolean hasValidLength()
	{
		final int length = mTextInputLayout.getEditText().length();
		return (length >= mMinLen && length <= mMaxLen);
	}

	@Override
	public void afterTextChanged(Editable s)
	{
		updateErrorText();
	}

	@Override
	public void beforeTextChanged(CharSequence s, int start, int count, int after)
	{
		//
	}

	@Override
	public void onTextChanged(CharSequence s, int start, int before, int count)
	{
		//
	}
}
import android.os.Bundle;
import android.support.design.widget.TextInputLayout;
import android.support.v7.app.AppCompatActivity;


public class TestActivity extends AppCompatActivity
{
	@Override
	protected void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_test);

		TextInputLayout text1 = (TextInputLayout) findViewById(R.id.text1);
		TextInputLayout text2 = (TextInputLayout) findViewById(R.id.text2);

		text1.getEditText().addTextChangedListener(new CharacterCountErrorWatcher(text1, 0, 10));
		text2.getEditText().addTextChangedListener(new CharacterCountErrorWatcher(text2, 5, 10));
	}
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
	xmlns:app="http://schemas.android.com/apk/res-auto"
	android:layout_width="match_parent"
	android:layout_height="match_parent"
	android:orientation="vertical"
	android:padding="24dp"
	>

	<android.support.design.widget.TextInputLayout
		android:id="@+id/text1"
		android:layout_width="match_parent"
		android:layout_height="wrap_content"
		android:orientation="vertical"
		>
		<EditText
			android:layout_width="match_parent"
			android:layout_height="wrap_content"
			android:hint="Text Hint 1"
			android:singleLine="true"
			/>
	</android.support.design.widget.TextInputLayout>
	<android.support.design.widget.TextInputLayout
		android:id="@+id/text2"
		android:layout_width="match_parent"
		android:layout_height="wrap_content"
		android:orientation="vertical"
		>
		<EditText
			android:id="@+id/text"
			android:layout_width="match_parent"
			android:layout_height="wrap_content"
			android:hint="Text Hint 2"
			/>
	</android.support.design.widget.TextInputLayout>
</LinearLayout>