MenuItemCompat.getActionView her zaman null değerini döndürür


142

v7 AppCompatDestek kütüphanesini yeni uyguladım, ancak MenuItemCompat.getActionViewtest ettiğim her Android sürümünde her zaman null döndürüyor (4.2.2, 2.3.4 ....)

SearchViewİşlem çubuğunda görüntülenir ancak eylemleri dokunmak yanıt vermiyor ve göstermek için genişletmek değil onun EditTextve sadece basit bir simgeye gibidir.

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.menu, menu);

    MenuItem searchItem = menu.findItem(R.id.action_search);
    SearchView searchView = (SearchView) MenuItemCompat.getActionView(searchItem);
    if (searchView != null) {
        SearchViewCompat.setOnQueryTextListener(searchView, mOnQueryTextListener);
        searchView.setIconifiedByDefault(false);
        Log.d(TAG,"SearchView not null");
    } else
        Log.d(TAG, "SearchView is null");
    }
    return super.onCreateOptionsMenu(menu);
}

menu.xml

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:app="http://schemas.android.com/apk/res-auto">

    <item android:id="@+id/action_search"
          app:showAsAction="always|collapseActionView"
          android:icon="@drawable/abc_ic_search"
          android:title="@string/action_bar_search"
          android:actionViewClass="android.support.v7.widget.SearchView"/>

    <item android:id="@+id/action_refresh"
          android:icon="@drawable/refresh"
          android:title="@string/action_bar_refresh"
          app:showAsAction="ifRoom"/>
</menu>

Yanıtlar:


296

Sonunda çözümü buldum.

  1. Ad değiştirilmesi actionViewClassgelen android:actionViewClassetmekapp:actionViewClass

  2. Uygulama android.support.v7.widget.SearchView.OnQueryTextListenerakım aktivitesi için arayüz.

  3. Doğrudan kullanmak setOnQueryTextListeneryerineSearchViewCompat.setOnQueryTextListener

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
      MenuInflater inflater = getMenuInflater();
      inflater.inflate(R.menu.menu, menu);
    
      MenuItem searchItem = menu.findItem(R.id.action_search);
      SearchView searchView = (SearchView) MenuItemCompat.getActionView(searchItem);
      if (searchView != null) {
         searchView.setOnQueryTextListener(this);
      }
    
      return super.onCreateOptionsMenu(menu);
    }

3
Bu sorununuzu çözdüyse muhtemelen cevabınızı kabul etmelisiniz. Ben de benzer sorunları tartışan bir konu daha benzer sorunları olan tüm diğer insanları işaret etmek istiyorum: stackoverflow.com/q/18407171/1108032 . Mevcut iş parçacığı sorunlarınızı çözmezse, oradaki çözümlere bakmayı düşünün.
Boris Strandjev

4
Mükemmel cevap! Uygulamadaki "uygulama" nın: actionViewClass'ın "uygulama" ad alanı için ek bir xmlns bildirimi gerektirdiğini açıklığa kavuşturmak da gerekebilir.
jklp

3
android.support.v7.widget.SearchViewSınıfın 'android.support.v4.widget.SearchViewCompat' sınıfı (ActionBarCompat kitaplığı kullanılırken yaygın bir hata olarak bilinir) sınıfı ile karıştırılmaması gerektiğini söylemeliyim
Alex Semeniuk

1
@jklp xmlns bildirimi eklemeye çalışıyorum <menu xmlns:app="http://schemas.android.com/apk/res/android" >ama hata alıyorum Attribute is missing the Android namespace prefix. Anlıyor musunuz ve nasıl düzeltirsiniz?
anticafe

5
Ayrıca, android: showAsAction uygulamasına değiştirilmelidir: showAsAction da. Ayrıca etkinlik temanızın (yalnızca uygulama için değil) bir uygulama uyumu temasına başvurduğundan emin olun. Son şey, uygulama beyanı " schemas.android.com/apk/res-auto " dir
Wade

