SearchView OnCloseListener nie działa


101

Próbuję dodać obsługę SearchViewpaska ActionBar systemu Android 3.0+, ale nie mogę go uruchomić OnCloseListener.

Oto mój kod:

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.menu, menu);
    searchView = (SearchView) menu.findItem(R.id.search_textbox).getActionView();
    searchView.setOnQueryTextListener(new OnQueryTextListener() {
        @Override
        public boolean onQueryTextChange(String newText) {
            searchLibrary(newText);
            return false;
        }
        @Override
        public boolean onQueryTextSubmit(String query) { return false; }
    });
    searchView.setOnCloseListener(new OnCloseListener() {
        @Override
        public boolean onClose() {
            System.out.println("Testing. 1, 2, 3...");
            return false;
        }
    });
    return true;
}

Wyszukiwanie działa świetnie i wszystko działa, z wyjątkiem OnCloseListener. Nic nie jest drukowane do Logcat. Oto Logcat, kiedy naciskam przycisk „Zamknij”:

02-17 13:01:52.914: I/TextType(446): TextType = 0x0
02-17 13:01:57.344: I/TextType(446): TextType = 0x0
02-17 13:02:02.944: I/TextType(446): TextType = 0x0

Przejrzałem dokumentację i próbki, ale wydawało się, że nic tego nie zmienia. Używam go na Asus Transformer Prime i Galaxy Nexus, oba na Ice Cream Sandwich. Jakieś pomysły?

Aktualizacja:

Tak - System.out.println() ma pracę. Oto dowód:

   @Override
 public boolean onQueryTextChange(String newText) {
    System.out.println(newText + "hello");
    searchLibrary(newText);
    return false;
 }

Wyniki w tym Logcat:

02-17 13:04:20.094: I/System.out(21152): hello
02-17 13:04:24.914: I/System.out(21152): thello
02-17 13:04:25.394: I/System.out(21152): tehello
02-17 13:04:25.784: I/System.out(21152): teshello
02-17 13:04:26.064: I/System.out(21152): testhello

Hmm, działa OK dla mnie z Androidem 3.2, ale NIE dla 4.0+
— PJL

10
Podniesiony błąd, 25758
— PJL

3
Cieszę się, że nie tylko ja mam ten problem. Czy ktoś ma jakieś inne hacki niż ten poniżej?
— bencallis

2
Nauczyłem się dwóch rzeczy, jeśli showAsActionjest ustawione na always. Pole wyszukiwania ma własny przycisk zamykania , ale jeśli jest ustawione ifRoom | collapseActionView, rozwija się na pasku akcji.
— Beraki,

Odpowiedzi:


153

Ja też spotykam się z tym problemem i nie mam innego wyjścia jak zrezygnować z „oncloselistener”. Zamiast tego możesz pobrać swoje menuItem setOnActionExpandListener. Następnie zastąp metody bezimplents.

@Override
public boolean onMenuItemActionExpand(MenuItem item) {
    // TODO Auto-generated method stub
    Log.d("*******","onMenuItemActionExpand");
    return true;
}

@Override
public boolean onMenuItemActionCollapse(MenuItem item) {
    //do what you want to when close the sesarchview
    //remember to return true;
    Log.d("*******","onMenuItemActionCollapse");
    return true;
}

Myślę, że mówimy tylko o widoku SearchView ActionBar, który jest tylko plastrem miodu +
— NKijak

nie przejmuj się używaniem onCloseListener, po prostu użyj tego z elementem menu.
— Robert

12
Myślę, że możesz użyć MenuItemCompat.OnActionExpandListener na wcześniejszych poziomach API: developer.android.com/reference/android/support/v4/view/ ...
— Ripityom

2
Pełna odpowiedź:if (Build.VERSION.SdkInt > BuildVersionCodes.NMr1) item.SetOnActionExpandListener(this); else MenuItemCompat.SetOnActionExpandListener(item, this);
— FindOutIslamNow

61

W przypadku interfejsu API systemu Android 14+ (ICS i nowszych) użyj tego kodu:

// When using the support library, the setOnActionExpandListener() method is
// static and accepts the MenuItem object as an argument
MenuItemCompat.setOnActionExpandListener(menuItem, new OnActionExpandListener() {
    @Override
    public boolean onMenuItemActionCollapse(MenuItem item) {
        // Do something when collapsed
        return true;  // Return true to collapse action view
    }

    @Override
    public boolean onMenuItemActionExpand(MenuItem item) {
        // Do something when expanded
        return true;  // Return true to expand action view
    }
});

Więcej informacji: http://developer.android.com/guide/topics/ui/actionbar.html#ActionView

Ref: onActionCollapse / onActionExpand


