Android: AutoCompleteTextView wyświetla sugestie, gdy nie wprowadzono żadnego tekstu

129

Używam AutoCompleteTextView, gdy użytkownik go kliknie, chcę wyświetlać sugestie, nawet jeśli nie ma tekstu - ale setThreshold(0)działa dokładnie tak samo, jak setThreshold(1)- więc użytkownik musi wprowadzić co najmniej 1 znak, aby wyświetlić sugestie.

fhucho
źródło
Robię coś podobnego TUTAJ !!! stackoverflow.com/questions/12854336/…
toobsco42

Odpowiedzi:

162

To jest udokumentowane zachowanie :

Gdy thresholdjest mniejsze lub równe 0, stosuje się próg 1.

Możesz ręcznie wyświetlić listę rozwijaną za pośrednictwem showDropDown(), więc być może możesz zorganizować wyświetlanie jej, kiedy chcesz. Lub podklasa AutoCompleteTextViewi przesłonięcie enoughToFilter(), zwracając truecały czas.

CommonsWare
źródło
7
ShowDropDown () wydaje się działać dobrze przy ustawianiu onClickListener, ale podklasa nie działa, dopóki użytkownik nie wprowadzi litery i nie wróci do usunięcia, ale nie tylko z onClick ...
amj
10
Działa to doskonale w połączeniu z OnFocusChangeListener, który wywołuje metodę showDropDown (), gdy widok zyskuje fokus.
Grishka,
Muszę również zastąpić onFocusChanged, jak stwierdził w odpowiedzi poniżej @David Vávra
Gabriel
4
@commonsWare showDropDown()nie działa w afterTextChangedwhen .getText().toString().length()==0. DLACZEGO
Prabs
1
Pomaga mi tylko zastąpienie wystarczająco dużoToFilter. Dziękuję Ci!
Fedir Tsapana
122

Oto moja klasa InstantAutoComplete . To coś pomiędzy AutoCompleteTextViewa Spinner.

import android.content.Context;  
import android.graphics.Rect;
import android.util.AttributeSet;
import android.widget.AutoCompleteTextView;

public class InstantAutoComplete extends AutoCompleteTextView {

    public InstantAutoComplete(Context context) {
        super(context);
    }

    public InstantAutoComplete(Context arg0, AttributeSet arg1) {
        super(arg0, arg1);
    }

    public InstantAutoComplete(Context arg0, AttributeSet arg1, int arg2) {
        super(arg0, arg1, arg2);
    }

    @Override
    public boolean enoughToFilter() {
        return true;
    }

    @Override
    protected void onFocusChanged(boolean focused, int direction,
            Rect previouslyFocusedRect) {
        super.onFocusChanged(focused, direction, previouslyFocusedRect);
        if (focused && getAdapter() != null) {
            performFiltering(getText(), 0);
        }
    }

}

Użyj go w swoim xml w ten sposób:

<your.namespace.InstantAutoComplete ... />
David Vávra
źródło
12
To wspaniale! Chciałbym również zwrócić uwagę, że w pliku XML układu musisz zmienić <AutoCompleteTextView ... />na <your.namespace.InstantAutoComplete ... />. Straciłem trochę czasu, zastanawiając się nad tym :)
Jules Colle
3
Świetna klasa - tylko sugestia byłaby w metodzie onFocusChanged, zmień "if (focus)" na "if (focus && getAdapter ()! = Null)".
Jacob Tabak
W przypadku AndroidX rozszerz androidx.appcompat.widget.AppCompatAutoCompleteTextView.
Mahmudul Hasan Shohag
To nie pokazuje menu po zmianach orientacji.
Miha_x64
46

Najprostszy sposób:

Po prostu użyj setOnTouchListener i showDropDown ()

AutoCompleteTextView text;
.....
.....
text.setOnTouchListener(new View.OnTouchListener(){
   @Override
   public boolean onTouch(View v, MotionEvent event){
      text.showDropDown();
      return false;
   }
});
user1913469
źródło
1
Aby było to jeszcze lepsze, użyj if (! Text.isPopupShowing ()) {text.showDropDown (); }
Boldijar Paul
7
niezbyt częste, ale to nie zadziała, jeśli użytkownik nie dotknie, aby przejść do tego EditText. Na przykład podczas korzystania z pilota z przyciskami (na przykład Android TV).
programista Androida
2
Powinieneś użyć setOnFocusChanged. Ktoś może mieć klawiaturę i nacisnąć klawisz TAB lub za pomocą myszy i dotyku słuchacz nie zostanie wywołany.
barwnikk
onTouchListener będzie wywoływany w różnym czasie dla jednego dotknięcia - np .: zdarzeniem może być MotionEvent.ACTION_DOWN, MotionEvent.ACTION_UP. Więc lepiej jest sprawdzić konkretne wydarzenie i napisać kod
Govind
18