85

Benim durumumda ProGuard dosyasıydı. Bu satırı eklemeniz gerekiyor:

-keep class android.support.v7.widget.SearchView { *; }

2
Vay canına, bu neden bir şey? Benim için işe yarayan tek şey buydu.
Claud

2
+1. Oldukça açık, ama yine de bahsedeceğim - SearchView'i başka bir sınıfa genişletmeniz durumunda, o sınıfa giden yolu koruyun!
user2520215

42

Benim için yanlış bir menu.xmlad alanı alma işlemi bu soruna neden oldu.

Orijinalim menu.xml:

<menu xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:app="http://schemas.android.com/tools">
        <item android:id="@+id/action_search"
              android:title="@string/map_option_search"
              android:icon="@drawable/ic_action_search"
              app:showAsAction="collapseActionView|ifRoom"
              app:actionViewClass="android.support.v7.widget.SearchView"/>
</menu>

Görünüşe xmlns:app="http://schemas.android.com/tools"neden oluyordu MenuItemCompat.getActionView()dönmek için null. Bu içe aktarmanın değiştirilmesi xmlns:app="http://schemas.android.com/apk/res-auto"sorunu çözdü.

Yeni çalışma menu.xml:

<menu xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:app="http://schemas.android.com/apk/res-auto">
       <item android:id="@+id/action_search"
              android:title="@string/map_option_search"
              android:icon="@drawable/ic_action_search"
              app:showAsAction="collapseActionView|ifRoom"
              app:actionViewClass="android.support.v7.widget.SearchView"/>
</menu>

5

Sorun, destek V7 paketinden SearchView kullanmak ve belki API düzeyini ..... 22 olarak ayarlanmış olduğunu düşünüyorum.

Sorunu çözmek için kodunuzu aşağıdaki şekilde değiştirme:

menu.xml

<?xml version="1.0" encoding="UTF-8" ?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
    <item 
        android:id="@+id/action_search"
        android:icon="@drawable/actionbar_button_search"
        android:title="Search"
        android:showAsAction="always"
        android:actionViewClass="android.widget.SearchView" />
</menu> 

1
Verdiğiniz kod örneğinin sorunu neden çözdüğünü açıklayabilir misiniz? (Sanırım öyle.)
Edgar N

4

Aynı hatayla karşılaştım, yöntemim getActionView()her zaman null döndürüyordu. Yani, aşağıdaki şeyleri yaptım:

<item android:id="@+id/action_search"
      android:icon="@drawable/abc_ic_search"
      android:title="@string/search_title"
      android:showAsAction="always"
      android:actionViewClass="android.widget.SearchView"/>

Bazı yayınlarda insanların uygulamayı kullandığını gördüm: ya da yourapp, ama normal olarak kullandım android:ActionVewClass.

Benim onCreateOptionsMenuyöntemime göre:

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.feed, menu);

    // Associate searchable configuration with the SearchView
    SearchManager searchManager = 
        (SearchManager) getSystemService(Context.SEARCH_SERVICE);
    SearchView searchView = (SearchView) menu.findItem(R.id.action_search)
            .getActionView();
    searchView.setSearchableInfo(searchManager
            .getSearchableInfo(getComponentName()));

    return true;
}

Ve onCreateyöntemi koymayı unutmayın :

// enabling action bar app icon and behaving it as toggle button
getActionBar().setDisplayHomeAsUpEnabled(true);
getActionBar().setHomeButtonEnabled(true);

Bu, FragmentActivityve için "genişletme" etkinliğim için çok iyi çalışıyor ActionBarActivity.


2