31

W przypadku tego problemu wymyśliłem coś takiego,

private SearchView mSearchView;

@TargetApi(14)
@Override
public boolean onCreateOptionsMenu(Menu menu)
{

    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.conversation_index_activity_menu, menu);

    mSearchView = (SearchView) menu.findItem(R.id.itemSearch).getActionView();

    MenuItem menuItem = menu.findItem(R.id.itemSearch);

    int currentapiVersion = android.os.Build.VERSION.SDK_INT;
    if (currentapiVersion >= android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH)
    {
        menuItem.setOnActionExpandListener(new OnActionExpandListener()
        {

            @Override
            public boolean onMenuItemActionCollapse(MenuItem item)
            {
                // Do something when collapsed
                Log.i(TAG, "onMenuItemActionCollapse " + item.getItemId());
                return true; // Return true to collapse action view
            }

            @Override
            public boolean onMenuItemActionExpand(MenuItem item)
            {
                // TODO Auto-generated method stub
                Log.i(TAG, "onMenuItemActionExpand " + item.getItemId());
                return true;
            }
        });
    } else
    {
        // do something for phones running an SDK before froyo
        mSearchView.setOnCloseListener(new OnCloseListener()
        {

            @Override
            public boolean onClose()
            {
                Log.i(TAG, "mSearchView on close ");
                // TODO Auto-generated method stub
                return false;
            }
        });
    }


    return super.onCreateOptionsMenu(menu);

}

1
Co się stanie, jeśli zawsze rozszerzałeś za pomocą setIconofiedByDefault (false)? To nie działa ... :(
— Joan Casadellà

19

Napotkałem ten sam problem na Androidzie 4.1.1. Wygląda na to, że to znany błąd: https://code.google.com/p/android/issues/detail?id=25758

W każdym razie jako obejście zastosowałem nasłuchiwanie zmian stanu (gdy SearchView jest odłączony od paska akcji, jest również oczywiście zamknięty).

view.addOnAttachStateChangeListener(new OnAttachStateChangeListener() {

    @Override
    public void onViewDetachedFromWindow(View arg0) {
        // search was detached/closed
    }

    @Override
    public void onViewAttachedToWindow(View arg0) {
        // search was opened
    }
});

Powyższy kod działał dobrze w moim przypadku.


Tę samą odpowiedź zamieszczam tutaj: https://stackoverflow.com/a/24573266/2162924


Tak, ten błąd został utworzony zaraz po wysłaniu tego pytania. Zobacz komentarze do pierwotnego pytania.
— Michell Bak,

O ok, zobacz teraz. Ale w każdym razie może to obejście z odbiornikiem zmiany stanu może być przydatne również dla innych.
— Dario,

Rozczarowujące, że OnCloseListener nie działa tak, jak myślisz, jest to w rzeczywistości ładne, czyste rozwiązanie. Sława!
— welshk91

10

Skończyło się na tym, że użyłem trochę hacka, który działa dobrze w moim celu - nie jestem pewien, czy zadziała we wszystkich celach. W każdym razie sprawdzam, czy zapytanie wyszukiwania jest puste. To naprawdę nie jest związany z SearchView„s OnCloseListenerchociaż - to nadal nie działa!

searchView.setOnQueryTextListener(new OnQueryTextListener() {
            @Override
            public boolean onQueryTextChange(String newText) {
                if (newText.length() > 0) {
                    // Search
                } else {
                    // Do something when there's no input
                }
                return false;
            }
            @Override
            public boolean onQueryTextSubmit(String query) { return false; }
        });

8

Cóż, to rozwiązało mój problem:

Element menu z showAsAction="always"

<item
    android:id="@+id/action_search"
    android:icon="@drawable/ic_action_search"
    android:title="Search"
    app:actionViewClass="android.support.v7.widget.SearchView"
    app:showAsAction="always"/>

i w działalności

searchView.setOnCloseListener(new OnCloseListener() {

        @Override
        public boolean onClose() {

            Log.i("SearchView:", "onClose");
            searchView.onActionViewCollapsed();
            return false;
        }
    });

1
Ustawienie alwayswartości showAsActionatrybutu rozwiązuje problem. Ważną rzeczą jest to, że gdy alwayswartość jest is notobecna w showAsAction, rozwinięty SearchViewprzedstawia przycisk zamykania (ikona krzyżyka) tylko wtedy, gdy zapytanie w SearchViewnie jest ciągiem niezerowym. SearchView.onCloseClickedŻe uchwyty blisko WYDARZENIA przycisk mówi, że wywołania zwrotnego OnCloseListenernazywa się tylko wtedy, gdy kwerenda jest pusta, jeśli nie - to zdaje się pierwsza - ale potem, po bliskich zapytania rozliczeń przycisku znika i jesteśmy w stanie dostarczyć onClosewywołania zwrotnegoOnCloseListener
— bpawlowski

1
Wskazówka: ta metoda jest wywoływana, gdy użytkownik zamyka widok wyszukiwania (dość oczywiste, ale zajęło mi to kilka razy). Pierwszy raz, gdy użytkownik kliknie X, usuwa tekst, a ja nie otrzymałem tej aktualizacji, po drugim kliknięciu X zamyka SearchView i wywoływane jest onClose. Mam nadzieję, że to pomoże!
— Federico Alvarez

4

Aby OnCloseListenerdziałało, upewnij się, że showAsActionjest ustawione na alwaysw pozycji menu wyszukiwania.

<menu xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:app="http://schemas.android.com/apk/res-auto"
      xmlns:tools="http://schemas.android.com/tools"
      tools:context=".SearchActivity">

    <item
        android:id="@+id/search"
        android:title="@string/search"
        android:icon="@drawable/ic_search_toolbar"
        app:showAsAction="always"
        app:actionViewClass="android.support.v7.widget.SearchView"/>
</menu>

2

Napotkałem ten sam problem z onCloseListener nie wywołującym SearchView. Zrozum z problemu błędu zgłoszonego w 25758 i niektórych postów, które przeczytałem, aby wywołać onCloseListener, musisz ustawić:

searchView.setIconifiedByDefault(true);

Ale w moim przypadku chciałem, aby widok wyszukiwania był otwarty i nie był wyświetlany przez cały czas. Udaje mi się to rozwiązać, dodając jeszcze jedną linię poniżej:

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.search_bar, menu);
    SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
    searchView = (SearchView) menu.findItem(R.id.search).getActionView();
    searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
    searchView.setOnQueryTextListener(queryTextListener);
    searchView.setIconifiedByDefault(true);
    searchView.setIconified(false);
    return true;
}