Kod Destila działa świetnie, gdy jest tylko jeden InstantAutoCompleteobiekt. Nie działało to jednak z dwoma - nie mam pojęcia, dlaczego. Ale kiedy showDropDown()wstawię (tak jak radzi CommonsWare) w onFocusChanged()ten sposób:

@Override
protected void onFocusChanged(boolean focused, int direction,
        Rect previouslyFocusedRect) {
    super.onFocusChanged(focused, direction, previouslyFocusedRect);
    if (focused) {
        performFiltering(getText(), 0);
        showDropDown();
    }
}

to rozwiązało problem.

To tylko dwie poprawnie połączone odpowiedzi, ale mam nadzieję, że może to komuś zaoszczędzić trochę czasu.

Alex
źródło
2
Twoje dodanie pomogło, ale wystąpił błąd, jeśli w InstantAutoComplete był tekst i zmieniła się orientacja ekranu. Naprawiłem to sprawdzeniem widoczności okna, opublikowałem nowy kod tutaj: gist.github.com/furycomptuers/4961368
FuryComputers
10

Adapter początkowo nie przeprowadza filtrowania.
Jeśli filtrowanie nie jest wykonywane, lista rozwijana jest pusta.
więc być może będziesz musiał uruchomić filtrowanie na początku.

Aby to zrobić, możesz wywołać filter()po zakończeniu dodawania wpisów:

adapter.add("a1");
adapter.add("a2");
adapter.add("a3");
adapter.getFilter().filter(null);
david m lee
źródło
7

Możesz użyć onFocusChangeListener;

TCKimlikNo.setOnFocusChangeListener(new OnFocusChangeListener() {

        @Override
        public void onFocusChange(View v, boolean hasFocus) {
            if (hasFocus) {
                TCKimlikNo.showDropDown();

            }

        }
    });
Göksel Güren
źródło
7

Powyższa odpowiedź Destila prawie działa, ale ma jeden subtelny błąd. Gdy użytkownik po raz pierwszy ustawi fokus na polu, to działa, jednak jeśli opuści, a następnie wróci do pola, lista rozwijana nie zostanie wyświetlona, ​​ponieważ wartość mPopupCanBeUpdated nadal będzie fałszywa od momentu ukrycia. Rozwiązaniem jest zmiana metody onFocusChanged na:

@Override
protected void onFocusChanged(boolean focused, int direction,
        Rect previouslyFocusedRect) {
    super.onFocusChanged(focused, direction, previouslyFocusedRect);
    if (focused) {
        if (getText().toString().length() == 0) {
            // We want to trigger the drop down, replace the text.
            setText("");
        }
    }
}
Colin Stewart
źródło
ale to również oznacza, że ​​tekst zostanie zresetowany (choć zwykle jest to całkiem w porządku) ...
programista Androida
3

Aby utworzyć CustomAutoCompleteTextView. 1. zastąpić metodę setThreshold, wystarczającoToFilter, onFocusChanged

public class CustomAutoCompleteTextView  extends AutoCompleteTextView { 

    private int myThreshold; 

    public CustomAutoCompleteTextView  (Context context) { 
        super(context); 
    } 

    public CustomAutoCompleteTextView  (Context context, AttributeSet attrs, int defStyle) { 
        super(context, attrs, defStyle); 
    } 

    public CustomAutoCompleteTextView  (Context context, AttributeSet attrs) { 
        super(context, attrs); 
    } 
     //set threshold 0.
    public void setThreshold(int threshold) { 
        if (threshold < 0) { 
            threshold = 0; 
        } 
        myThreshold = threshold; 
    } 
    //if threshold   is 0 than return true
    public boolean enoughToFilter() { 
         return true;
        } 
    //invoke on focus 
    protected void onFocusChanged(boolean focused, int direction,
            Rect previouslyFocusedRect) {
                    //skip space and backspace 
        super.performFiltering("", 67);
        // TODO Auto-generated method stub
        super.onFocusChanged(focused, direction, previouslyFocusedRect);

    }

    protected void performFiltering(CharSequence text, int keyCode) {
        // TODO Auto-generated method stub
        super.performFiltering(text, keyCode);
    }

