MenuItemCompat.getActionView हमेशा शून्य देता है


142

मैंने अभी v7 AppCompatसमर्थन पुस्तकालय लागू किया है लेकिन MenuItemCompat.getActionViewमेरे द्वारा परीक्षण किए गए प्रत्येक Android संस्करण में हमेशा वापसी नल (4.2.2, 2.3.4 ....)

SearchViewकार्रवाई पट्टी में प्रदर्शित किया जाता है, लेकिन यह कार्रवाई को छूने के लिए जवाब नहीं है और दिखाने के लिए विस्तृत नहीं है अपने EditTextऔर सिर्फ एक सरल आइकन की तरह है।

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

जवाबों:


296

अंत में मुझे इसका हल मिल गया।

  1. के नाम स्थान बदलने actionViewClassसे android:actionViewClassकरने के लिएapp:actionViewClass

  2. android.support.v7.widget.SearchView.OnQueryTextListenerवर्तमान गतिविधि के लिए इंटरफ़ेस लागू करना ।

  3. के setOnQueryTextListenerबजाय सीधे उपयोग करेंSearchViewCompat.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
यदि इससे आपकी समस्या हल हो जाती है तो आपको शायद अपना उत्तर स्वीकार कर लेना चाहिए। मैं अन्य सभी लोगों को समान समस्याओं के साथ समान मुद्दों पर चर्चा करने वाले एक और सूत्र को इंगित करना चाहूंगा: stackoverflow.com/q/18407171/1108032 । यदि वर्तमान थ्रेड आपकी समस्याओं को हल नहीं करता है, तो वहां समाधानों पर विचार करें।
बोरिस स्ट्रैंडजेव

4
बहुत बढ़िया जवाब! यह स्पष्ट कर सकता है कि ऐप में "ऐप": एक्शन व्यूक्लास को "ऐप" नामस्थान के लिए अतिरिक्त xmlns घोषणा की भी आवश्यकता है।
1

3
यह कहने की आवश्यकता है कि android.support.v7.widget.SearchViewकक्षा को 'android.support.v4.widget.SearchViewCompat' वर्ग के साथ भ्रमित नहीं किया जाना चाहिए (जो एक्शनबर्पाट लाइब्रेरी का उपयोग करते समय एक सामान्य गलती के रूप में जाना जाता है)
एलेक्स सेमेनिएक

1
@jklp मैं xmlns घोषणा को जोड़ने की कोशिश करता हूं, <menu xmlns:app="http://schemas.android.com/apk/res/android" >लेकिन त्रुटि मिलती है Attribute is missing the Android namespace prefix। क्या आप इसे प्राप्त करते हैं, और आप इसे कैसे ठीक करते हैं?
15

5
यह भी ध्यान दें, android: showAsAction को ऐप में बदलना होगा: showAsAction भी। यह भी सुनिश्चित करें कि गतिविधि के लिए आपका विषय (न केवल आवेदन) एक appcompat विषय संदर्भित है। अंतिम बात, एप्लिकेशन घोषणा " स्कीमासएंड्रॉइड.com
apk

85

मेरे मामले में यह ProGuard फ़ाइल थी। आपको यह पंक्ति जोड़ने की आवश्यकता है:

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

2
वाह, यह बात क्यों है? यह केवल एक चीज थी जो मेरे लिए काम करती थी।
क्लेम

2
+1। बहुत स्पष्ट है, लेकिन मैं अभी भी उल्लेख करूंगा - यदि आपने SearchView को किसी अन्य वर्ग में विस्तारित कर दिया है, तो उस कक्षा का पथ प्रागार्ड में रखें!
14:25 बजे user2520215

42

मेरे लिए, एक गलत menu.xmlनाम स्थान आयात ने इस समस्या का कारण बना।

मेरा मूल 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>

ऐसा लग रहा है कि वापस लौटने xmlns:app="http://schemas.android.com/tools"का कारण था । इस आयात को बदलकर समस्या को ठीक किया गया।MenuItemCompat.getActionView()nullxmlns:app="http://schemas.android.com/apk/res-auto"

नया काम 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

मुझे लगता है कि समस्या यह है कि आप समर्थन V7 पैकेज से SearchView का उपयोग करते हैं और शायद आपका एपीआई स्तर ..... 22 ?? पर सेट है।

समस्या को ठीक करने के लिए अपने कोड को निम्न में बदलना:

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
क्या आप बता सकते हैं कि आपके द्वारा प्रदान किया गया कोड नमूना समस्या का समाधान क्यों करता है? (मुझे लगता है कि यह करता है।)
एडगर एन

4

मैं एक ही त्रुटि के साथ था, मेरी विधि getActionView()हमेशा शून्य लौट रही थी। तो, मैंने निम्नलिखित चीजें बनाई हैं:

<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"/>

मैंने कुछ पोस्टों में देखा कि लोग एप्लिकेशन का उपयोग कर रहे हैं: या आप उपयोग कर रहे हैं, लेकिन मैंने सामान्य रूप से उपयोग किया है android:ActionVewClass

