OnCloseListener SearchView не працює


101

Я намагаюся додати підтримку для SearchViewAndroid 3.0+ ActionBar, але не можу OnCloseListenerпрацювати.

Ось мій код:

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

Пошук чудово працює, і кожен працює, за винятком OnCloseListener. Нічого не друкується в Logcat. Ось Logcat, коли я натискаю кнопку "Закрити":

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

Я переглянув документацію та зразки, але ніби нічого не змінило. Я запускаю його на Asus Transformer Prime і Galaxy Nexus, обидва на сендвіч-морозиві. Якісь ідеї?

Оновлення:

Так - System.out.println() робить роботу. Ось доказ:

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

Результати в цьому 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

Хм, працює добре для мене з Android 3.2, але НЕ для 4.0+
PJL

10
Піднята помилка, 25758
PJL

3
Я радий, що у мене не лише ця проблема. У когось є інші хаки, окрім наведених нижче?
bencallis

2
Я навчився двох речей, якщо showAsActionце встановлено always. У вікні пошуку є своя кнопка закриття, але якщо вона встановлена, ifRoom | collapseActionViewвона розгортається на панелі дій.
Беракі

Відповіді:


153

Я також зустрічаюся з цією проблемою, і не маю іншого вибору, окрім як відмовитись від "онколозистера". Натомість ви можете отримати свій менюItem, тоді setOnActionExpandListener. Потім переосмислити методи безперебійної роботи.

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

Я думаю, що ми говоримо лише про ActionVar SearchView, який є лише сот +
NKijak

не заважайте користуватися onCloseListener, просто використовуйте його разом із пунктом меню.
Роберт

12
Я думаю, ви можете використовувати MenuItemCompat.OnActionExpandListener для більш ранніх рівнів API: developer.android.com/reference/android/support/v4/view/…
Ripityom

2
Повна відповідь:if (Build.VERSION.SdkInt > BuildVersionCodes.NMr1) item.SetOnActionExpandListener(this); else MenuItemCompat.SetOnActionExpandListener(item, this);
FindOutIslamNow

61

Для Android API 14+ (ICS та новіших версій) використовуйте цей код:

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

Для отримання додаткової інформації: http://developer.android.com/guide/topics/ui/actionbar.html#ActionView

Посилання: onActionCollapse / onActionExpand


31

