Android: Restrict user from selecting other than autocompletion suggestions? - android

I have provided an AutoCompleteTextView to show suggestions to the user. Based on the item selected by the user, I am getting the ID of the item and using it in data base side. Now my problem is to force the user to make selection only from AutoCompleteTextView (i.e. user should not enter his own text). It is a client requirement. How to do this?

Here's a pretty straightforward solution:
You can create a variable to store the selected value by setting setOnItemClickListener in your AutoCompleteTextView. Then you can null that value whenever a user types in the field by adding a TextWatcher to it. Finally, you can validate your variable is not null before continuing.
String my_var; //keep track!
AutoCompleteTextView tv = (AutoCompleteTextView) layout.findViewById(R.id.tv);
tv.setAdapter(my_adapter);
tv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
my_var = my_adapter.getItem(position).toString();
}
});
/**
* Unset the var whenever the user types. Validation will
* then fail. This is how we enforce selecting from the list.
*/
tv.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
my_var = null;
}
#Override
public void afterTextChanged(Editable s) {}
});

I happened to need such a requirement for a project I am working on, and I though I'll share you guys the way I implemented the required.
I added a on focus change listener for the auto-complete text view and checked when the user has focus changed focus from the auto-complete, and handled the situation straight forward.
autoTextViewCountry.setOnFocusChangeListener(new View.OnFocusChangeListener() {
#Override
public void onFocusChange(View view, boolean b) {
if(!b) {
// on focus off
String str = autoTextViewCountry.getText().toString();
ListAdapter listAdapter = autoTextViewCountry.getAdapter();
for(int i = 0; i < listAdapter.getCount(); i++) {
String temp = listAdapter.getItem(i).toString();
if(str.compareTo(temp) == 0) {
return;
}
}
autoTextViewCountry.setText("");
}
}
});
So my implementation is: if the typed text doesn't exist in the array adapter then on focus changed empty the text view, and later on when continuing to next stage of say registration, check if this text view is empty or not.
Hope this approach helps somebody.
Happy coding.

NiceAutoCompleteTextView will give you the ability to check whether a selection was made from the drop-down popup, by invoking isSelectionFromPopup()

Just add this property to your AutoCompleteTextView.
android:focusable="false"
My Code looks like:
<com.google.android.material.textfield.TextInputLayout
android:id="#+id/menu"
style="#style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.ExposedDropdownMenu"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Mode">
<AutoCompleteTextView
android:id="#+id/mode"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:focusable="false"
/>
</com.google.android.material.textfield.TextInputLayout>
On Java Side:
AutoCompleteTextView mode = findViewById(R.id.mode);
final List<String> modeList = new ArrayList();
modeList.add("YEARLY");
modeList.add("HALF-YEARLY");
modeList.add("QUARTER-YEARLY");
modeList.add("MONTHLY");
mode.setAdapter(new ArrayAdapter(getApplicationContext(),R.layout.list_item,modeList));
To get the Text of AutoCompleteTextView:
mode.getText().toString()

Ok I assume you would like to limit the input of the user to the texts contained in the list of items listed in the suggest box.
For instance if you have:
One
Two
Three
then the user could only type for the first character "O" and "T".
And so on according to the text entered before.
To achieve this you can utilize the setFilters method of TextView:
editBox = (TextView) findViewById(R.id.editBox);
editBox.setFilters(getFilters());
editBox.addTextChangedListener(this);
editBox.setOnFocusChangeListener(this);
Additionally you would probably need the text change listener and focus listener to react and update the filtered list when a new character is entered ... plus to update the filter.
Here is an example of decimal number filter I have used on a project:
protected InputFilter[] getFilters()
{
InputFilter[] filters = new InputFilter[1];
filters[0] = new InputFilter()
{
public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend)
{
// limit input to digits and decimal / thousand separator only
// in case thousand separator is pressed, change it to decimal
// separator instead
String output = "";
if (number.isFocused())
{
for (int i = start; i < end; i++)
{
char c = source.charAt(i);
if (isDecimalOrThousandSeparator(c))
{
output = output + Character.toString(decimalSeparator);
}
else if (Character.isDigit(c))
{
output = output + Character.toString(c);
}
}
return output == "" ? null : output;
}
return null;
}
};
return filters;
}

A simple solution would be to just check if the current input is one of the items in the adapter. You can do it like this:
val AutoCompleteTextView.isValid: Boolean
get() {
for (i in 0 until adapter.count) {
if (adapter.getItem(i) == text.toString()) {
return true
}
}
return false
}

