Reputation: 15
I want to create a custom EditText in Android that shows a blinking red background when there is an error. The idea is to visually indicate to the user that input is invalid.
Here is what I have tried so far:
Here is the code I have written:
class BlinkingEditText(context: Context, attrs: AttributeSet?) : AppCompatEditText(context, attrs) {
fun showErrorBlink() {
val handler = Handler(Looper.getMainLooper())
var isRed = false
val runnable = object : Runnable {
override fun run() {
if (isRed) {
setBackgroundColor(Color.WHITE)
} else {
setBackgroundColor(Color.RED)
}
isRed = !isRed
handler.postDelayed(this, 500) // Blink every 500ms
}
}
handler.post(runnable)
// Stop blinking after 3 seconds
handler.postDelayed({ handler.removeCallbacks(runnable) }, 3000)
}
}
This works, but I am facing the following issues:
I would like to know:
Any guidance or suggestions for improving this implementation would be greatly appreciated.
Upvotes: 1
Views: 29
Reputation: 21
I have the best solution for this issue. i have recently implemented this into my android project.
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.AttributeSet;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import com.app.materialwallpaperapps.R;
import com.app.materialwallpaperapps.base.BaseActivity;
public class CustomEditText extends androidx.appcompat.widget.AppCompatEditText {
private static final String TAG = BaseActivity.TAG;
public CustomEditText(@NonNull Context context) {
super(context);
init();
}
public CustomEditText(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
public CustomEditText(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
// Add a TextWatcher to listen for user input and reset the background if necessary
this.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
// No action needed here
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
// Reset the background to the default when the user starts typing
if (s.length() > 0) {
setBackgroundResource(R.drawable.edittext_bg); // Reset to original background
}
}
@Override
public void afterTextChanged(Editable s) {
// No action needed here
}
});
}
/**
* Shows a blinking error background to indicate an error.
*/
public void showBlinkableError() {
// Ensure the current background is mutable to modify its color dynamically
Drawable background = getBackground().mutate();
if (background instanceof GradientDrawable) {
GradientDrawable gradientDrawable = (GradientDrawable) background;
// Define the error color (light red) and original color
int errorColor = Color.parseColor("#FFCDD2"); // Light red
int originalColor = ContextCompat.getColor(getContext(), R.color.lightBlueEt);
// Store the original drawable
Drawable originalBackground = background.getConstantState().newDrawable();
// Create an ObjectAnimator to animate the color
ObjectAnimator animator = ObjectAnimator.ofArgb(gradientDrawable, "color", errorColor, originalColor);
// Set animation properties
animator.setDuration(200); // 500ms per blink
animator.setRepeatCount(3); // Blink 3 times
animator.setRepeatMode(ValueAnimator.REVERSE); // Reverse back to the original color
// Start the animation
animator.start();
animator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
// Restore the original background after animation end
Log.d(TAG, "onAnimationEnd: originalBackground = " + originalBackground);
setBackground(originalBackground);
}
});
// Set focus on the EditText
this.requestFocus();
} else {
Log.e("CustomEditText", "Background is not a GradientDrawable. Ensure correct drawable is used.");
}
}
/**
* Validates if the EditText is not empty.
*
* @return true if not empty, false otherwise
*/
public boolean validateEmpty() {
if (getText() == null || getText().toString().trim().isEmpty()) {
showBlinkableError();
return true;
}
return false;
}
}
you can implement this in .xml file and do validation process in java or kotlin file as below
<com.app.materialwallpaperapps.util.custom.CustomEditText
android:id="@+id/etName"
style="@style/CustomEditTextStyleOneLine"
android:hint="Example Corp"
android:text="@={viewModel.mainBoardRoot.companyContactDetails.name}" />
Put this into java or kotlin file for validation.
if (binding.etName.validateEmpty()) {
showToast("Please enter Name");
return;
}
Upvotes: 0