Для цієї проблеми я придумав щось подібне,

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
Що станеться, якщо ви завжди розширювались за допомогою setIconofiedByDefault (false)? Це не працює ... :(
Joan Casadellà

19

Я зіткнувся з такою ж проблемою на андроїді 4.1.1. Схоже, це відома помилка: https://code.google.com/p/android/isissue/detail?id=25758

У будь-якому випадку, як вирішення, я використовував слухач змін стану (коли SearchView відключається від рядка дій, він також очевидно закритий).

view.addOnAttachStateChangeListener(new OnAttachStateChangeListener() {

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

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

Вищий код добре працював у моєму випадку.


Я публікую ту саму відповідь тут: https://stackoverflow.com/a/24573266/2162924


Так, ця помилка була створена одразу після того, як я опублікував це питання. Дивіться коментарі до оригінального питання.
Мішель Бак

Ой добре, дивіться зараз. Але в будь-якому випадку, можливо, це рішення з слухачем змін стану може бути корисним і для інших.
Даріо

Не дивлячись на те, що OnCloseListener працює не так, як ви думаєте, це насправді приємне чисте рішення. Кудо!
welshk91

10

Я в кінцевому підсумку використав трохи хак, який добре працює для моєї мети - не впевнений, що він буде працювати з усіма цілями. У будь-якому випадку я роблю перевірку, щоб побачити, чи пошуковий запит порожній. Це насправді не пов’язано з SearchViewросійською мовою OnCloseListener- це все ще не працює!

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

7

Що ж, це вирішило мою проблему:

Пункт меню с 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"/>

і в діяльності

searchView.setOnCloseListener(new OnCloseListener() {

        @Override
        public boolean onClose() {

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

1
Встановлення alwaysзначення showAsActionатрибуту вирішує проблему. Важливим є те, що коли alwaysзначення is notприсутнє в showAsAction, розгорнуте SearchViewподає кнопку закриття (перехресний значок), лише якщо запит у SearchViewненульовий рядок. SearchView.onCloseClickedЩо ручки Кнопка закриття подій говорить , що зворотний виклик OnCloseListenerвикликається , тільки якщо запит порожній, якщо це не - це очищається перший - але потім, після того, як близько кліринг запит кнопки зникає , і ми не можемо поставити onCloseзворотний викликOnCloseListener
bpawlowski

1
Лише підказка: цей метод викликається, коли користувач закриває перегляд пошуку (цілком очевидно, але мені знадобилося кілька разів, щоб усвідомити). Перший раз, коли користувач натискає на X, він стирає текст, і я не отримав це оновлення, після другого клацання на X він закриває SearchView і викликається onClose. Сподіваюся, це допомагає!
Федеріко Альварес

4

Для того, щоб зробити OnCloseListenerроботу, переконайтеся, що showAsActionвстановлено alwaysв пункті меню пошуку.

<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

Я зіткнувся з тією ж проблемою, що і onCloseListener, який не звертається до SearchView. Зрозумійте, з помилки, піднятої в 25758 , і деяких публікацій, які я прочитав, щоб викликати onCloseListener, вам потрібно встановити:

searchView.setIconifiedByDefault(true);

Але в моєму випадку я хотів, щоб перегляд пошуку відкривався і не було ініційовано весь час. Мені вдається вирішити це, додавши ще один рядок нижче:

@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) призведе до відкриття searchView, незважаючи на те, що в попередньому рядку за замовчуванням встановлено значення iconified для істинного. Таким чином, мені вдалося створити як SearchView, який відкривається весь час, так і викликати його onCloseListener.


2

Створіть пункт меню з app:showAsActionнабором завжди.

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

При створенні групи SearchViewв onCreateOptionsMenuметоді зробити що - щось подібне

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

В search.setIconifiedByDefault(true)необхідно встановити для trueвикликати onClose()метод на SearchView.OnCloseListener()створений вище.



0

Причина того OnCloseListener, що не викликається, полягає в тому, що в коді Android є помилка - слухач викликається лише якщо ви також дзвоните setIconifiedByDefault(true).


7
Я щойно спробував додати setIconifiedByDefault (правда), але це не називається
Джузеппе

@Joseph Earl: У мене тут схожа проблема: stackoverflow.com/questions/43702055/… . Будь-які думки чи ідеї, як виправити?
AJW

0

здається, старий потік уже, але я подумав, що я отримав ту ж проблему API 18 на першому початку. Подивившись навколо, знайшов цю тему, ще годину прочитав javadoc спробував і помилився за те, що я не претендую, що повністю розумію в javadoc, наступна робота для мене зараз:

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

Я трохи пограв з true / false, що якимось чином має значення, і це працює для мене зараз. Сподіваємось, це може врятувати комусь час.


0

Це вирішення, але працює для мене

  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
    }

якщо натиснути на закрити searchView ->

D / клацання: натиснуто закрити


1
Відповіді з крапкою коду та деякими криптовалютами не особливо зрозумілі. Просто використовуйте природну мову, щоб описати, чому ви вважаєте, що це вирішує проблему, а потім показати реалізацію рішення.

0

Я зіткнувся з цією проблемою під час спроби виявити показ / відхилення SearchView. Я в кінцевому підсумку використовував іншого слухача, і він працював на те, що мені потрібно:

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

0

Я використав кнопку закриття SearchView і встановив на ній setOnClickListener

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

-2

В Android немає консолі, на якій можна було б увійти. Замість цього використовуйте рамку реєстрації андроїдів:

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

Дивіться також це питання: Чому "System.out.println" не працює в Android?


2
Неправда, це працює просто чудово. Будь ласка, дивіться моє оновлене питання - я додав рядок у метод onQueryTextChange, щоб довести це. Також спробував додати Log.d (), але це також нічого не відображало.
Мішель Бак

Ой, мій поганий! Схоже, десь по дорозі вони вирішили вивести System.out.println в Log.i. Удачі
Кріс Найт

-3

Існує дві загальні моделі для SearchView.setOnCloseListener(). Це дійсно стосується всіх слухачів, але я конкретно звертаюся з вашим питанням. Перший спосіб - створити функцію слухача і приєднати її до змінної члена, а другий - зробити клас реалізовувати інтерфейс і мати обробник функцією-членом.

Створення об'єкта для слухача виглядає приблизно так:

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

Реалізація слухача на рівні класу виглядає приблизно так:

public class MyClass implements OnCloseListener {
    private SearchView mSearchView;

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

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

Я не бачив жодних прикладів, які б створювали OnCloseListenerрекламу, як ви робили у своєму запитанні.


Гей Спаркі, дякую за коментар до цього. Я не бачу, як це може щось змінити. Вкладений слухач - це дійсний спосіб зробити це також, і він працює на Honeycomb, як ви можете бачити на основі коментарів тут. У мене не було жодних проблем із вкладеними слухачами на ICS, окрім цього - який знову працює на Honeycomb.
Мішель Бак

Під вкладеними слухачами я маю на увазі анонімні внутрішні класи.
Мішель Бак

Я згоден, що це не має значення. Я коментую лише те, що є в кодовій базі. Подивлюсь і побачу, чи можливо умови, в яких onClose були переглянуті.
Sparky

Я не впевнений, що ви розумієте Java - це називається анонімний внутрішній клас.
Джозеф Граф
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.