मेरे onCreateOptionsMenuतरीके पर:

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

और onCreateविधि में रखना मत भूलना :

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

यह मेरी गतिविधि "के लिए" का विस्तार FragmentActivityऔर के लिए बहुत अच्छी तरह से काम करता है ActionBarActivity


2

मोहसिन अफशीन का जवाब मेरे शुरुआती बिंदु था और मैंने इसे अपने सेटअप के साथ काम करने के लिए कुछ ट्विक्स किए:

@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

मेरे पास समान कोड था, लेकिन आयात के बजाय android.support.v7.widget.SearchView;मैं उपयोग कर रहा था import android.widget.SearchView;। इसने मेरी समस्या को nullमूल्य के साथ ठीक कर दिया । तो बस इस कोड को अपनी खोज गतिविधि में बदलें और यह काम करेगा और xml फ़ाइल में नाम स्थान भी बदल देगा।


यह हमारा मुद्दा था, हमारे पास एक्टिविटी में android.widget.SearchView का मिश्रण था, लेकिन हमारे menu_main.xml फ़ाइल में v7 का आंशिक उपयोग था। बस सुनिश्चित करें कि .xml फ़ाइल भी ऐप का उपयोग कर रही है: actionViewClass = "android.support.v7.widget.SearchView" भी।
gmcc051

0

यहाँ कैसे समर्थन पुस्तकालय v7 से खोज दृश्य को संभालने का एक स्निपेट दिया गया है:

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

इसके अलावा, यदि आप प्रोगार्ड का उपयोग करते हैं, तो इसे इसके विन्यास में जोड़ें:

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

जो कोई भी कोड को प्रारूपित करना चाहता था, यह "व्हाइटस्मिथ" नामक एक बहुत ही ज्ञात प्रारूपण है। दूसरे प्रारूप में बदलाव करना बेहतर नहीं है, क्योंकि यह स्वाद का मामला है।
Android डेवलपर

@JDD हाँ। सही बात। यह दूसरों की तरह आम नहीं है, लेकिन मैंने इसे बहुत लंबे समय तक इस्तेमाल किया है। आप चाहें तो इसे ग्रहण पर सेट कर सकते हैं।
एंड्रॉइड डेवलपर

साझा करने के लिए धन्यवाद। मैं डिफ़ॉल्ट के साथ रहता हूं क्योंकि यह टीम के सदस्यों या योगदानकर्ताओं के साथ बहुत अवांछित चर्चा से बचता है।
JJD

@JJD यह भी सच है। कार्यालय में हम डिफ़ॉल्ट एक की तुलना में थोड़ा अलग शैली के साथ काम करते हैं। वैसे भी, एक अच्छे डेवलपर को सभी सामान्य स्वरूपण शैलियों को संभालने में सक्षम होना चाहिए, और यदि यह "आंखों को नुकसान पहुंचाता है" तो आप हमेशा कोड की प्रतिलिपि बना सकते हैं और इसे विभिन्न स्वरूपण टूल (ऑनलाइन, या आईडीई) पर प्रारूपित कर सकते हैं।
Android डेवलपर

0

मेरे पास एक बहुत ही समान मुद्दा था अंतर के साथ मैं एक वर्ग का उपयोग करने का प्रयास कर रहा था जो बढ़ाया गया था android.widget.ImageView

यदि आप ProGuard का उपयोग कर रहे हैं, तो आपको इस वर्ग में शामिल विधियों की अनुमति देने की आवश्यकता है।

-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

यह कहता है, "सभी आवश्यक निर्माणकर्ताओं को अनुमति दें जो xml से बुलाए जा सकते हैं और किसी भी कस्टम बसने वाले को इसके साथ ही उपयोग करने की अनुमति देते हैं (आवश्यकता से अधिक जोड़ें)"


0

मैंने जावा कोड में मैनुअल सेट द्वारा यह किया है:

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

लेआउट फ़ाइल:

<?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>

फिर जावा कोड में:

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

यहाँ छवि विवरण दर्ज करें


-1

निकालें कोड: सार्वजनिक वर्ग DemoActivity का विस्तार ActionBarActivity है

द्वारा बदलें: सार्वजनिक वर्ग DemoActivity फैली गतिविधि


2
वह ऐसा क्यों करे? कृपया अपने उत्तर को थोड़ा और विस्तार से बताएं।
रॉबिन एल्केरमैन

जब मैं ActionBarActivity का विस्तार करता हूं, तो यह वापसी के लिए शून्य हो जाता है। लेकिन मैं केवल गतिविधि का विस्तार करता हूं, यह सामान्य काम करता है
Hieu

ActionBarActivity का उपयोग करते समय आपको अपने स्वयं के नामस्थान का उपयोग करने की आवश्यकता होती है क्योंकि यह समर्थन पुस्तकालय का एक हिस्सा है। जब से आप android का उपयोग कर रहे हैं: showAsAction आपके xml में यह गतिविधि के साथ काम करता है (जो समर्थन पुस्तकालय से नहीं है) और ActionBarActivity के साथ काम नहीं करता है
डेनिस के
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.