    public int getThreshold() { 
        return myThreshold; 
    } 
}
sanjeev vishnoi
źródło
3

Spróbuj

    searchAutoComplete.setThreshold(0);
    searchAutoComplete.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) {//cut last probel
                    if (charSequence.length() > 1) {
                        if (charSequence.charAt(charSequence.length() - 1) == ' ') {
                            searchAutoComplete.setText(charSequence.subSequence(0, charSequence.length() - 1));
                            searchAutoComplete.setSelection(charSequence.length() - 1);
                        }
                    }
                   }


                @Override
                public void afterTextChanged(Editable editable) {
                }
            });


    //when clicked in autocomplete text view
        @Override
        public void onClick(View view) {
            switch (view.getId()) {
              case R.id.header_search_etv:
                    if (searchAutoComplete.getText().toString().length() == 0) {
                        searchAutoComplete.setText(" ");
                    }
             break;
            }
        }):
Rafayel Pogosyan
źródło
3

Po prostu wywołaj tę metodę za dotknięciem lub kliknięciem zdarzenia autoCompleteTextView lub gdzie chcesz.

autoCompleteTextView.showDropDown()
Dalvinder Singh
źródło
0

To zadziałało dla mnie, pseudo kod:

    public class CustomAutoCompleteTextView extends AutoCompleteTextView {
    public CustomAutoCompleteTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public boolean enoughToFilter() {
        return true;
    }

    @Override
    protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
        super.onFocusChanged(focused, direction, previouslyFocusedRect);
        if (focused) {
            performFiltering(getText(), 0);
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        this.showDropDown();
        return super.onTouchEvent(event);
    }
}

Nasif Md. Tanjim
źródło
0

Po prostu wklej to do swojej metody onCreate w Javie

final ArrayAdapter<String> arrayAdapter = new ArrayAdapter<>(
            this, android.R.layout.simple_spinner_dropdown_item,
            getResources().getStringArray(R.array.Loc_names));

    textView1 =(AutoCompleteTextView) findViewById(R.id.acT1);
    textView1.setAdapter(arrayAdapter);

    textView1.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(final View arg0) {
            textView1.setMaxLines(5);
            textView1.showDropDown();

        }
    });

A to do twojego pliku Xml ...

<AutoCompleteTextView
            android:layout_width="200dp"
            android:layout_height="30dp"
            android:hint="@string/select_location"
            android:id="@+id/acT1"
            android:textAlignment="center"/>

I utwórz tablicę w string.xml w Values ​​...

<string-array name="Loc_names">

        <item>Pakistan</item>
        <item>Germany</item>
        <item>Russia/NCR</item>
        <item>China</item>
        <item>India</item>
        <item>Sweden</item>
        <item>Australia</item>
    </string-array>

I jesteś gotowy.

Lalit Fauzdar
źródło
0

Siedem lat później, chłopaki, problem pozostaje ten sam. Oto klasa z funkcją, która zmusza to głupie wyskakujące okienko do wyświetlania się w każdych warunkach. Wszystko, co musisz zrobić, to ustawić adapter do swojego AutoCompleteTextView, dodać do niego trochę danych i wywołać showDropdownNow()funkcję w dowolnym momencie.

Kredyty dla @David Vávra. Opiera się na jego kodzie.

import android.content.Context
import android.util.AttributeSet
import android.widget.AutoCompleteTextView

class InstantAutoCompleteTextView : AutoCompleteTextView {

    constructor(context: Context) : super(context)

    constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs)

    constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)

    override fun enoughToFilter(): Boolean {
        return true
    }

    fun showDropdownNow() {
        if (adapter != null) {
            // Remember a current text
            val savedText = text

            // Set empty text and perform filtering. As the result we restore all items inside of
            // a filter's internal item collection.
            setText(null, true)

            // Set back the saved text and DO NOT perform filtering. As the result of these steps
            // we have a text shown in UI, and what is more important we have items not filtered
            setText(savedText, false)

            // Move cursor to the end of a text
            setSelection(text.length)

            // Now we can show a dropdown with full list of options not filtered by displayed text
            performFiltering(null, 0)
        }
    }
}
mykolaj
źródło
0

na FocusChangeListener, sprawdź

if (hasFocus) {
            tvAutoComplete.setText(" ")

w filtrze wystarczy przyciąć tę wartość:

filter { it.contains(constraint.trim(), true) }

i pokaże wszystkie sugestie, gdy skupisz się na tym widoku.

beokh
źródło