here is the another solution for this proAutoCompleteTextView.Validator to ensure the valid values. Validator is invoked when edit text looses focus.
autoCompleteTextView.validator = object : AutoCompleteTextView.Validator {
override fun isValid(text: CharSequence?): Boolean {
return optionsList.contains(text.toString())
}
override fun fixText(invalidText: CharSequence?): CharSequence {
return ""
}
}
Where optionsList is list of valid values.

I was having the same requirement, so here is my implementation:
autoCompleteTextView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
autoCompleteTextView.showDropDown();
}
});
In the xml set focusable=false and focusableInTouchMode=false.
Happy coding

In order to have a non editable variation of the AutoCompleteTextView, you should disable user input in the AutoCompleteTextView. That can be achieved by setting android:inputType="none" on the AutoCompleteTextView.

Related

Impossible to append comma in Editable object

What I'm trying to achieve is to have an EditText with the following behaviour:
At first, the text show:
0.00 (en_GB local) or 0,00 (fr_FR local)
When user type the number 4, the Edittext show:
0.04 (en_GB) or 0,04 (fr_FR)
When user type another 6:
0.46 (en_GB) or 0,46 (fr_FR)
Etc.
Currently my code works very fine when the local is set to en_GB, however when the local change to fr_FR, I get an infinite loop.
Here is the code:
EditText layout:
<EditText
android:id="#+id/amount_ET"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:inputType="numberDecimal"
android:maxLength="8" />
And the java code:
amountEditText = (EditText) findViewById(R.id.amount_ET);
amountEditText.setText(mValueToString());
// ensure the cursor is always in the beginning of the text.
amountEditText.setOnFocusChangeListener(new OnFocusChangeListener() {
#Override
public void onFocusChange(View v, boolean hasFocus) {
if (v.hasFocus()) {
int len = amountEditText.getEditableText().toString().trim().length();
if (len > 1) {
amountEditText.setSelection(0);
amountEditText.setCursorVisible(false);
}
}
}
});
// add listener in order to intercept input on the EditText
amountEditText.addTextChangedListener(new TextWatcher() {
#Override
public void afterTextChanged(Editable s) {
// we only update if the value is not what we expect to avoid infinite loop
if (!s.toString().isEmpty() && !s.toString().equals(mValueToString())) {
// the cursor is always at the first position, so new char are in the beginning of the editable
updateAmountTextView(s, s.charAt(0));
}
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
});
}
/**
* Update the new value with the given numeral and update the given Editable with the new value.
*
* #param s
* if not null, will be updated with the formatted value.
* #param c
* the char representing the number to insert.
*/
protected void updateAmountTextView(Editable s, char c) {
Integer i = Integer.valueOf(c - 48);
mValue = mValue * 10 + i;
if (s != null) {
s.clear();
s.append(mValueToString()); // when using fr_FR local, the coma is not appended leading to a false value in the editable.
}
amountEditText.setSelection(0);
}
/**
* return the String formatted value.
*/
protected String mValueToString() {
Double d = Double.valueOf(mValue) / 100;
NumberFormat formatter = new DecimalFormat("#0.00");
return formatter.format(d);
}
Has explained in the comments of the java code, the bug is in the method updateAmountTextView() where the Editable refuse to take the coma.
When changing the inputType of the EditText to the value text this bug doesn't occur, except I want to have a softkeyboard accepting numbers only.
I guess I should do something on the Editable object before appending value to it but I can't find anything about this in the documentation.
As pointed in the comments by https://stackoverflow.com/users/427291/devisnik adding the line android:digits="0123456789.," in the Edittext layout solved the issue.

Permanent hint in EditText