SearchView.setIconified (false) spowoduje otwarcie searchView, pomimo ustawienia wartości domyślnej iconified na true w poprzednim wierszu. W ten sposób udało mi się mieć zarówno SearchView, który otwiera się cały czas, jak i wywoływał onCloseListener.


2

Utwórz pozycję menu z app:showAsActionustawieniem na zawsze.

<item   
 android:id="@+id/action_search"  
 android:title="..."  
 android:icon="..."  
 app:actionViewClass="android.support.v7.widget.SearchView"  
 app:showAsAction="always"/>

Tworząc SearchVieww onCreateOptionsMenumetodzie zrób coś podobnego

inflater.inflate(R.menu.menu_search, menu);
final MenuItem item = menu.findItem(R.id.action_search);
final SearchView search = (SearchView) item.getActionView();
search.setQueryHint(getString(R.string.search_brand_item));
search.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
  @Override
  public boolean onQueryTextSubmit(String query) {
    // add your code
    return false;
  }

  @Override
  public boolean onQueryTextChange(String newText) {
    // add your code 
    return false;
  }
});
search.setOnCloseListener(new SearchView.OnCloseListener() {
  @Override
  public boolean onClose() {
    // add your code here
    return false;
  }
});
search.setIconifiedByDefault(true); // make sure to set this to true

Należy search.setIconifiedByDefault(true)ustawić, aby truewywołać onClose()metodę na SearchView.OnCloseListener()utworzonym powyżej.



0

Powodem, dla którego OnCloseListenernie jest wywoływany, jest błąd w kodzie Androida - słuchacz jest wywoływany tylko wtedy, gdy również dzwonisz setIconifiedByDefault(true).


7
Właśnie próbowałem dodać setIconifiedByDefault (true), ale nie jest to wywoływane
— Giuseppe

@Joseph Earl: Mam podobny problem tutaj: stackoverflow.com/questions/43702055/… . Jakieś przemyślenia lub pomysły, jak to naprawić?
— AJW

0

wydaje się już stary wątek, ale myślałem, że mam ten sam problem z API 18 na początku. Po przeszukaniu go i znalezieniu tego wątku, kolejna godzina przeczytania wypróbowanego i błędnego javadoc dla czegoś, czego nie udaję w pełni rozumiem w javadoc, następująca praca dla mnie teraz:

searchView.setIconifiedByDefault(true);

   // OnQueryTextListener
   @Override
   public boolean onQueryTextSubmit(String query) {
      Log.d(tag, "onQueryTextSubmit: " + query);
      return true;
   }

   @Override
   public boolean onQueryTextChange(String query) {
      Log.d(tag, "onQueryTextChange: " + query);
      return true;
   }

   // OnCloseListener
   @Override
   public boolean onClose() {
      Log.w(tag, "onClose: ");
      return false;
   }

Bawiłem się trochę z prawdą / fałszem, to w jakiś sposób robi różnicę i teraz działa. Miejmy nadzieję, że może to komuś zaoszczędzić czas.


0

To obejście, ale zadziałało dla mnie

  searchView.setOnQueryTextListener(new android.widget.SearchView.OnQueryTextListener() {

                String lastText;

                @Override
                public boolean onQueryTextChange(final String newText) {
                    if (lastText != null && lastText.length() > 1 && newText.isEmpty()) {
                        // close ctn clicked

                        return true;
                    }
}

0
    searchView.setOnCloseListener {
        d("click", "close clicked")
        return@setOnCloseListener false
    }

jeśli klikniesz zamknij searchView ->

D / kliknięcie: zamknięcie kliknięto


1
Odpowiedzi zawierające fragment kodu i tajemnicze słowa nie są szczególnie jasne. Po prostu użyj języka naturalnego, aby opisać, dlaczego uważasz, że to rozwiązuje problem, a następnie pokaż wdrożenie rozwiązania.

0

Napotkałem ten problem, próbując wykryć wyświetlanie / odrzucanie SearchView. Skończyło się na tym, że użyłem innego słuchacza i działało to, czego potrzebowałem:

        setOnQueryTextFocusChangeListener { _, hasFocus ->
            if (hasFocus) {
                // SearchView is being shown
            } else {
                // SearchView was dismissed
            }
        }

0

Użyłem przycisku zamykania SearchView i ustawiłem na nim setOnClickListener

searchView.findViewById<ImageView>(R.id.search_close_btn).setOnClickListener {
    searchView.setQuery("", false)
    searchView.clearFocus()
}

-2

W systemie Android nie ma konsoli do logowania. Zamiast tego użyj struktury rejestrowania systemu Android:

Log.d("Test Tag", "Testing.  1, 2, 3...");

Zobacz także to pytanie: Dlaczego „System.out.println” nie działa w systemie Android?


2
Nieprawda, działa dobrze. Zobacz moje zaktualizowane pytanie - dodałem linię w metodzie onQueryTextChange, aby to udowodnić. Próbowałem także dodać Log.d (), ale to też nic nie wyświetlało.
— Michell Bak

Och, moja wina! Wygląda na to, że gdzieś po drodze zdecydowali się wyprowadzić System.out.println do Log.i. Powodzenia
— Chris Knight

-3

Istnieją dwa typowe wzorce dla SearchView.setOnCloseListener(). To naprawdę dotyczy wszystkich słuchaczy, ale odnoszę się konkretnie do twojego pytania. Pierwszy sposób polega na utworzeniu funkcji nasłuchującej i dołączeniu jej do zmiennej składowej, a drugi polega na tym, aby klasa implementowała interfejs i by funkcja obsługi była funkcją składową.

Tworzenie obiektu detektora wygląda następująco:

private SearchView mSearchView;
private final SearchView.OnCloseListener mOnCloseListener = 
    new SearchView.OnCloseListener() {
        public boolean onClose() {
            doStuff();
            return myBooleanResult;
        }
    };
mSearchView.setOnCloseListener(mOnCloseListener);

Implementacja detektora na poziomie klasy wygląda następująco:

public class MyClass implements OnCloseListener {
    private SearchView mSearchView;

    public MyClass(...) {
        mSearchView.setOnCloseListener(this);
    }

    @Override
    public boolean onClose() {
        doStuff();
        return false;
    }
}

Nie widziałem żadnych przykładów, które tworzyłyby OnCloseListenerad hoc, jak to zrobiłeś w swoim pytaniu.


Hej Sparky, dziękuję za komentarz. Naprawdę nie rozumiem, jak to powinno cokolwiek zmienić. Zagnieżdżony odbiornik jest również prawidłowym sposobem tworzenia go i działa na Honeycomb, jak widać na podstawie komentarzy tutaj. Nie miałem żadnych problemów z zagnieżdżonymi słuchaczami w ICS poza tym - co znowu działa na Honeycomb.
— Michell Bak

Przez zagnieżdżonych słuchaczy mam na myśli anonimowe klasy wewnętrzne.
— Michell Bak

Zgadzam się, że to nie ma znaczenia. Komentuję tylko to, co jest obecne w bazie kodu. Poszukam i zobaczę, czy może warunki, w których onClose zostały przedefiniowane.
— Sparky

Nie jestem pewien, czy rozumiesz Javę - nazywa się to anonimową klasą wewnętrzną.
— Joseph Earl
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.