OnCloseListener SearchView tidak berfungsi

101

Saya mencoba menambahkan dukungan untuk SearchViewdi Android 3.0+ ActionBar, tetapi saya tidak bisa mulai OnCloseListenerbekerja.

Ini kode saya:

@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;
}

Pencarian berfungsi dengan baik dan semuanya berfungsi kecuali untuk OnCloseListener. Tidak ada yang dicetak ke Logcat. Ini Logcat untuk saat saya menekan tombol "Tutup":

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

Saya telah memeriksa dokumentasi dan sampel, tetapi sepertinya tidak ada yang mengubahnya. Saya menjalankannya di Asus Transformer Prime dan Galaxy Nexus, keduanya di Ice Cream Sandwich. Ada ide?

Memperbarui:

Ya - System.out.println() tidak bekerja. Berikut buktinya:

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

Hasil di Logcat ini:

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
Michell Bak
sumber
Hmm, Berfungsi baik untuk saya dengan Android 3.2 tetapi TIDAK untuk 4.0+
PJL
10
Bug yang meningkat, 25758
PJL
3
Saya senang bukan hanya saya yang mengalami masalah ini. Adakah yang punya peretasan lain selain yang di bawah ini?
bencallis
2
Saya telah mempelajari dua hal jika showAsActiondiatur ke always. Kotak pencarian memiliki dekat tombol sendiri tetapi jika sudah diatur untuk ifRoom | collapseActionViewmemperluas pada bar tindakan.
Beraki

Jawaban:

153

Saya juga menemui masalah ini, dan saya tidak punya pilihan selain menyerah "oncloselistener". Sebagai gantinya, Anda bisa mendapatkan menuItem Anda, lalu setOnActionExpandListener. Kemudian timpa metode yang tidak disederhanakan.

@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;
}
niki huang
sumber
Saya percaya kita hanya berbicara tentang SearchView ActionBar yang hanya sarang lebah +
NKijak
jangan repot-repot menggunakan onCloseListener, cukup gunakan yang ini dengan item menu Anda.
Robert
12
Saya pikir Anda dapat menggunakan MenuItemCompat.OnActionExpandListener untuk level API sebelumnya: developer.android.com/reference/android/support/v4/view/…
Ripityom
2
Jawaban lengkap:if (Build.VERSION.SdkInt > BuildVersionCodes.NMr1) item.SetOnActionExpandListener(this); else MenuItemCompat.SetOnActionExpandListener(item, this);
FindOutIslamNow
61

Untuk Android API 14+ (ICS dan lebih tinggi) gunakan kode ini:

// 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
    }
});

Untuk informasi lebih lanjut: http://developer.android.com/guide/topics/ui/actionbar.html#ActionView

Ref: onActionCollapse / onActionExpand

lomza
sumber
31

Untuk masalah ini saya menemukan sesuatu seperti ini,

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);

}
Ben Benson
sumber
1
Apa yang terjadi jika Anda selalu memperluas menggunakan setIconofiedByDefault (false)? Tidak bekerja ... :(
Joan Casadellà
19

Saya mengalami masalah yang sama di Android 4.1.1. Sepertinya ini adalah bug yang diketahui: https://code.google.com/p/android/issues/detail?id=25758

Bagaimanapun, sebagai solusinya saya menggunakan pendengar perubahan status (ketika SearchView dilepaskan dari bilah tindakan, itu juga ditutup dengan jelas).

view.addOnAttachStateChangeListener(new OnAttachStateChangeListener() {

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

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

Kode di atas bekerja dengan baik dalam kasus saya.


Saya memposting jawaban yang sama di sini: https://stackoverflow.com/a/24573266/2162924

Dario
sumber
Ya, bug itu dibuat tepat setelah saya memposting pertanyaan ini. Lihat komentar pada pertanyaan asli.
Michell Bak
Oh oke, lihat sekarang. Tapi bagaimanapun, mungkin solusi dengan listener perubahan status ini mungkin berguna untuk orang lain juga.
Dario
Meskipun mengecewakan karena OnCloseListener tidak berfungsi seperti yang Anda pikirkan, ini sebenarnya adalah solusi yang bagus dan bersih. Pujian!
welshk91
10

Saya akhirnya menggunakan sedikit retasan, yang berfungsi dengan baik untuk tujuan saya - tidak yakin itu akan berfungsi dengan semua tujuan. Bagaimanapun, saya sedang melakukan pemeriksaan untuk melihat apakah kueri penelusuran kosong. Ini tidak benar-benar terkait dengan SearchViewitu OnCloseListener- itu masih tidak berhasil!

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; }
        });
