Search code examples
androidandroid-support-librarycontextual-action-barandroid-actionbaractivity

Support Contextual Action Bar never inflates


In order to add a contextual action bar to my application using the support action bar v7 library I implemented it like this :

My ActionBarActivity (support v7) :

    package com.supinfo.cubbyhole.mobileapp.activities;

import com.supinfo.cubbyhole.mobileapp.R;

import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.support.v7.view.ActionMode;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;

public class Homy extends ActionBarActivity {

    private ActionMode mActionMode;
    private ListView list;

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_home);

        // I instantiate and fill my list with custom adapter ... All is fine
        list = (ListView) findViewById(R.id.home_list);

        String[] array = {"test", "test2", "test3"};
        list.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, android.R.id.text1, array));

        list.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
         @Override
         public boolean onItemLongClick(AdapterView<?> adapterView, View view, int position, long l) {

                 if (mActionMode != null) {
                     return false;
                 }
                 mActionMode = startSupportActionMode(mActionModeCallback);
                 view.setSelected(true);
                 return true;
         }
     });

    } 

    private ActionMode.Callback mActionModeCallback = new ActionMode.Callback() {

        @Override
        public boolean onCreateActionMode(ActionMode mode, Menu menu) {
            // Inflate a menu resource providing context menu items
            MenuInflater inflater = mode.getMenuInflater();
            inflater.inflate(R.menu.menu, menu);
            return true;
        }

        // Called each time the action mode is shown. Always called after onCreateActionMode, but
        // may be called multiple times if the mode is invalidated.
        @Override
        public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
            return false; // Return false if nothing is done
        }

        // Called when the user selects a contextual menu item
        @Override
        public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
            switch (item.getItemId()) {
                case R.id.action_settings:
                    mode.finish(); // Action picked, so close the CAB
                    return true;
                default:
                    return false;
            }
        }

        // Called when the user exits the action mode
        @Override
        public void onDestroyActionMode(ActionMode mode) {
            mActionMode = null;
        }

    };

}

My contextual_menu.xml :

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

    <item
        android:id="@+id/test"
        android:icon="@android:drawable/ic_menu_delete"
        android:showAsAction="ifRoom|withText"
        android:title="@string/test"
        android:titleCondensed="Delete">
    </item>

</menu>

And when I try to long click on an item I got this stack error :