Mohsen Afshin'in yukarıdaki cevabı başlangıç ​​noktamdı ve kurulumumla çalışmasını sağlamak için bazı değişiklikler yaptım:

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.menu, menu);
    MenuItem searchItem = menu.findItem(R.id.action_search);
    // SearchView searchView = (SearchView) MenuItemCompat
    //    .getActionView(searchItem);
    SearchView searchView = (SearchView) searchItem.getActionView();
    if (searchView != null) {
        searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
            @Override
            public boolean onQueryTextSubmit(String s) {
                // do something with s, the entered string
                query = s;
                Toast.makeText(getApplicationContext(), 
                    "String entered is " + s, Toast.LENGTH_SHORT).show();
                return true;
            }
            @Override
            public boolean onQueryTextChange(String s) {
                return false;
            }
        });
    }
    return super.onCreateOptionsMenu(menu);
}

menu.xml

<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    tools:context=".MainActivity" >

<item android:id="@+id/action_search"
    android:orderInCategory="5"
    android:title="Search"
    android:icon="@drawable/ic_action_search"
    android:showAsAction="ifRoom|collapseActionView"
    android:actionViewClass="android.widget.SearchView" />
</menu>

1

Ben aynı kodu vardı, ama android.support.v7.widget.SearchView;ben kullanmakta olduğum ithalat kullanmak yerine import android.widget.SearchView;. Bu nulldeğer ile benim sorunum düzeltildi . Bu yüzden sadece arama etkinliğinizde bu kodu değiştirin ve çalışacak ve ayrıca xml dosyasındaki ad alanını değiştirecektir.


Bu bizim sorunumuzdu, Aktivitede android.widget.SearchView'ın bir karışımı vardı, ancak menu_main.xml dosyamızda v7'nin kısmi bir kullanımı vardı. .Xml dosyasının aynı zamanda app: actionViewClass = "android.support.v7.widget.SearchView" da kullandığından emin olun.
gmcc051

0

Destek kütüphanesi v7'den searchView ile nasıl başa çıkılacağına dair bir pasaj:

@Override
public void onCreateOptionsMenu(final Menu menu,final MenuInflater inflater)
  {
  menu.clear();
  getActivity().getMenuInflater().inflate(...,menu);
  _searchView=(SearchView)MenuItemCompat.getActionView(_searchMenuItem);
  _searchView.setQueryHint(...);

  if(VERSION.SDK_INT<VERSION_CODES.HONEYCOMB)
    {
    final EditText searchTextView=(EditText)searchView.findViewById(R.id.search_src_text);
    if(searchTextView!=null)
      {
      searchTextView.setScroller(new Scroller(_context));
      searchTextView.setMaxLines(1);
      searchTextView.setVerticalScrollBarEnabled(true);
      searchTextView.setMovementMethod(new ScrollingMovementMethod());
      searchTextView.setTextColor(_context.getResources().getColor(App.getResIdFromAttribute(_context,android.R.attr.textColorPrimary)));
      }
    }
  _searchView.setOnQueryTextListener(new android.support.v7.widget.SearchView.OnQueryTextListener()
    {
    ...
    });
  MenuItemCompat.setActionView(_searchMenuItem,_searchView);
  MenuItemCompat.setOnActionExpandListener(_searchMenuItem,new OnActionExpandListener()
    {
    ...
    });
  super.onCreateOptionsMenu(menu,inflater);
  }


public static int getResIdFromAttribute(final Activity activity,final int attr)
  {
  if(attr==0)
    return 0;
  final TypedValue typedvalueattr=new TypedValue();
  activity.getTheme().resolveAttribute(attr,typedvalueattr,true);
  return typedvalueattr.resourceId;
  }

Ayrıca, Proguard kullanıyorsanız, bunu yapılandırmasına ekleyin:

-keep class android.support.v4.app.** { *; }
-keep interface android.support.v4.app.** { *; }
-keep class android.support.v7.widget.SearchView { *; }
-keepattributes *Annotation*

Kodu kim biçimlendirmek isterse, bu "WhiteSmith" adında çok bilinen bir biçimlendirmedir. Başka bir formata geçmek onu daha iyi yapmaz, çünkü bu bir zevk meselesidir.
android geliştirici