Michell Bak
sumber
7

Nah, ini memecahkan masalah saya:

Item menu dengan 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"/>

dan dalam aktivitas

searchView.setOnCloseListener(new OnCloseListener() {

        @Override
        public boolean onClose() {

            Log.i("SearchView:", "onClose");
            searchView.onActionViewCollapsed();
            return false;
        }
    });
Sushant
sumber
1
Menetapkan alwaysnilai ke showAsActionatribut memecahkan masalah. Yang penting adalah ketika alwaysnilai is notada di showAsAction, diperluas SearchViewmenampilkan tombol tutup (ikon silang) hanya jika kueri dalam SearchViewadalah String non-null. Yang SearchView.onCloseClickedmenangani peristiwa tombol tutup memberi tahu bahwa callback ke OnCloseListenerdipanggil hanya jika kueri kosong, jika tidak - dihapus terlebih dahulu - tetapi kemudian, setelah menghapus kueri, tombol tutup menghilang dan kami tidak dapat mengirimkan onClosepanggilan balik keOnCloseListener
bpawlowski
1
Sekadar petunjuk: metode ini dipanggil saat pengguna menutup tampilan pencarian (cukup jelas, tapi butuh beberapa kali untuk menyadarinya). Pertama kali pengguna mengklik X itu menghapus teks, dan saya tidak mendapatkan pembaruan itu, pada klik kedua pada X itu menutup SearchView dan onClose dipanggil. Semoga membantu!
Federico Alvarez
4

Untuk membuat OnCloseListenerpekerjaan, pastikan itu showAsActiondiatur ke alwaysdalam item menu pencarian.

<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>
Julio Betta
sumber
2

Saya mengalami masalah yang sama dengan onCloseListener yang tidak mengaktifkan SearchView. Pahami dari masalah bug yang diangkat pada 25758 , dan beberapa postingan yang telah saya baca, untuk menjalankan onCloseListener, Anda perlu menyetel:

searchView.setIconifiedByDefault(true);

Tetapi untuk kasus saya, saya ingin tampilan pencarian dibuka & tidak diikonkan sepanjang waktu. Saya berhasil menyelesaikan ini dengan menambahkan satu baris lagi di bawah ini:

@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) akan menyebabkan searchView terbuka, meskipun menyetel default ke iconified menjadi true di baris sebelumnya. Dengan cara ini, saya berhasil memiliki SearchView yang terbuka sepanjang waktu & membuatnya memanggil onCloseListener.

gkl
sumber
2

Buat item menu dengan app:showAsActionset ke selalu.

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

Saat membuat SearchViewdalam onCreateOptionsMenumetode, lakukan sesuatu yang serupa

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

The search.setIconifiedByDefault(true)harus ditetapkan untuk trueuntuk memanggil onClose()metode pada SearchView.OnCloseListener()buat di atas.

Ray Hunter
sumber
1

Untuk MenuItemCompatmasalah, saya menambahkan ViewTreeObserver untuk melacak status visibilitas. Anda dapat memeriksa jawaban saya di sini: https://stackoverflow.com/a/28762632/1633609

Sir NIkolay Cesar Yang Pertama
sumber
0

Alasan OnCloseListenertidak dipanggil adalah karena ada bug di kode Android - pendengar hanya dipanggil jika Anda juga menelepon setIconifiedByDefault(true).

Joseph Earl
sumber
7
Saya baru saja mencoba menambahkan setIconifiedByDefault (true) tetapi tidak dipanggil
Giuseppe
@ Joseph Earl: Saya mengalami masalah serupa di sini: stackoverflow.com/questions/43702055/… . Ada pemikiran atau ide tentang cara memperbaikinya?
AJW
0