06-01 18:11:09.888: E/AndroidRuntime(1206): FATAL EXCEPTION: main
    06-01 18:11:09.888: E/AndroidRuntime(1206): android.view.InflateException: Binary XML file line #17: Error inflating class <unknown>
    06-01 18:11:09.888: E/AndroidRuntime(1206):     at android.view.LayoutInflater.createView(LayoutInflater.java:613)
    06-01 18:11:09.888: E/AndroidRuntime(1206):     at com.android.internal.policy.impl.PhoneLayoutInflater.onCreateView(PhoneLayoutInflater.java:56)
    06-01 18:11:09.888: E/AndroidRuntime(1206):     at android.view.LayoutInflater.onCreateView(LayoutInflater.java:660)
    06-01 18:11:09.888: E/AndroidRuntime(1206):     at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:685)
    06-01 18:11:09.888: E/AndroidRuntime(1206):     at android.view.LayoutInflater.inflate(LayoutInflater.java:466)
    06-01 18:11:09.888: E/AndroidRuntime(1206):     at android.view.LayoutInflater.inflate(LayoutInflater.java:396)
    06-01 18:11:09.888: E/AndroidRuntime(1206):     at com.android.internal.widget.ActionBarContextView.initForMode(ActionBarContextView.java:206)
    06-01 18:11:09.888: E/AndroidRuntime(1206):     at com.android.internal.app.ActionBarImpl.startActionMode(ActionBarImpl.java:448)
    06-01 18:11:09.888: E/AndroidRuntime(1206):     at android.app.Activity.onWindowStartingActionMode(Activity.java:4881)
    06-01 18:11:09.888: E/AndroidRuntime(1206):     at android.support.v7.app.ActionBarActivityDelegateICS$WindowCallbackWrapper.onWindowStartingActionMode(ActionBarActivityDelegateICS.java:341)
    06-01 18:11:09.888: E/AndroidRuntime(1206):     at com.android.internal.policy.impl.PhoneWindow$DecorView.startActionMode(PhoneWindow.java:2256)
    06-01 18:11:09.888: E/AndroidRuntime(1206):     at android.app.Activity.startActionMode(Activity.java:4864)
    06-01 18:11:09.888: E/AndroidRuntime(1206):     at android.support.v7.app.ActionBarActivityDelegateICS.startSupportActionMode(ActionBarActivityDelegateICS.java:185)
    06-01 18:11:09.888: E/AndroidRuntime(1206):     at android.support.v7.app.ActionBarActivity.startSupportActionMode(ActionBarActivity.java:194)
    06-01 18:11:09.888: E/AndroidRuntime(1206):     at com.supinfo.cubbyhole.mobileapp.activities.Home$4.onItemLongClick(Home.java:414)
    06-01 18:11:09.888: E/AndroidRuntime(1206):     at android.widget.AbsListView.performLongPress(AbsListView.java:2815)
    06-01 18:11:09.888: E/AndroidRuntime(1206):     at android.widget.AbsListView$CheckForLongPress.run(AbsListView.java:2765)
    06-01 18:11:09.888: E/AndroidRuntime(1206):     at android.os.Handler.handleCallback(Handler.java:725)
    06-01 18:11:09.888: E/AndroidRuntime(1206):     at android.os.Handler.dispatchMessage(Handler.java:92)
    06-01 18:11:09.888: E/AndroidRuntime(1206):     at android.os.Looper.loop(Looper.java:137)
    06-01 18:11:09.888: E/AndroidRuntime(1206):     at android.app.ActivityThread.main(ActivityThread.java:5041)
    06-01 18:11:09.888: E/AndroidRuntime(1206):     at java.lang.reflect.Method.invokeNative(Native Method)
    06-01 18:11:09.888: E/AndroidRuntime(1206):     at java.lang.reflect.Method.invoke(Method.java:511)
    06-01 18:11:09.888: E/AndroidRuntime(1206):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
    06-01 18:11:09.888: E/AndroidRuntime(1206):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
    06-01 18:11:09.888: E/AndroidRuntime(1206):     at dalvik.system.NativeStart.main(Native Method)
    06-01 18:11:09.888: E/AndroidRuntime(1206): Caused by: java.lang.reflect.InvocationTargetException
    06-01 18:11:09.888: E/AndroidRuntime(1206):     at java.lang.reflect.Constructor.constructNative(Native Method)
    06-01 18:11:09.888: E/AndroidRuntime(1206):     at java.lang.reflect.Constructor.newInstance(Constructor.java:417)
    06-01 18:11:09.888: E/AndroidRuntime(1206):     at android.view.LayoutInflater.createView(LayoutInflater.java:587)
    06-01 18:11:09.888: E/AndroidRuntime(1206):     ... 25 more
    06-01 18:11:09.888: E/AndroidRuntime(1206): Caused by: java.lang.StackOverflowError
    06-01 18:11:09.888: E/AndroidRuntime(1206):     at android.graphics.drawable.StateListDrawable$StateListState.indexOfStateSet(StateListDrawable.java:295)
    06-01 18:11:09.888: E/AndroidRuntime(1206):     at android.graphics.drawable.StateListDrawable$StateListState.access$000(StateListDrawable.java:274)
    06-01 18:11:09.888: E/AndroidRuntime(1206):     at android.graphics.drawable.StateListDrawable.onStateChange(StateListDrawable.java:100)
    06-01 18:11:09.888: E/AndroidRuntime(1206):     at android.graphics.drawable.StateListDrawable.<init>(StateListDrawable.java:327)
    06-01 18:11:09.888: E/AndroidRuntime(1206):     at android.graphics.drawable.StateListDrawable.<init>(StateListDrawable.java:75)
    06-01 18:11:09.888: E/AndroidRuntime(1206):     at android.graphics.drawable.Drawable.createFromXmlInner(Drawable.java:843)
    06-01 18:11:09.888: E/AndroidRuntime(1206):     at android.graphics.drawable.Drawable.createFromXml(Drawable.java:822)
    06-01 18:11:09.888: E/AndroidRuntime(1206):     at android.content.res.Resources.loadDrawable(Resources.java:1950)
    06-01 18:11:09.888: E/AndroidRuntime(1206):     at android.content.res.Resources.getDrawable(Resources.java:660)
    06-01 18:11:09.888: E/AndroidRuntime(1206):     at android.graphics.drawable.StateListDrawable.inflate(StateListDrawable.java:173)
    06-01 18:11:09.888: E/AndroidRuntime(1206):     at android.graphics.drawable.Drawable.createFromXmlInner(Drawable.java:885)
    06-01 18:11:09.888: E/AndroidRuntime(1206):     at android.graphics.drawable.Drawable.createFromXml(Drawable.java:822)
    06-01 18:11:09.888: E/AndroidRuntime(1206):     at android.content.res.Resources.loadDrawable(Resources.java:1950)
    06-01 18:11:09.888: E/AndroidRuntime(1206):     at android.content.res.Resources.getDrawable(Resources.java:660)
    06-01 18:11:09.888: E/AndroidRuntime(1206):     at android.graphics.drawable.StateListDrawable.inflate(StateListDrawable.java:173)
    06-01 18:11:09.888: E/AndroidRuntime(1206):     at android.graphics.drawable.Drawable.createFromXmlInner(Drawable.java:885)
    06-01 18:11:09.888: E/AndroidRuntime(1206):     at android.graphics.drawable.Drawable.createFromXml(Drawable.java:822)
    06-01 18:11:09.888: E/AndroidRuntime(1206):     at android.content.res.Resources.loadDrawable(Resources.java:1950)
    06-01 18:11:09.888: E/AndroidRuntime(1206):     at android.content.res.Resources.getDrawable(Resources.java:660)
    06-01 18:11:09.888: E/AndroidRuntime(1206):     at android.graphics.drawable.StateListDrawable.inflate(StateListDrawable.java:173)
    06-01 18:11:09.888: E/AndroidRuntime(1206):     at android.graphics.drawable.Drawable.createFromXmlInner(Drawable.java:885)
    06-01 18:11:09.888: E/AndroidRuntime(1206):     at android.graphics.drawable

I don't understand why the contextual menu doesn't display...

-- EDIT --

Issue was due to the Override of the close icon in my auto generated theme... I just had to comment this line :

<item name="android:actionModeCloseButtonStyle">@style/ActionButton.CloseMode.Cubbyhole</item>

Solution

  • The exception is an stack overflow (how appropriate) while expanding the "close" icon in the CAB. Probably because of a state-list drawable that references itself.

    The relevant code in ActionBarContextView.java is:

    LayoutInflater inflater = LayoutInflater.from(mContext);
    mClose = inflater.inflate(R.layout.action_mode_close_item, this, false);
    

    The problem might be related to an incorrect definition of the actionModeCloseDrawable drawable, or the actionModeCloseButtonStyle style.

    Is either one of them customized in your theme, possibly with an recursive state-list drawable?

    In case everything is correctly defined, I would suggest cleaning and rebuilding the project (the resource ids may be incorrect).