Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
306 views
in Technique[技术] by (71.8m points)

android - getActionProvider: item does not implement SupportMenuItem

I am trying to implement a ShareActionProvider using the support library in a contextual action bar in my fragment. I face no issues implementing it in a normal action bar( onCreateOptionsMenu() ), but when i try it in the CAB ( onCreateActionMode() in MultiModeListener interface), I get the error :

getActionProvider: item does not implement SupportMenuItem; returning null

Looking at the Android source at https://cells-source.cs.columbia.edu/plugins/gitiles/platform/frameworks/support/+/30837f1095c803f332f4a1c3f0917c8afdd50156/v4/java/android/support/v4/view/MenuItemCompat.java, the problem seems to be because my MenuItem is not an instance of SupportMenuItem :

 public static ActionProvider getActionProvider(MenuItem item) {
    if (item instanceof SupportMenuItem) {
        return ((SupportMenuItem) item).getSupportActionProvider();
    }

    // TODO Wrap the framework ActionProvider and return it
    Log.w(TAG, "getActionProvider: item does not implement SupportMenuItem; returning null");
    return null;
}

Any ideas on how i can go about resolving this ?

Manifest :

<activity
            android:name=".myactivity_ActionBarActivity"
            android:theme="@style/Theme.AppCompat.Light"
            android:windowSoftInputMode="stateUnchanged">
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />
                <category android:name="android.intent.category.DEFAULT" />
                </intent-filter>
            </activity>

Activity :

import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;

public class myactivity_ActionBarActivity extends ActionBarActivity{
    @Override
    public void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        setContentView(R.layout.actionbaractivity_layout); //loads a fragment

    }
}

fragment :

import android.support.v7.widget.ShareActionProvider;
import android.support.v4.view.MenuItemCompat;
import android.view.MenuItem;
import android.view.Menu;
import android.support.v4.app.Fragment;

...
...

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    ...
    ...
    //Handle Action mode events
    myListView.setMultiChoiceModeListener(new MultiChoiceModeListener() {
        private ShareActionProvider mShareActonProvider;
        ....
        ....
        @Override
        public boolean onCreateActionMode(ActionMode mode,
        Menu menu) {
            MenuInflater inflater = mode.getMenuInflater();
            inflater.inflate(R.menu.chatsession_contextmenu, menu);

            //get the ShareActionProvider from the menu item
            MenuItem item = menu.findItem(R.id.share_menu);
            mShareActonProvider = (ShareActionProvider) MenuItemCompat.getActionProvider(item);

            return true;
        }
    }

    ...
    ...
}

Menu layout file :

<?xml version="1.0" encoding="utf-8" ?>
    <menu xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:myapp="http://schemas.android.com/apk/res-auto">
        <item
            android:id="@+id/delete_menu"
            android:title="Delete message"
            myapp:showAsAction="ifRoom|withText"
            android:icon="@drawable/ic_action_discard">
        </item>

        <item
            android:id="@+id/share_menu"
            android:title="Share message"
            myapp:showAsAction="ifRoom|withText"
            android:icon="@drawable/ic_action_share"
            myapp:actionProviderClass="android.support.v7.widget.ShareActionProvider">
            </item>

    </menu>

Edit 1 :

The root of the problem seems to be the difference in the Menu object that is being passed as argument to onCreateActionMode(ActionMode mode, Menu menu) and onCreateOptionsMenu(Menu menu, MenuInflater inflater). Only the one in onCreateOptionsMenu has the MenuWrapperICS. Here is a screenshot of both objects in debug mode :

onCreateActionMode(ActionMode mode, Menu menu) :

enter image description here

onCreateOptionsMenu(Menu menu, MenuInflater inflater) :

enter image description here

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

The problem is that the MultipleModeListener interface extends the android.view.ActionMode.Callback, as can be seen in the source code at http://androidxref.com/4.4.2_r2/xref/frameworks/base/core/java/android/widget/AbsListView.java#6301. If you are using ShareActionProvider from the support library, you need the android.support.v7.view.ActionMode.Callback instead.

The solution is to create your own ActionMode.CallBack implementation instead of using the framework's MultipleModeListener. This way you make sure that the support libraries are being used wherever required.

For example :

  1. Import the v7 version of ActionMode and ActionBarActivity in your fragment

    import android.support.v7.view.ActionMode;
    import android.support.v7.app.ActionBarActivity;
    
  2. Create an onClickListener for your list view and use startSupportActionMode to start your custom ActionMode.CallBack implementation

    myListView.setItemsCanFocus(false);
    myListView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
    actionMode = null;
    myListView.setOnItemClickListener(new OnItemClickListener(){
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id){
                    if(myListView.getCheckedItemCount() == 0){
                        actionMode.finish();
                        return;
                    }
    
                        if(actionMode == null){
                            actionMode = ((ActionBarActivity)getActivity()).startSupportActionMode(new ContextualActionBar());
                        }
    
                }
            });
    
  3. Create your custom ActionMode.Callback implementation

    private class ContextualActionBar implements ActionMode.Callback{
        private ShareActionProvider mShareActionProvider;
    
        @Override
        public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
            switch(item.getItemId()){
    
            case R.id.share_menu :
                mode.finish();
                return true;
    
            default :
                return false;
            }
        }
    
        @Override
        public boolean onCreateActionMode(ActionMode mode, Menu menu) {
            MenuInflater inflater = mode.getMenuInflater();
            inflater.inflate(R.menu.chatsession_contextmenu, menu);
    
            //Initialize the ShareActionProvider
            MenuItem shareMenuItem = menu.findItem(R.id.share_menu);
            mShareActionProvider = (ShareActionProvider) MenuItemCompat.getActionProvider(shareMenuItem);
            Intent shareIntent = new Intent(Intent.ACTION_SEND);
            shareIntent.setType("text/plain");
            shareIntent.putExtra(Intent.EXTRA_TEXT, "test message");
            mShareActionProvider.setShareIntent(shareIntent);
            return true;
        }
    
        @Override
        public void onDestroyActionMode(ActionMode mode) {
            //Nullify the actionMode object 
            //so that the onClickListener can identify whether the ActionMode is ON  
            actionMode = null;
    
            //Uncheck all checked messages 
            SparseBooleanArray selectedItems = myListView.getCheckedItemPositions();
            for(int i=0;i<selectedItems.size();i++){
                myListView.setItemChecked(selectedItems.keyAt(i), false);
            }
        }
    
        @Override
        public boolean onPrepareActionMode(ActionMode arg0, Menu arg1) {
            // TODO Auto-generated method stub
            return false;
        }
    
    }
    

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...