我想在 Android 中创建一个自定义 EditText,当出现错误时显示闪烁的红色背景。这个想法是直观地向用户表明输入无效。
这是我迄今为止尝试过的:
这是我写的代码:
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)
}
}
这可行,但我面临以下问题:
我想知道:
任何改进此实施的指导或建议将不胜感激。
我对这个问题有最好的解决方案。 我最近已将其实现到我的 Android 项目中。
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;
}
}
您可以在 .xml 文件中实现此功能,并在 java 或 kotlin 文件中执行验证过程,如下所示
<com.app.materialwallpaperapps.util.custom.CustomEditText
android:id="@+id/etName"
style="@style/CustomEditTextStyleOneLine"
android:hint="Example Corp"
android:text="@={viewModel.mainBoardRoot.companyContactDetails.name}" />
将其放入 java 或 kotlin 文件中进行验证。
if (binding.etName.validateEmpty()) {
showToast("Please enter Name");
return;
}