@JJD Evet. Doğru. Diğerleri kadar yaygın değil, ama çok uzun süre kullandım. İsterseniz Eclipse'de ayarlayabilirsiniz.
android geliştirici

Paylaşım için teşekkürler. Ekip üyeleriyle veya katkıda bulunanlarla çok fazla istenmeyen tartışmalardan kaçındığı için varsayılanla devam ediyorum.
JJD

@JJD Bu da doğrudur. ofiste varsayılandan biraz farklı bir stil ile çalışıyoruz. Her neyse, iyi bir geliştirici tüm yaygın biçimlendirme stillerini işleyebilmelidir ve eğer "gözleri incitirse" kodu her zaman kopyalayabilir ve çeşitli biçimlendirme araçlarında (çevrimiçi veya IDE'de) biçimlendirebilirsiniz.
android geliştirici

0

Genişleyen bir sınıfı kullanmaya çalıştığım farkla çok benzer bir sorunum vardı android.widget.ImageView

ProGuard kullanıyorsanız, bu sınıfa dahil olan yöntemlere izin vermeyi belirtmeniz gerekir.

-keep public class * extends android.widget.ImageView{
  public <init>(android.content.Context);
  public <init>(android.content.Context, android.util.AttributeSet);
  public <init>(android.content.Context, android.util.AttributeSet, int);
  public void set*(...);
}

http://proguard.sourceforge.net/manual/examples.html

Bu, "xml'den çağrılabilecek tüm gerekli kuruculara izin ver ve kullandığı özel ayarlayıcılara da izin ver (gerektiğinde daha fazlasını ekle)"


0

Java kodunda manuel olarak ayarlayarak yaptım:

<menu xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:id="@+id/user_info"
        android:title="@string/user_name_title"
        app:actionLayout="@layout/menu_item_username"
        android:showAsAction="always" />
</menu>

Düzen dosyası:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="200dp"
    android:layout_height="wrap_content"
    android:gravity="center_horizontal"
    android:orientation="horizontal">

    <TextView
        android:id="@+id/usr_name_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="10dp"
        android:layout_marginEnd="10dp"
        android:contentDescription="@string/user_info_image_des"
        android:padding="5dp"
        android:paddingStart="10dp"
        android:paddingEnd="10dp"
        android:text="@string/user_name_title"
        android:textStyle="bold"
        android:visibility="visible" />
</LinearLayout>

Sonra java kodunda:

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.connect_menu, menu);
        // show user name on the top of menu
        Log.e("menu", "Size: " + menu.size());
        MenuItem item = menu.getItem(0);
        item.setActionView(R.layout.menu_item_username);
        View v = item.getActionView();
        if (null == v) {
            Log.e("NULL POINTER EX", "NULL MENU VIEW");
        } else {
            TextView usrNameTitle = v.findViewById(R.id.usr_name_title);
            if (null != usrName && usrName.length() > 0) {
                usrNameTitle.setText(usrName);
            }
        }
        return true;
    }

resim açıklamasını buraya girin


-1

Kodlarını kaldırın: public class DemoActivity uzanır ActionBarActivity

Değiştiren: genel sınıf DemoActivity Etkinliği genişletir


2
Neden yapsın ki? Lütfen cevabınızı biraz daha ayrıntılı olarak açıklayınız.
Robin Ellerkmann

ActionBarActivity'yi genişlettiğimde, her zaman null değerini döndürür. Ama sadece aktiviteyi genişletiyorum, normal çalışıyor
Hieu

ActionBarActivity'yi destek kütüphanesinin bir parçası olduğu için kullanırken kendi ad alanınızı kullanmanız gerekir. Android'i kullandığınız için: xml'nizde showAsAction, Etkinlik (destek kitaplığından olmayan) ile çalışır ve ActionBarActivity ile çalışmaz
Dennis K
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.