I've an email field as EditText. I'm trying to add a green-tick icon at the end of the text field when the validation is true, and setError when it is false.
Here's the piece of code I'm using right now:
email.setOnFocusChangeListener(new View.OnFocusChangeListener() {
#Override
public void onFocusChange(View v, boolean hasFocus) {
if (!hasFocus) {
String mail = email.getText().toString();
if(!android.util.Patterns.EMAIL_ADDRESS.matcher(mail).matches()) {
email.setError("Please enter a valid email address");
}
else {
Log.i("YaY","Email is valid!!!");
email.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.validated, 0);
}
}
}
});
PROBLEM:
Though I can see the log Yay: Email is valid!!!, it seems no icon is set as I can't see it.
But when I change the if-condition to false, which means setError will never be called, I can see the log as well as the icon.
Any explanations upon why I'm seeing this strange behavior? What am I missing?
try removing the icon from xml if you are setting any
and set both images from the code
for some reason the image does not refresh if you set one from xml
and use
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
numTxt.setCompoundDrawablesRelativeWithIntrinsicBounds(R.drawable.icon, 0, 0, 0);
} else {
numTxt.setCompoundDrawablesWithIntrinsicBounds(R.drawable.icon, 0, 0, 0);
}
I am not sure if this is a bug but I am able to workaround this by setting the drawable to zero (0) first before assigning the new drawable.
In your case, you can try the following:
Log.i("YaY","Email is valid!!!");
email.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
email.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.validated, 0);
Related
We have the setError method for setting an error message with a red exclamation symbol at the end of the box if validation of an EditText returns false:
I want to set a green tick symbol, just like the red exclamation at the end of the box when my validation returns true:
password.setOnFocusChangeListener(new View.OnFocusChangeListener() {
#Override
public void onFocusChange(View v, boolean hasFocus) {
if (!hasFocus) {
if (password.getText().toString().length() < 6) {
password.setError("Password should be greater than 6 characters!");
}
else {
//validation is true, so what to put here?
}
}
}
});
}
EDIT 1
Seemingly impossible, but there's more to the problem. I did this:
email.setOnFocusChangeListener(new View.OnFocusChangeListener() {
#Override
public void onFocusChange(View v, boolean hasFocus) {
if (!hasFocus) {
String mail = email.getText().toString();
if(!android.util.Patterns.EMAIL_ADDRESS.matcher(mail).matches()) {
email.setError("Please enter a valid email address");
}
else {
Log.i("yay!","Email is valid!!!");
email.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.validated, 0);
}
}
}
});
Though I can see in my logs that yay: Email is valid!!!, I can't see the validation symbol at the end of the EditText.
However, to my surprise when I change the if statement to always false, I can see both the symbol with the log statement.
Any explanations upon why could this be happening?
You can show drawableRight when your validation is true.
password.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.rightImage, 0);
and set it back to normal when validation is false.
password.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
I just tested it out in my own project using setError(CharSequence error, Drawable icon)
Get a new Icon:
Go to my drawable folder
adding a new vector asset.
I picked "material icon" and browse,
then picked ic_done_24pp.
Color:
Next, I went into the xml and made it green by changing the fillcolor:
android:fillColor="#FF00FF00"
3: Change code:
Drawable myIcon = getResources().getDrawable(R.drawable.ic_done_24dp);
myIcon.setBounds(0, 0, myIcon.getIntrinsicWidth(), myIcon.getIntrinsicHeight());
mPasswordView.setError("Good", myIcon);
Edit text in android doesn't allow to change draw able after setError.
I have used drawable right for password field but if error comes in password field it won't allow to change draw able after it. before error it works fine.
<EditText
android:id="#+id/edt_reg_password"
style="#style/editText_full_view"
android:layout_height="wrap_content"
android:layout_below="#id/edt_reg_email"
android:layout_marginTop="#dimen/padding_normal"
android:drawableLeft="#mipmap/ic_action_password"
android:drawableRight="#mipmap/ic_action_password_visibility"
android:drawablePadding="#dimen/padding_normal"
android:hint="#string/hint_password"
android:inputType="textPassword"
android:maxLength="25"
android:paddingLeft="#dimen/padding_normal"
tools:visibility="visible" />
Java code for changing eye icon run time
private void setPasswordDrawable()
{
final Drawable showpass_icon = getResources().getDrawable(R.mipmap.ic_action_password_visibility);
final Drawable hidepass_icon = getResources().getDrawable(R.mipmap.ic_action_password_visibility_off);
final Drawable pass_drawable = getResources().getDrawable(R.mipmap.ic_action_password);
pass_drawable.setBounds(0, 0, pass_drawable.getIntrinsicWidth(), pass_drawable.getIntrinsicHeight());
//edtPassword.setCompoundDrawables(pass_drawable, null, showpass_icon, null);
edtPassword.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if (edtPassword.getCompoundDrawables()[2] == null) {
return false;
}
if (event.getAction() != MotionEvent.ACTION_UP) {
return false;
}
if (event.getX() > edtPassword.getWidth() - edtPassword.getPaddingRight()
- showpass_icon.getIntrinsicWidth()) {
if (isPasswordVisible) {
runOnUiThread(new Runnable() {
#Override
public void run() {
//edtPassword.setError(null);
edtPassword.setTransformationMethod(
PasswordTransformationMethod.getInstance());
edtPassword.setSelection(edtPassword.getText().length());
showpass_icon.setBounds(0, 0, showpass_icon.getIntrinsicWidth(), showpass_icon.getIntrinsicHeight());
edtPassword.setCompoundDrawables(pass_drawable, null, showpass_icon, null);
}
});
isPasswordVisible = false;
} else {
runOnUiThread(new Runnable() {
#Override
public void run() {
//edtPassword.setError(null);
edtPassword.setTransformationMethod(
HideReturnsTransformationMethod.getInstance());
edtPassword.setSelection(edtPassword.getText().length());
hidepass_icon.setBounds(0, 0, hidepass_icon.getIntrinsicWidth(), hidepass_icon.getIntrinsicHeight());
edtPassword.setCompoundDrawables(pass_drawable, null, hidepass_icon, null);
}
});
isPasswordVisible = true;
}
}
return false;
}
});
}
For setting error
public void setViewError(View view, String message)
{
if (view instanceof EditText) {
((EditText) view).setError(message);
}
}
You may use this like -
if(error=true){
editText.setCompoundDrawablesWithIntrinsicBounds(
0, 0,R.drawable.ic_error, 0);
editText.setCompoundDrawablePadding(5);}
else{
editText.setCompoundDrawablesWithIntrinsicBounds(
0, 0,R.drawable.ic_corrct, 0);
editText.setCompoundDrawablePadding(5);}
It may be very late. Me too faced these kind of issue. And I frustrated to find the solution. Finally I found the solution. It may helpful someone like me. The solution is very simple.
EditText stores the errors whenever we set the error and it didn't remove automatically even after entering the correct value. So you need to manually override the error text and set empty value.
if (!isError) {
edt_reg_password.setError("");
edt_reg_password.setText(edt_reg_password.getText().toString());
} else {
edt_reg_password.setError("Data Invalid");
}
Thanks ! Happy Coding !
The right drawable and error drawable of the TextView (or EditText) are displayed based on the same field.
When the error drawable is showing, the right drawable will be stored in a temporary variable and then restored when the error disappears.
So you can't change the right drawable when the error is showing.
But there is a problem with the code in TextView: the temporary variable (right drawable) will not be clear after restoration.
And once the temporary variable exists, even if you set the right drawable with a new value, the temporary variable will be display anyway.
This is why right drawable not change after setError(): it keep showing the previous value.
All this happens in TextView#Drawables.
Unfortunately there is no direct way to that clear temporary variables, but this can be done indirectly by set TextView#mDrawables to null. Then, you can set the right drawable as you want.
// Clear error first
editText.setError(null);
// Clear TextView#Drawables
editText.setCompoundDrawables(null, null, null, null);
// Set right drawable
editText.setCompoundDrawables(null, null, drawableRight, null);
I'm developing an IME for Android, which includes some highlighting of the text input by the user with a background colour (using SpannableString).
When the device is rotated and the keyboard is redrawn, the text remains in the input box as entered by the user, however, all styling (i.e. background colour) is lost.
Any ideas why this might be happening and how to circumvent it?
I have found a solution, which is not perfect, but it works.
Set up an ExtractedText variable in the IME service class.
In the OnConfigurationChanged method, get the extracted text. Then in the onStartInputView method, delete the text in the bound editor, and replace it with the extracted text.
#Override
public void onConfigurationChanged (Configuration newConfig)
{
//get what's been input so far
ExtractedTextRequest req = new ExtractedTextRequest();
req.token = 0;
req.flags = InputConnection.GET_TEXT_WITH_STYLES;
extractedText = ic.getExtractedText(req, 0);
super.onConfigurationChanged(newConfig);
}
#Override public void onStartInputView(EditorInfo attribute, boolean restarting) {
...
if(extractedText!=null)
{
if(ic.deleteSurroundingText(9999, 0))
{
ic.commitText(extractedText.text, 1);
Log.i("onStartInputView", "Text Replaced");
}
else
{
Log.i("onStartInputView", "IC not valid");
}
}
super.onStartInputView(attribute, restarting);
}
I am usig TranlateAnimation to showing and hiding EditText. First EditText has visibility gone. After it takes visibility visible and tranlating up. When EditText get focus backgroung of all app becomes black. When focus of EditText is lost everything becomes good. Maybe it's because I use ViewPager which contains all fragrament. What is the problem of this?
Here is code of animation:
private void initAnimationDown() {
animationDown = new TranslateAnimation(0, 0, 0, height);
animationDown.setFillAfter(true);
animationDown.setDuration(500);
}
private void initAnimationUp() {
animationUp = new TranslateAnimation(0, 0, height, 0);
animationUp.setFillAfter(true);
animationUp.setDuration(500);
}
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
initAnimationUp();
perfectEditText.startAnimation(animationUp);
perfectEditText.setVisibility(View.VISIBLE);
} else {
initAnimationDown();
perfectEditText.startAnimation(animationDown);
perfectEditText.setVisibility(View.GONE);
}
}
What if you try to unvalidate the edit text before hidding him and starting animation?
perfectEditText.setFocusable( false );
perfectEditText.setFocusableInTouchMode( false );
I want to to have some validation for my EditText wherein I want to show "" icon (that comes when you put editText.setError("blah blah")) but don't want the text in the popup displaying that "blah blah".
Is there any way to do it? One way is to create a custom layout which will show the image icon in the EditText. But is there any better solution?
Problem solved after a lot of research and permutations- (Also thanks to #van)
Create a new class that will extend EditText something like this-
public class MyEditText extends EditText {
public MyEditText(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
public void setError(CharSequence error, Drawable icon) {
setCompoundDrawables(null, null, icon, null);
}
}
Use this class as a view in your xml like this-
<com.raj.poc.MyEditText
android:id="#+id/et_test"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
Now in the third step, just set a TextWatcher to your custom text view like this-
et = (MyEditText) findViewById(R.id.et_test);
errorIcon = getResources().getDrawable(R.drawable.ic_error);
errorIcon.setBounds(new Rect(0, 0, errorIcon.getIntrinsicWidth(), errorIcon.getIntrinsicHeight()));
et.setError(null,errorIcon);
et.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
// TODO Auto-generated method stub
}
#Override
public void afterTextChanged(Editable s) {
if(s.toString().length()>6){
et.setError("", null);
}else{
et.setError("", errorIcon);
}
}
});
where R.drawable.ic_error =
Keeping text null solves the problem
But if we keep only null in setError(null), this won't show the validation error; it should be null along with second param.
You dont need to create a new EditText class or change xml. The solution is very simple:
Edittext editText= (EditText) rootView.findViewById(R.id.email);
String str= editText.getText().toString();
if(str.equalsIgnoreCase("") ){
Drawable dr = getResources().getDrawable(R.drawable.error);
//add an error icon to yur drawable files
dr.setBounds(0, 0, dr.getIntrinsicWidth(), dr.getIntrinsicHeight());
editText.setCompoundDrawables(null,null,dr,null);
}
Sorry Rajkiran, but your solution is not working on Android 4.2 version. If I am trying to set null value for error, it is not even displayed. The solution I came up was to extend EditText and override setError method. No I have only error indicator without popup.
#Override
public void setError(CharSequence pError, Drawable pIcon) {
setCompoundDrawables(null, null, pIcon, null);
}
I have been dealing with the same problem. I wanted to use .setError() to my EditText when user insert null input. But I think the pop-out message is annoying, especially when you have more EditTexts.
My solution was naive and simple, but it worked on all devices I've tried so far.
I created my own class myEditText and just #Override this method:
#Override
public void setError(CharSequence error, Drawable icon) {
setCompoundDrawables(null, null, icon, null);
}
then use in layout.xml
<cz.project.myEditText
...
/>
and finally in my code
I put onFocusChangeListener to myEditText, so when someone clicks-in, the icon disappears.
myEditText input = (myEditText) findViewById(R.id.input);
input.setOnFocusChangeListener(new OnFocusChangeListener() {
#Override
public void onFocusChange(View v, boolean hasFocus) {
input.setError(null);
});
if(val == null) input.setError("");
It works Exactly how I want = no pop-up message when .setError() is called on EditText.
To get only the error-icon without an error-message-popup only when setError("") is called (i.e. set an empty String as error-message) I use a custom EditText-class where I override setError(CharSequence, Drawable) like this:
#Override
public void setError(CharSequence error, Drawable icon) {
if (error == null) {
super.setError(null, icon);
setCompoundDrawables(null, null, null, null);
}
else if (error.toString().equals("")) setCompoundDrawables(null, null, icon, null);
else super.setError(error, icon);
}
Everything else stays the same:
Use setError(null) to get neither the icon nor the message-popup.
Use setError(errorMessage), where errorMessage is a String with length 1 at least, to get the icon and message-popup.
This is the very useful when you want to show the error messages for the edittext field when the user enter wrong information.this is very simply program only you have to use serError() method in the edittext.
Step 1:
Create button and implement onclickListener.
btnLogin.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
}
});
Step 2:
Validate the input fields and set the error in the input field.
if(edName.length()>3){
if(edNumber.length()>3){
Toast.makeText(getApplicationContext(), "Login success", Toast.LENGTH_SHORT).show();
}else{
edNumber.setError("Number Mininum length is 4");
}
}else{
edName.setError("Name Mininum length is 4");
}
Refer this link for more:http://velmuruganandroidcoding.blogspot.in/2014/08/set-error-message-in-edittext-android.html