MenuItemCompat.getActionView는 항상 null을 반환합니다


142

방금 v7 AppCompat지원 라이브러리를 구현 했지만 MenuItemCompat.getActionView테스트 한 모든 Android 버전에서 항상 null을 반환합니다 (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:actionViewClassapp: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 . 현재 스레드가 문제를 해결하지 못하면 솔루션을 살펴보십시오.
Boris Strandjev

4
좋은 답변입니다! app : actionViewClass의 "app"에도 "app"네임 스페이스에 대한 추가 xmlns 선언이 필요하다는 점을 분명히 밝힐 수도 있습니다.
jklp

3
그 말을 필요 android.support.v7.widget.SearchView클래스 (ActionBarCompat 라이브러리를 사용하는 경우 일반적인 실수로 알려져있다) 'android.support.v4.widget.SearchViewCompat'클래스와 혼동해서는 안
알렉스 Semeniuk

1
@jklp xmlns 선언을 추가하려고 <menu xmlns:app="http://schemas.android.com/apk/res/android" >하지만 오류가 발생 Attribute is missing the Android namespace prefix합니다. 당신은 그것을 어떻게 얻습니까?
anticafe

5
또한 android : showAsAction도 app : showAsAction으로 변경해야합니다. 또한 응용 프로그램뿐만 아니라 활동에 대한 테마가 appcompat 테마를 참조하고 있는지 확인하십시오. 마지막 것은, 응용 프로그램의 declartion는 " schemas.android.com/apk/res-auto "
Kalel 웨이드

85

제 경우에는 ProGuard 파일이었습니다. 이 줄을 추가해야합니다.

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

2
와, 왜이게 문제 야? 이것이 나를 위해 일한 유일한 것입니다.
Claud

2
+1. 꽤 명백하지만 여전히 언급 할 것입니다. SearchView를 다른 클래스로 확장 한 경우 해당 클래스의 경로를 유지하십시오!
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()돌아갑니다 null. 이 가져 오기를 변경 xmlns: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

문제는 Support V7 패키지에서 SearchView를 사용하고 API 레벨이 ..... 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
제공 한 코드 샘플이 문제를 해결하는 이유를 설명해 주시겠습니까? (나는 그렇게 생각합니다.)
Edgar N

4

나는 같은 오류 getActionView()가 있었고 내 메서드 는 항상 null을 반환했습니다. 그래서 나는 다음과 같이 만들었습니다.

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

사람들이 app : 또는 yourapp를 사용하고 있다는 게시물을 보았지만 정상적으로 사용했습니다 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

위의 Mohsen Afshin의 대답은 출발점이며 설정과 작동하도록 약간 조정했습니다.

@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 파일의 네임 스페이스도 변경됩니다.


이것은 우리의 문제였습니다. 우리는 Activity에서 android.widget.SearchView를 혼합했지만 menu_main.xml 파일에서 v7을 부분적으로 사용했습니다. .xml 파일도 app : actionViewClass = "android.support.v7.widget.SearchView"도 사용하고 있는지 확인하십시오.
gmcc051

0

다음은 지원 라이브러리 v7에서 searchView를 처리하는 방법에 대한 스 니펫입니다.

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

또한 Proguard를 사용하는 경우이를 구성에 추가하십시오.

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

코드를 포맷하려는 사람은 "WhiteSmith"라고하는 매우 알려진 포맷입니다. 다른 형식으로 변경해도 맛이 나기 때문에 더 나아지지 않습니다.
안드로이드 개발자

@JJD 예. 옳은. 다른 사람들만큼 흔하지는 않지만 오랫동안 사용했습니다. 원하는 경우 Eclipse에서 설정할 수 있습니다.
안드로이드 개발자

공유해 주셔서 감사합니다. 팀 구성원이나 기고자와의 원치 않는 토론을 피하기 때문에 기본값을 유지합니다.
JJD

@JJD 그것은 사실이다. 사무실에서는 기본 스타일과 약간 다른 스타일로 작업합니다. 어쨌든, 훌륭한 개발자는 모든 일반적인 서식 스타일을 처리 할 수 ​​있어야하며, "눈이 아프면"항상 다양한 서식 도구 (온라인 또는 IDE)에서 코드를 복사하고 형식을 지정할 수 있습니다.
안드로이드 개발자

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

Java 코드에서 수동으로 설정 하여이 작업을 수행했습니다.

<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를 확장 함

대체 : public class DemoActivity가 활동을 확장 함


2
왜 그렇게해야합니까? 답변을 좀 더 자세히 설명하십시오.
Robin Ellerkmann

ActionBarActivity를 확장하면 항상 null을 반환합니다. 그러나 나는 활동 만 확장하고 정상적으로 작동합니다
Hieu

지원 라이브러리의 일부이므로 ActionBarActivity를 사용할 때는 고유 한 네임 스페이스를 사용해야합니다. xml에서 android : showAsAction을 사용하고 있기 때문에 지원 라이브러리가 아닌 Activity와 작동하며 ActionBarActivity와 작동하지 않습니다.
Dennis K
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.