I have a situation where I would like the user to complete a sentence for me. For example, consider a EditText with a hint of "The last time I ". Normally, when a user clicks an EditText, the hint disappears, but I would like it to stay. Additionally, I would like the text to be permanent, so that it cannot be erased... leaving the user with only one option... complete the sentence.
The first part is fairly simple, just use the setText() method of EditText to place the hint. The difficult part is the latter. How can I have text in an EditText that the user cannot erase?
Well couldn't you do it in code? Some algorithim like, if the text is less than 16 characters (length of "The last time I ") then set the text to that. Therefore whenever they clicked it, if they tried to erase it, it would just go back to the default text.
Also, another idea..why don't you just make a TextView thats right edge aligns with the left edge of the EditText box, the user would never know that it was another box. This is acutally the best solution, if you don't want the text ever to be edited, just make it a TextView
Described problem can be solved using android.text.TextWatcher.
public class CompleteSentenceWathcher implements TextWatcher {
private final String initialText;
private int start;
private int after;
private int count;
public CompleteSentenceWathcher(String initialText) {
this.initialText = initialText;
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
this.start = start;
this.count = count;
this.after = after;
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
#Override
public void afterTextChanged(Editable s) {
if(start < initialText.length()) {
if(s.toString().startsWith(initialText)) {
return;
}
if(count >= 1 && after == 0) {
if(start+count+1 <= initialText.length()) {
s.replace(start, start+count, initialText.substring(start, start+count+1));
} else {
s.replace(start, start, initialText.substring(start, start+1));
}
} else if(count == 0 && after >= 1) {
s.delete(start, start+after);
}
}
}
}
Create an instance of EditText and add the TextWatcher.
EditText editText = new EditText(this);
editText.setText("I love");
editText.addTextChangedListener(new CompleteSentenceWathcher(editText.getText().toString()));
I've implemented this with an InputFilter, where _PERMANENT_HINT_TEXT is the text at the end of the EditText that I don't want the user to be able to modify. I recommend adding a color span to it, so that it is grayed out to hopefully look like a hint/disabled section of text. This should hopefully improve the UX as they should automatically assume it is unmodifiable, and not just wonder why some part of the EditText (that they usually can completely change) isn't "working". This approach allowed the text to be set after
the InputFilter was set on the EditText, which was a requirement for me since I used this on an EditTextPreference.
To be clear, I needed the permanent text to exist at the end of the EditText, instead of the beginning, but that should be symmetrical to my implementation.
new InputFilter() {
#Override
public CharSequence filter(CharSequence source, int source_start, int source_end,
Spanned destination, int destination_start, int destination_end) {
final int protected_text_start = (TextUtils.isEmpty(destination)? source.length() : destination.length()) - _PERMANENT_HINT_TEXT.length();
// Allows input into unprotected region
if (source_start + destination_start - source_end < protected_text_start)
return null;
// Prevents deletion of protected region
else if (TextUtils.isEmpty(source))
return destination.subSequence(destination_start, destination_end);
// Ignores insertion into protected region
else
return "";
}
}
use EditText.setFilters(new InputFilters[] { /* InputFilter goes here */ }; to add it to the desired EditText.
Just checking for the length wouldn't be adequate... I could type "This is a really long text I put into the box" and it would accept it even though it doesn't begin with "The last time I" string.
Personally, I would probably go for the prevention method suggested of using a TextView over that of a check on the way out. But if you're going to validate it afterwards, you'd actually need to check the beginning of the returned string.

Problem with android password field, not hiding the last character typed

In Android, I create a password field like this:
EditText text = new EditText(context);
text.setTransformationMethod(PasswordTransformationMethod.getInstance());
Or like this, which seems to do the same thing:
EditText text = new EditText(context);
text.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
I get a nice password field except for the last character typed by the user. It's visible on the screen for a few seconds before beeing masked with a dot.
Here is a screenshot:
Do you know how to fix this behaviour please?
This is expected behavior. With the soft keyboards on most devices, it is valuable feedback that they are typing the password correctly.
For a list of all of the different inputTypes you can specify and how they change the EditText,
see android inputTypes .
Also, it is possible to change this behavior by implementing your own TransformationMethod and setting it via setTransformationMethod(), but I would not recommend doing that. Users will expect the behavior you are seeing and by changing your app, you'll be providing an inconsistent user experience.
also check this android article
Implementation of TransformationMethod to hide last char typed in password:
public class LoginActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// example of usage
((TextView) findViewById(R.id.password)).setTransformationMethod(new HiddenPassTransformationMethod());
}
private class HiddenPassTransformationMethod implements TransformationMethod {
private char DOT = '\u2022';
#Override
public CharSequence getTransformation(final CharSequence charSequence, final View view) {
return new PassCharSequence(charSequence);
}
#Override
public void onFocusChanged(final View view, final CharSequence charSequence, final boolean b, final int i,
final Rect rect) {
//nothing to do here
}
private class PassCharSequence implements CharSequence {
private final CharSequence charSequence;
public PassCharSequence(final CharSequence charSequence) {
this.charSequence = charSequence;
}
#Override
public char charAt(final int index) {
return DOT;
}
#Override
public int length() {
return charSequence.length();
}
#Override
public CharSequence subSequence(final int start, final int end) {
return new PassCharSequence(charSequence.subSequence(start, end));
}
}
}
}
I came across this problem after needing to implement a pin-code type user interface. After the user entered 1 number (1:1 relationship between EditTexts and pin numbers for a total of 4 EditTexts) the password would remain "in the open". My solution was to implement a TextWatcher that replaced the input with bullets (•'s).
See the full answer here
I was also facing same issues, in my case there was 3 edit text each edit text can have maximum 4 digit number for Aadhaar number. I used numberPassword input type.
When user type Aadhaar number very fast first edit text last text 4th was not hiding because I am changing focus when 4 digit completed. I have added text watcher.
I got solution at the end of last edit text when 4 digit completed I requestFocus for all 3 edit text one by one.
Solution :
#Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
if (getBinding().edtFirstFourNumber.getText().toString().length() == 4 && getBinding().edtMiddleFourNumber.getText().toString().length() == 4 && getBinding().edtLastFourNumber.getText().toString().length() == 4) {
// getBinding().homeProceed.setAlpha(1f);
getBinding().homeProceed.setTextColor(ContextCompat.getColor(mContext, R.color.color_ffffff));
getBinding().homeProceed.setEnabled(true);
} else {
// getBinding().homeProceed.setAlpha(0.5f);
getBinding().homeProceed.setTextColor(ContextCompat.getColor(mContext, R.color.color_4090BE));
getBinding().homeProceed.setEnabled(false);
}
if (getBinding().edtFirstFourNumber.length() == 4) {
getBinding().edtMiddleFourNumber.requestFocus();
}
if (getBinding().edtMiddleFourNumber.length() == 4) {
getBinding().edtLastFourNumber.requestFocus();
}
if (getBinding().edtLastFourNumber.length() == 4) {
getBinding().edtFirstFourNumber.requestFocus();
getBinding().edtMiddleFourNumber.requestFocus();
getBinding().edtLastFourNumber.requestFocus();
CommonUtils.hideSoftKeyboard(getActivity());
}
}

Make EditText ReadOnly

I want to make a read-only EditText view. The XML to do this code seems to be android:editable="false", but I want to do this in code.
How can I do this?
Please use this code..
Edittext.setEnabled(false);
If you setEnabled(false) then your editText would look disabled (gray, etc). You may not want to change the visual aspect of your editor.
A less intrusive way would be to use setFocusable(false).
I believe that this answers your question closer to your initial intent.
In XML use:
android:editable="false"
As an example:
<EditText
android:id="#+id/EditText1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:editable="false" />
This works for me:
EditText.setKeyListener(null);
editText.setInputType(InputType.TYPE_NULL);
As per the docs this prevents the soft keyboard from being displayed. It also prevents pasting, allows scrolling and doesn't alter the visual aspect of the view. However, this also prevents selecting and copying of the text within the view.
From my tests setting setInputType to TYPE_NULL seems to be functionally equivalent to the depreciated android:editable="false". Additionally, android:inputType="none" seems to have no noticeable effect.
android:editable="false" has been deprecated. Therefore you cant use it to make the edit text readonly.
I have done this using the bellow solution. Here I have used
android:inputType="none"
android:textIsSelectable="true"
android:focusable="false"
Give it try :)
<EditText
android:id="#+id/et_newsgpa_university"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:hint="#string/hint_educational_institute"
android:textSize="#dimen/regular_text"
android:inputType="none"
android:textIsSelectable="true"
android:focusable="false"
android:maxLines="1"
android:imeOptions="actionNext"/>
The best is by using TextView instead.
editText.setEnabled(false);
editText.setFilters(new InputFilter[] { new InputFilter() {
public CharSequence filter(CharSequence src, int start, int end,
Spanned dst, int dstart, int dend) {
return src.length() < 1 ? dst.subSequence(dstart, dend) : "";
}
} });
This will give you uneditable EditText filter. you first need to put the text you want on the editText field and then apply this filter.
writing this two line is more than enough for your work.
yourEditText.setKeyListener(null);
yourEditText.setEnabled(false);
set in XML
android:inputType="none"
Try using
editText.setEnabled(false);
editText.setClickable(false);
Try overriding the onLongClick listener of the edit text to remove context menu:
EditText myTextField = (EditText)findViewById(R.id.my_edit_text_id);
myTextField.setOnLongClickListener(new OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
return true;
}
});
android:editable
If set, specifies that this TextView has an input method. It will be a textual one unless it has otherwise been specified. For TextView, this is false by default. For EditText, it is true by default.
Must be a boolean value, either true or false.
This may also be a reference to a resource (in the form #[package:]type:name) or theme attribute (in the form ?[package:][type:]name) containing a value of this type.
This corresponds to the global attribute resource symbol editable.
Related Methods
If you just want to be able to copy text from the control but not be able to edit it you might want to use a TextView instead and set text is selectable.
code:
myTextView.setTextIsSelectable(true);
myTextView.setFocusable(true);
myTextView.setFocusableInTouchMode(true);
// myTextView.setSelectAllOnFocus(true);
xml:
<TextView
android:textIsSelectable="true"
android:focusable="true"
android:focusableInTouchMode="true"
...
/>
<!--android:selectAllOnFocus="true"-->
The documentation of setTextIsSelectable says:
When you call this method to set the value of textIsSelectable, it sets the flags focusable, focusableInTouchMode, clickable, and longClickable to the same value...
However I had to explicitly set focusable and focusableInTouchMode to true to make it work with touch input.
Use this code:
editText.setEnabled(false);
editText.setTextColor(ContextCompat.getColor(context, R.color.black);
Disabling editText gives a read-only look and behavior but also changes the text-color to gray so setting its text color is needed.
this is my implementation (a little long, but useful to me!):
With this code you can make EditView Read-only or Normal. even in read-only state, the text can be copied by user. you can change the backgroud to make it look different from a normal EditText.
public static TextWatcher setReadOnly(final EditText edt, final boolean readOnlyState, TextWatcher remove) {
edt.setCursorVisible(!readOnlyState);
TextWatcher tw = null;
final String text = edt.getText().toString();
if (readOnlyState) {
tw = new TextWatcher();
#Override
public void afterTextChanged(Editable s) {
}
#Override
//saving the text before change
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
// and replace it with content if it is about to change
public void onTextChanged(CharSequence s, int start,int before, int count) {
edt.removeTextChangedListener(this);
edt.setText(text);
edt.addTextChangedListener(this);
}
};
edt.addTextChangedListener(tw);
return tw;
} else {
edt.removeTextChangedListener(remove);
return remove;
}
}
the benefit of this code is that, the EditText is displayed as normal EditText but the content is not changeable. The return value should be kept as a variable to one be able revert back from read-only state to normal.
to make an EditText read-only, just put it as:
TextWatcher tw = setReadOnly(editText, true, null);
and to make it normal use tw from previous statement:
setReadOnly(editText, false, tw);
This worked for me, taking several of the suggestions above into account. Makes the TextEdit focusable, but if user clicks or focuses, we show a list of selections in a PopupWindow. (We are replacing the wacky Spinner widget). TextEdit xml is very generic...
public void onCreate(Bundle savedInstanceState) {
....
fEditState = (EditText) findViewById(R.id.state_edit);
fEditState.setLongClickable(false);
fEditState.setKeyListener(null);
fEditState.setFocusable(true);
fEditState.setOnFocusChangeListener(new View.OnFocusChangeListener() {
public void onFocusChange(View v, boolean hasFocus)
{
if (hasFocus)
{
showStatesPopup();
}
}
});
fEditState.setOnClickListener(new Button.OnClickListener(){
public void onClick(View arg0)
{
showStatesPopup();
}
});
....
}
private void showStatesPopup()
{
// fPopupWindowStates instantiated in OnCreate()
if (!fPopupWindowStates.isShowing()) {
// show the list view as dropdown
fPopupWindowStates.showAsDropDown(fEditState, -5, 0);
}
}
This was the only full simple solution for me.
editText.setEnabled(false); // Prevents data entry
editText.setFocusable(false); // Prevents being able to tab to it from keyboard
As android:editable="" is deprecated,
Setting
android:clickable="false"
android:focusable="false"
android:inputType="none"
android:cursorVisible="false"
will make it "read-only". However, users will still be able to paste into the field or perform any other long click actions. To disable this, simply override onLongClickListener().
In Kotlin:
myEditText.setOnLongClickListener { true }
suffices.
My approach to this has been creating a custom TextWatcher class as follows:
class ReadOnlyTextWatcher implements TextWatcher {
private final EditText textEdit;
private String originalText;
private boolean mustUndo = true;
public ReadOnlyTextWatcher(EditText textEdit) {
this.textEdit = textEdit;
}
#Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
if (mustUndo) {
originalText = charSequence.toString();
}
}
#Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
#Override
public void afterTextChanged(Editable editable) {
if (mustUndo) {
mustUndo = false;
textEdit.setText(originalText);
} else {
mustUndo = true;
}
}
}
Then you just add that watcher to any field you want to be read only despite being enabled:
editText.addTextChangedListener(new ReadOnlyTextWatcher(editText));
I had no problem making EditTextPreference read-only, by using:
editTextPref.setSelectable(false);
This works well when coupled with using the 'summary' field to display read-only fields (useful for displaying account info, for example). Updating the summary fields dynamically snatched from http://gmariotti.blogspot.com/2013/01/preferenceactivity-preferencefragment.html
private static final List<String> keyList;
static {
keyList = new ArrayList<String>();
keyList.add("field1");
keyList.add("field2");
keyList.add("field3");
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
for(int i=0;i<getPreferenceScreen().getPreferenceCount();i++){
initSummary(getPreferenceScreen().getPreference(i));
}
}
private void initSummary(Preference p) {
if (p instanceof PreferenceCategory) {
PreferenceCategory pCat = (PreferenceCategory) p;
for (int i = 0; i < pCat.getPreferenceCount(); i++) {
initSummary(pCat.getPreference(i));
}
} else {
updatePrefSummary(p);
}
}
private void updatePrefSummary(Preference p) {
if (p instanceof ListPreference) {
ListPreference listPref = (ListPreference) p;
p.setSummary(listPref.getEntry());
}
if (p instanceof EditTextPreference) {
EditTextPreference editTextPref = (EditTextPreference) p;
//editTextPref.setEnabled(false); // this can be used to 'gray out' as well
editTextPref.setSelectable(false);
if (keyList.contains(p.getKey())) {
p.setSummary(editTextPref.getText());
}
}
}
Set this in EdiTextView xml file
android:focusable="false"
in java file:
Edittext.setEnabled(false);
in xml file:
android:editable="false"
These 2 lines makes ur edittext selectable and at the same time not editable (it doesn't even show the soft keyboard):
editText.setInputType(InputType.TYPE_NULL);
editText.setTextIsSelectable(true);

Keyboard doesn't accept first character when changing inputs

I have a TextWatcher set on an EditText that changes the input type after a user types a number followed by a space.
If the user types two numbers the input type switches and accepts the next character, but if the user types only one number and presses space the input type still changes but it won't accept the first character the user tries to input.
I've tested this on Froyo and 1.6, it only happens on Froyo, 1.6 works like it should.
Here's the code:
TextWatcher watcher = new TextWatcher() {
#Override
public void afterTextChanged (Editable s) {
}
#Override
public void beforeTextChanged (CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged (CharSequence s, int start, int before, int count) {
// Parsed text holder is a class that just parses the EditText and pulls out various parts.
ParsedTextHolder th = parseTextHolder(s);
String newText = "";
Boolean setTextKeyListener = false;
String tGetTextString = mQuery.getText().toString();
if (!th.pFullMatch.equals("")) {
if (th.pFullMatch.length() == 2) {
mQuery.setKeyListener(new
TextKeyListener(TextKeyListener.Capitalize.SENTENCES, true));
newText = tGetTextString + " for ";
setTextKeyListener = true;
}
}
if (setTextKeyListener) {
Log.i("setTextKeyListener", "true");
if (mQuery.getKeyListener().getClass() != TextKeyListener.class) {
mQuery.setKeyListener(new TextKeyListener(TextKeyListener.Capitalize.SENTENCES, true));
} else {
Log.d("setTextKeyListener", "skipped. already was text.");
}
if (!newText.equals("")) {
int position = newText.length();
String ttext = newText;
newText = "";
mQuery.setText(ttext, TextView.BufferType.EDITABLE);
mQuery.setText(ttext);
Editable text = mQuery.getEditableText();
Log.w("setting selectiont to text: ", text.toString());
Log.w("setting selectiont to position: ", Integer.toString(position));
Selection.setSelection(text, position);
mQuery.setKeyListener(new TextKeyListener(TextKeyListener.Capitalize.SENTENCES, true));
}
}
}
};
Also, here's an APK if you want to see what the bug is like: http://endlesswhileloop.com/files/KeyboardBug.apk
Is mQuery the editText that is being watched? According to the javadocs, you shouldn't be making any changes to the text in your EditText in onTextChanged. All such changes should be made in afterTextChanged.
Generally, I've ended up examining the change in onTextChanged and then doing the work that results form the change in afterTextChanged. You might try that.

Categories

Resources