Skip to content

Instantly share code, notes, and snippets.

@dmytrodanylyk
Created January 21, 2015 15:35
Show Gist options
  • Star 34 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save dmytrodanylyk/d0c0f93c305e6879ec12 to your computer and use it in GitHub Desktop.
Save dmytrodanylyk/d0c0f93c305e6879ec12 to your computer and use it in GitHub Desktop.
Android Error Label
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center_horizontal"
android:padding="16dp">
<com.dd.ui.view.ErrorLabelLayout
android:id="@+id/nameErrorLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:id="@+id/editFirsName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="First name"/>
</com.dd.ui.view.ErrorLabelLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="horizontal">
<Button
android:id="@+id/btnError"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="8dp"
android:text="Show error"/>
<Button
android:id="@+id/btnClear"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:text="Clear error"/>
</LinearLayout>
</LinearLayout>
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);
// tint drawable
mDrawable.setColorFilter(mErrorColor, PorterDuff.Mode.SRC_ATOP);
// changing focus from EditText to error label, necessary for Android L only
// EditText background Drawable is not tinted, until EditText remains focus
mErrorLabel.requestFocus();
}
@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());
}
}
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final ErrorLabelLayout errorLabelLayout = (ErrorLabelLayout) findViewById(R.id.nameErrorLayout);
Button btnError = (Button) findViewById(R.id.btnError);
btnError.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
errorLabelLayout.setError("First name is required");
}
});
Button btnClear = (Button) findViewById(R.id.btnClear);
btnClear.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
errorLabelLayout.clearError();
}
});
// whenever user click on edit text - remove error
EditText editFirsName = (EditText) findViewById(R.id.editFirsName);
editFirsName.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_UP:
errorLabelLayout.clearError();
break;
}
return false;
}
});
}
}
@Yougin
Copy link

Yougin commented Feb 19, 2015

Very nice tutorial and gist! I'm only wondering if you care about state saving? I'm not sure if your instance variables are restored automatically on configuration change.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment