Disable Android AutoCompleteTextView after user selects item from drop down - android

I'm using Android's AutoCompleteTextView with a CursorAdapter to add autocomplete to an app. In the view's onItemClickListener() (i.e. when the user touches one of the autocompleted drop down items) I retrieve the text and place it in the EditText so that the user can modify it if they need to.
However, when I call setText() on the TextView the autocomplete behavior is triggered and the dropdown shows again. I'd like to only show the dropdown if the user types new text with the keyboard. Is there a way to do this?

You can use the dismissDropDown() method of the AutoCompleteTextView object. Take a look at the documentation.

When we click on item suggested in AutoCompleteTextView.onTextChanged() is performed before onItemClick
So, to avoid this try below code..
autocompletetextview.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
#Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
if (autocompletetextview.isPerformingCompletion()) {
// An item has been selected from the list. Ignore.
} else {
// Perform your task here... Like calling web service, Reading data from SQLite database, etc...
}
}
#Override
public void afterTextChanged(final Editable editable) {
}
});

If you wish to dissmis AutoCompleteTextView's dropdown you should use its post(Runnable r) method. It works for me :)
Here is an example:
mAutoCompleteTextView.post(new Runnable() {
public void run() {
mAutoCompleteTextView.dismissDropDown();
}
}

Answering my own question after a couple hours of hacking at this: It turns out you should implement your own OnItemClickListener and instead rely on the existing click listener to populate the TextView. I had originally implemented the onItemClickListener because it was using the results of Cursor.toString() to populate the text view. To change the output String, you should implement convertToString(Cursor) in your CursorAdapter. The CharSequence that gets returned will be populated in the text view.
Doing this will also prevent the dropdown from showing up again (since setText() triggers the completion behavior but the default onItemClickListener does not).

Different approach.
I agreed dismissDropDown() works but in my case, it wasn't working as expected. So, I used:
autoCompleteTextView.setDropDownHeight(0);
And if you want to show the dropdown list again, you an use
autoCompleteTextView.setDropDownHeight(intValue);

Related

Android AutoCompleteTextView is overlapping while typing suggestion list

I am trying to implement HashTag and mention by using AutocompleteTextview. It is working fine.
Depends on the entered keyword I am setting adapter in AutocompleteTextview. For that, I am using TextWatcher. It is showing the result. Till this working fine. But when I am typing the suggestion list is overlapping.
In the image, black Shadow is because of multiple pages. The number of pages is increasing when text in AutocompleteTextview is changing.
autoCompleteTextview.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) {
if (s.toString().startsWith("#")) {
setupTagUserAutocomplete(data);
}
else if (s.toString().startsWith("#")) {
setupHashAutocomplete(list);
}
}
#Override
public void afterTextChanged(Editable s) {
}
});
How to avoid this?
You do not have to use TextWatcher. Using TextWatcher will create a new suggestion list every time the text is changed.
You have to use an adapter for that purpose.
That is the reason it is creating so many suggestion-lists.
You have to create a custom adapter since there is a custom requirement because of the two conditions ( # and #).
Here is a link to an AutoCompleteTextView tutorial for you to go through. I hope you find this one useful.
https://www.studytonight.com/android/autocomplete-textview
In the above tutorial refer to the steps, but instead of an ArrayAdapter create a custom one. Inside that adapter, you can have that list according to the text.

How to make a custom Data Picker like Date Picker in Android

How to make a custom Data Picker like Date Picker in Android so that I can get data (int data) by custom input or by using the buttons (- & +) so that it become easy for user to enter larger value !!
Has anyone any idea how to implement this?
please provide example, code snippet if possible.
I want to make like this
left - Button
middle - EditText
right - Button
I want Like this image--
This is the example of Date Picker in Android:-
then try this link
try on text changed listener as described in the link to update the variable whenever user changes the edit text, then variable will hold the changed value and so you can use your method to change values of that variable
Design a layout as you want with two buttons and one edittext in middle
Then give one button addition funtionality and other substraction functionality
Follow little code snippet, provided below
addButton.setOnClickListener(new OnClickListener(){
public void onClick(){
int valueInEditText = Integer.parseInt(etReference.getText().toString());
etReference.setText(String.valueOf(valueInEditText + 1));
}
});
Similaryly, do it for substration button.
Note: Do validation if you don't want negative values.
You might want to use the NumberPicker which will allow you to select any value.
It's not the same look but it might work for you:
https://android--examples.blogspot.com/2015/05/how-to-use-numberpicker-in-android.html
After reading through various posts, examples, articles and Android documentation I found solution to my own question, It can be achieved by two ways:
First by using NumberPicker
Secondly by adding TextChangedListener to the EditText
Here is the code how I achieved it :
int noOfCups = 2;
EditText editTextNoOfCups;
editTextNoOfCups = (EditText) findViewById(R.id.edit_text_no_of_cups);
editTextNoOfCups.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) {
if(s.length() != 0) {
Log.e("pss", String.valueOf(s));
noOfCups = Integer.parseInt(String.valueOf(s));
}
}
#Override
public void afterTextChanged(Editable s) {
}
});
Here is the link to official Android documentation :
TextWatcher | Android Developers

Detect if content of EditText was changed by user or programmatically?

I would need a way to detect if the EditText has been changed by the user typing something or by the app changing the text programmatically. Any standard way of doing this? I guess I could always do something hackish like unsetting the TextWatcher before setText() and setting it back again afterwards, but there's got to be a better way of doing this... right?
I tried checking if the EditText is focused in the TextWatcher, but that was of little help since the EditTexts gets focused "semi-randomly" anyway when scrolling...
Background
I have a ListView with EditTexts in every listitem. I've sorted out the basic problem of storing the values for the EditTexts for reuse when the user scrolls.
I also have a TextWatcher that sums up the values in all EditTexts and displays the sum when the user edits the content of any of the EditTexts.
The problem is that when I'm scrolling the list and my custom adapter is reentering the stored values in the EditTexts on bindView(), that also triggers the TextWatchers afterTextChanged() method, causing the scrolling to lag because the summing-up-function is triggered.
This sorted itself out a long time ago, but for anyone who finds their way here looking for an answer, here's what I did:
I ended up setting the Tag of the EditText to some arbitrary value right before I'm about to change it programmatically, and changing the value, and then resetting the Tag to null. Then in my TextWatcher.afterTextChanged() method I check if the Tag is null or not to determine if it was the user or the program that changed the value. Works like a charm!
Something like this:
edit.setTag( "arbitrary value" );
edit.setText( "My Text Value" );
edit.setTag(null);
and then
public void afterTextChanged(Editable s) {
if( view.getTag() == null )
// Value changed by user
else
// Value changed by program
}
The accepted answer is perfectly valid, but I have another approach;
#Override
public void onTextChanged(CharSequence charSequence,
int start, int before, int count) {
boolean userChange = Math.abs(count - before) == 1;
if (userChange) {
}
}
It works by checking if the change was a single character.
This is not a fool-proof solution as copy-paste operations might be missed, and non-user changes of a single character will also be missed.
Depending on your use case, this might be a viable solution.
One thing that helped to me is having boolean canListenInput field. Use it inside of watcher.
email.addTextChangedListener(new TextWatcher() {
#Override
public void afterTextChanged(Editable s) {
if (canListenInput) {
emailChanged = true;
}
}
});
Clear it before changing text programmatically. Set it inside of onAttachedToWindow, (after state) restoration:
#Override
public void onAttachedToWindow() {
super.onAttachedToWindow();
canListenInput = true;
}
Depending on your use case (e.g. you are auto-populating this field when the user types into another field), you can also check if the view has focus, e.g.:
textView.doAfterTextChanged {
val isValueChangedByUser = textView.hasFocus()
// ...
}
I have created some extension methods to tackle this scenario
inline fun TextView.runTaggingCode(block: () -> Unit) {
this.setTag(R.string.tag_text_id, "set_from_code")
block()
this.setTag(R.string.tag_text_id, null)
}
fun TextView.isTaggedForCode() = this.getTag(R.string.tag_text_id) != null
where I have defined the R.string.tag_text_id as below
<string name="tag_text_id" translatable="false">dummy</string>
Now where I to use these methods, I will simply change my code as below,
override fun beforeTextChanged(
s: CharSequence, start: Int, count: Int,
after: Int,
) {
if (textView.isTaggedForCode()) {
return
}
textView.runTaggingCode {
// your logic here
}
}
But in case you don't want to change the same text view text, in it own TextWatcher you can also see the answer
You can do this by adding:
private String current = "";
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if(!s.toString().equals(current)){
[your_edittext].removeTextChangedListener(this);
//Format your string here...
current = formatted;
[your_edittext].setText(formatted);
[your_edittext].setSelection(formatted.length());
[your_edittext].addTextChangedListener(this);
}

Android Listview Searching

I am making a program in android using EditText and ListView. I want to search the ListView item using EditText above. After populate data to ListView, when user type text in EditText, the ListView will scroll to the position start with that text. Example: I have item: [apple, application, book, boy, car, cat, cash.....] when I type b in EditText then ListView will scroll to book. I want to use the listview.setSelection(position), but I don't know how can I get the position from my EditText search. I use the code below, it work well, but it seem slow when we search in EditText. How can I do this and run smoothly?
Thanks in advances.
I use following code:
YOUR_EDITTEXT.addTextChangedListener(new TextWatcher() {
public void onTextChanged(CharSequence s, int start, int before, int count) {
//LOGIC MAY DIFFER ACCORDING TO YOUR REQUIREMENT..
int POSITION = 0;
for(int i =0;i<list.size();i++) {
if(list.get(i).startsWith(s.toString()))
{
POSITION = i;
break;
}
}
listview.smoothScrollToPosition(POSITION);
}
public void afterTextChanged(Editable s) {
// TODO Auto-generated method stub
}
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
// TODO Auto-generated method stub
}
});
As you have 20,000 list entries, what you currently do is bound to be slow, as you do up to 20,000 startsWith() operations, everytime the user changes the text.
So what can you do:
Simplest solution:
Do NOT select an entry while the user types. Let him finish and click a search button and only then do what you currently do for every text change.
Database solution:
If you have your entries in a database, make a query to get the position. This is much much faster than searching in code. If you don't, can you put it into a database? Is it worth the effect or would the 'Simplest Solution' be good enough?
Try to be smart:
You can try to collect information while the user types, and use that for your advantage. Say the user begins to type Hello. When H is entered you find the first item that starts with H, say at position 1000. Now when the user types e, you don't have to start from the beginning but can start at position 1000 and so on. Of course you also have to handle cases when the user deletes a character or pastes another text and so on, so there is quite some programming logic involved here.

AutoCompleteTextView detect when selected entry from list edited by user

I have an AutoCompleteTextView I use to select an item from a long list. The user should only be able to select a predetermined item from the list. They should not be able to enter their own item.
The way I check to make sure they submit only an item from the list is to use setOnItemClickListener to trigger a boolean flag. The problem is that after the boolean flag is set to true, they can still edit the selected text of the item. I need to detect this and set the boolean flag to false again. How do I do this. I have seen a suggestion to use onKeyDown, but I am not sure how to implement this.
You can add text changed listener:
autoCompleteTextView.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) {
}
#Override
public void afterTextChanged(Editable s) {
}
});
Implement a TextWatcher, which will give you 3 methods which will constantly get call backs when someone changes the text.
If the string grows, your user is typing by himself again.
Use
AutoCompleteTextView#setOnItemSelectedListener()
- works like a charm.

Categories

Resources