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);
}
Related
i'm working with expandable recycler view from bignerdranch. Inside my child view, i placed a edit text where user can leave a comment regarding an issue shown on the parent view.
My problem is that, i wanted the user input to be save after the edit text loose focus. (In this case, i have 3 parents, and each parent has 1 editText). But when i input edit text 1 and focus on edit text 2 without inputing... edit text 2 would take up edit text 1 input after it loose focus.
I try using text watcher, and put the codes inside after text changes.. but the app freezes and stopped working after a while. If there a better way for me to save accordingly?
mCatatan is my editText.
#Override
public void onBindChildViewHolder(final ATPChildViewHolder atpChildViewHolder, int i, Object childObject) {
final ATPChild atpChild = (ATPChild) childObject;
final String text = atpChildViewHolder.mCatatanInput.getText().toString();
if(!text.equals("")) {
atpChild.setDetail(text);
atpChildViewHolder.mCatatanInput.setText(atpChild.getDetail());
} else {
atpChildViewHolder.mCatatanInput.setText(atpChild.getDetail());
}
// todo: fixed catatan being saved to another catatan
atpChildViewHolder.mCatatanInput.setOnFocusChangeListener(new View.OnFocusChangeListener() {
#Override
public void onFocusChange(View v, boolean hasFocus) {
if (!hasFocus) {
Log.d(TAG, "onFocusChange: ");
atpChild.setDetail(atpChildViewHolder.mCatatanInput.getText().toString());
atpChildViewHolder.mCatatanInput.setText(atpChild.getDetail());
}
}
});
}
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 have made a class that is responsible for monitoring an EditText widget following the Observer pattern. Its sole function is to disable or re-enable auto-correct based on a method call. I am able to successfully achieve this, but the problem is that the new InputType only applies to new text I add to the EditText - old text still retains the red underline to show that it can be auto-corrected.
Is there any way I can force the new InputType to apply to the entire EditText block, and not simply the new content I add? I tried calling editText.invalidate() and editText.refreshDrawableState() in the hope all the text would refresh, but to no avail.
final class SpellCheckerObserver implements EditTextObserver {
public static final int KEY = KeyGenerator.generateUniqueId();
private int defaultInputType;
SpellCheckerObserver(EditTextSubject subject) {
subject.attach(SpellCheckerObserver.KEY, this);
}
#Override
public void activating(EditText editText) {
defaultInputType = editText.getInputType();
editText.setRawInputType(InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
}
#Override
public void deactivating(EditText editText) {
editText.setInputType(defaultInputType);
}
}
I found out the answer whilst looking through the source code for TextView, where I came across the removeSuggestionSpans() method.I wasn't aware that the suggestions were in fact a type of span, (unsurprisingly, the SuggestionSpan)
This meant I was able to remove the red underline with the following code:
SuggestionSpan[] spans = editText.getText().getSpans(
0, editText.length(), SuggestionSpan.class
);
if (spans.length > 0) {
for (SuggestionSpan span : spans) {
editText.getText().removeSpan(span);
}
}
I'm dynamically setting the Background color and text color of a textview component in my app, using a single options menu button "toggle color"
The problem is, as soon as the orientation changes the textview "forgets" what colors it was supposed to use...so it uses default and not those that were set by the options menu.
Here's the original function of the options menu option :
#Override
public boolean onOptionsItemSelected(MenuItem item) {
TextView textView = (TextView) findViewById(R.id.xxtt);
if (Cflag) {
textView.setBackgroundColor(Color.parseColor("#ffffff"));
textView.setTextColor(Color.parseColor("#000000"));
Cflag= false;
} else {
textView.setBackgroundColor(Color.parseColor("#000000"));
textView.setTextColor(Color.parseColor("#ffffff"));
Cflag= true;
}
return super.onOptionsItemSelected(item);
}
^Cflag is "global" boolean, depending on whether true/false the function sets the textviews color. (If it's black on white, it sets it to white text on black background...and vice-versa)
After doing a little research, Here are the extra functions I modified :
Since on orientation change, the app pauses and resumes, I modified onResume to independently change the color according to the variable Cflag.
And also the OnCofigChange, to update the colors if and when the orientation changes. I've tried using both these functions , and I've tried using them one at a time. Nothing helped.
#Override
protected void onResume() {
TextView textView = (TextView) findViewById(R.id.xxtt);
if (Cflag) {
textView.setBackgroundColor(Color.parseColor("#ffffff"));
textView.setTextColor(Color.parseColor("#000000"));
} else {
textView.setBackgroundColor(Color.parseColor("#000000"));
textView.setTextColor(Color.parseColor("#ffffff"));
}
super.onResume();
}
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
TextView textView = (TextView) findViewById(R.id.xxtt);
if (Cflag) {
textView.setBackgroundColor(Color.parseColor("#ffffff"));
textView.setTextColor(Color.parseColor("#000000"));
} else {
textView.setBackgroundColor(Color.parseColor("#000000"));
textView.setTextColor(Color.parseColor("#ffffff"));
}
}
I don't want to unnecessarily use a SharedPreferences object.
I reckon it's a matter of logic only,
If it's black text on white background(default) .... Press the option menu's option, It toggles to white text on black background .... Cflag variable is also toggled.
Now Cflag is constant, we just have to set the text color again according to Cflag.
But I can't get it to work: I change the settings in one orientation, and on switching orientation it goes back to default state(The one I defined in XML, black text on white background..)
What's wrong?
Thank you !
Save them in bundle
#Override
protected void onSaveInstanceState (Bundle outState) {
outState.putBoolean("CFLAG",CFlag);
}
and it will be restored in Activity onCreate.
#Override
protected void onCreate (Bundle savedInstanceState) {
CFlag = savedInstanceState.getBoolean("CFLAG");
}
Can anyone explain this difference in appearance?
SetColorFilter() acts on the background Drawable, whether setBackgroundResource() sets the background color.
In Android version 2.3 I safely used SetColorFilter() to alter the background color of EditText, since it is very easy to restore the original color by clearing the filter. No need to get and remember it. Now there seems to be a difference between the two ways.
This is an EditTextPreference dialog box, et is the EditText id.
public void afterTextChanged(Editable s) {
String source = s.toString();
et.removeTextChangedListener(this);
if( !source.matches("^[0-9]+$") ) {
et.getBackground().setColorFilter(getResources().getColor(R.color.invalid), Mode.OVERLAY);
et.invalidate();
et.selectAll();
} else {
et.getBackground().clearColorFilter();
et.invalidate();
}
et.addTextChangedListener(this);
}
And this is the same code using SetBackgroundResource()
public void afterTextChanged(Editable s) {
String source = s.toString();
et.removeTextChangedListener(this);
if( !source.matches("^[0-9]+$") ) {
et.setBackgroundResource(R.color.invalid);
et.selectAll();
} else {
et.setBackgroundResource(R.color.valid);
}
et.addTextChangedListener(this);
}
You can use textView.setError("Error message") as mentioned above.
If you want to customize the behavior of setError() however (such as changing background color), you will sadly enough need to override EditText and write your own handler for setError, as shown here: EditText setError() with icon but without Popup message