Sepertinya utas lama sudah, tapi saya pikir saya mendapat masalah API 18 yang sama di awal pertama. Setelah mencari-cari di Google, menemukan utas ini, satu jam lagi membaca javadoc mencoba dan salah untuk sesuatu yang saya tidak pura-pura mengerti sepenuhnya di javadoc, berikut pekerjaan untuk saya sekarang:

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;
   }

Saya bermain dengan benar / salah sedikit, yang entah bagaimana membuat perbedaan, dan itu berhasil untuk saya sekarang. Semoga bisa menghemat waktu seseorang.

Sean
sumber
0

Ini adalah solusi tetapi berhasil untuk saya

  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;
                    }
}
Nativ
sumber
0
    searchView.setOnCloseListener {
        d("click", "close clicked")
        return@setOnCloseListener false
    }

jika Anda mengklik close searchView ->

D / klik: tutup diklik

Oleksandr Yahnenko
sumber
1
Jawaban dengan gumpalan kode dan beberapa kata samar tidak terlalu jelas. Cukup gunakan bahasa alami untuk mendeskripsikan mengapa menurut Anda ini menyelesaikan masalah, dan kemudian tunjukkan implementasi solusi.
0

Saya mengalami masalah ini saat mencoba mendeteksi tampilan / penutupan SearchView. Saya akhirnya menggunakan pendengar yang berbeda dan itu berfungsi untuk apa yang saya butuhkan:

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

Saya menggunakan tombol tutup SearchView dan menyetel setOnClickListener di atasnya

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

Tidak ada konsol di Android untuk masuk. Sebagai gantinya, gunakan framework logging android:

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

Lihat juga pertanyaan ini: Mengapa "System.out.println" tidak berfungsi di Android?

Chris Knight
sumber
2
Tidak benar, ini berfungsi dengan baik. Silakan lihat pertanyaan saya yang diperbarui - Saya telah menambahkan baris dalam metode onQueryTextChange untuk membuktikannya. Juga mencoba menambahkan Log.d (), tetapi itu juga tidak menampilkan apa pun.
Michell Bak
Ya ampun! Sepertinya di suatu tempat di sepanjang jalan mereka memutuskan untuk mengeluarkan System.out.println ke Log.i. Semoga berhasil
Chris Knight
-3

Ada dua pola umum untuk SearchView.setOnCloseListener(). Ini benar-benar berlaku untuk semua pendengar, tetapi saya menjawab pertanyaan Anda secara khusus. Cara pertama adalah membuat fungsi pendengar dan melampirkannya ke variabel anggota, dan yang kedua adalah membuat kelas mengimplementasikan antarmuka dan membuat penangan menjadi fungsi anggota.

Membuat objek pendengar terlihat seperti ini:

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

Menerapkan listener di tingkat kelas terlihat seperti ini:

public class MyClass implements OnCloseListener {
    private SearchView mSearchView;

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

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

Saya belum melihat contoh yang menciptakan OnCloseListenerad-hoc, seperti yang Anda lakukan dalam pertanyaan Anda.

Sparky
sumber
Hai Sparky, terima kasih telah mengomentari ini. Saya tidak begitu mengerti bagaimana hal itu seharusnya mengubah apa pun. Pendengar bersarang adalah cara yang valid untuk membuatnya juga, dan berfungsi di Honeycomb seperti yang Anda lihat berdasarkan komentar di sini. Saya tidak memiliki masalah dengan pendengar bersarang di ICS selain ini - yang lagi-lagi berfungsi di Honeycomb.
Michell Bak
Yang saya maksud dengan pendengar bersarang adalah kelas dalam anonim.
Michell Bak
Saya setuju bahwa itu tidak masalah. Saya hanya mengomentari apa yang ada di basis kode. Saya akan melihat dan melihat apakah mungkin kondisi di mana onClose didefinisikan ulang.
Sparky
Saya tidak yakin Anda memahami Java - ini disebut kelas dalam anonim.
Joseph Earl