Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

startActionMode returning null

Tags:

java

android

It is really weird. The first time I start the application in eclipse and i call startActionMode, everything works fine. If i close the app and open it again, the startActionMode returns null. It will always return null until I change something in the app and run it again from eclipse. In the documentation, it says that the startActionMode returns null if it was canceled, but it doesn't explain why it is canceled.

Any ideas? btw, i`m using actionbarsherlock

UPDATE: if I shutdown my phone or kill the app and start the app again, it works... but then does the same thing when i close it and open it again.

here's my code: the ActionModeCallback class:

   class ActionModeCallback implements ActionMode.Callback{

    @Override 
    public boolean onCreateActionMode(ActionMode mode, Menu menu) {
          MenuInflater inflater = mode.getMenuInflater();
          inflater.inflate(R.menu.contextactiondownloads, menu);
          return true;
        }

    @Override
    public void onDestroyActionMode(ActionMode mode) {

    }

    @Override
    public boolean onActionItemClicked(ActionMode mode, MenuItem item) {

    }

    @Override
    public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
        // TODO Auto-generated method stub

        return false;
    }
};

In my mainactivity:

public ActionMode startActionMode()
{
    mActionMode = startActionMode(new ActionModeCallback());
    return mActionMode;
}

In my listview adapter:

 public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {

                MainActivity activity = (MainActivity)rowView.getContext();
                if (isChecked) {

                    if(actionmode == null){
                        actionmode = activity.startActionMode();
                    }else
                    {
                        actionmode.invalidate();
                    }
                }
                else {
                        activity.finishActionMode();
                        actionmode=null;
                }
            }
        });
like image 965
Marc-André Therrien Avatar asked Jul 12 '13 22:07

Marc-André Therrien


2 Answers

Well, I don't really understood why it's happening with you. But I've created a ListView that have the same behavior the old Gmail's ListView used to have.

Basically, the user can start the "Selection Mode" by long pressing one of the items and then, the user can select other items either by long clicking or clicking at the left part of the item. The checkbox is managed by your adapter by making it visible in "Selection Mode" and invisible when it's not in "Selection Mode". You also make it checked by checking if the current item is selected. Then, you make it non clickable, so that the ListView can get the touch events.

If you want the ListView to start in the "Selection Mode", you can set the selectableFromTheBeginning to true. And then, you make the CheckBox visible from the beginning. I'll make it easier to use and document it later, but I think it's usable now.

Here is the link for the SelectionListView:

https://github.com/CyberEagle/OpenProjects/blob/master/android-projects/widgets/src/main/java/br/com/cybereagle/androidwidgets/view/SelectionListView.java

You'll also need to copy the part of my attrs.xml that specifies the SelectionListView attributes to be set via XML.

https://github.com/CyberEagle/OpenProjects/blob/master/android-projects/widgets/res/values/attrs.xml

To use it, you implement SelectionListView.SelecionActionModeCallback instead of ActionMode.ActionModeCallback. Remember to call the parent's methods.

You can use it in the XML and find it by ID. So you can change the message that appears when the user select the items using:

listView.setSelectedStringFormat("%d selected items");

You set your implementation of SelectionListView.SelecionActionModeCallback using the method setActionModeCallback.

In your Adapter, you can do something like this:

checkBox.setChecked(listView.isItemChecked(position));

In your ActionModeCallback, you can implement something like this:

public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
    SparseBooleanArray checkedItems = listView.getCheckedItemPositions();

    List<Item> selectedItems = new ArrayList<Item>();

    for (int i = 0; i < checkedItems.size(); i++) {
        if (checkedItems.valueAt(i)) {
            selectedItems.add(yourListOfItems.get(checkedItems.keyAt(i)));
        }
    }

    switch(item.getId()){
        case R.id.do_something:
            doSomething(selectedItems);
            mode.finish();
            break;
    }
}

Your checkbox would look like this:

<CheckBox
    android:id="@+id/select"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:clickable="false"
    android:focusable="false"
    android:focusableInTouchMode="false" />

With this widget, you don't need to worry too much with the ActionMode or with the way you will select the items. I'm sorry about the lack of documentation. This is repository I put some code to use in other projects. I'm planning to document it. There're other widgets there you can look.

If you use this, please, just respect the Apache License.

like image 180
Fernando Camargo Avatar answered Oct 02 '22 18:10

Fernando Camargo


So I finally found a workaround which is probably NOT the best solution, but i didn't find any other solutions. I did a kill process in the onDestroy on my activity.

like this :

android.os.Process.killProcess(android.os.Process.myPid());

It is working now. It seems that my phone wasn`t clearing the memory of something.

EDIT: I can't use this solution because I have a service which need to be open even if the app is closed. The killProcess kill the service too.

EDIT 2 I finally found the source of my problem. I was keeping a static variable of one of my fragment. For some reason, that variable was kept in memory even when restarting the app. I still don`t know exactly why startActionMode is returning null. To fix it, i've instantiate my variable in the onCreate of my activity.

like image 38
Marc-André Therrien Avatar answered Oct 02 '22 18:10

Marc-André Therrien