Created
January 21, 2015 15:35
-
-
Save dmytrodanylyk/d0c0f93c305e6879ec12 to your computer and use it in GitHub Desktop.
Android Error Label
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<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> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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()); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | |
} | |
}); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.