Toolbar won't disappear in action mode
Asked Answered
S

6

8

I am trying to implement the feature that, when I am long clicking a list item, the action mode shall start and it shall be possible to delete one or more items.
I am starting in DocumentsActivity a search, which starts a Fragment DocumentsFragment with a ListView and their items. The ListAdapter is initialized and set via method call setListAdapter(this.documentsAdapter) in onCreate of Fragment. I set various listeners on the listview in the onActivityCreated in the Fragment:

public void onActivityCreated(Bundle savedInstanceState) {

    getListView().setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
    getListView().setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
        @Override
        public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
            getListView().setItemChecked(position, true);
            return true; 
    }});
    getListView().setMultiChoiceModeListener(new AbsListView.MultiChoiceModeListener() {
        @Override
        public boolean onCreateActionMode(ActionMode mode, Menu menu) {
            menu.clear();
            ((DocumentsActivity)getActivity()).getMenuInflater().inflate(R.menu.documents_context_menu, menu);
            return true;
        }
    });
    super.onActivityCreated(savedInstanceState);
}

When long clicking on a listitem the action mode gets started and the menu documents_context_menu appears to be the action bar. But the problem is, the action bar appears above the toolbar and the toolbar won't disappear (see the picture).

I've tried to call getSupportActionBar().hide() or set it to null or even use another style/theme. It all didn't work. Sometimes the blue toolbar was completely white, but that is all.

I have absolutely no idea why the toolbar won't disappear. May you give some advice?

Thanks in advance!

_____ Update 1 _____

This is the styles.xml

<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <item name="android:fitsSystemWindows">true</item>
    <item name="colorAccent">@color/darkblue100</item>
    <item name="android:actionOverflowButtonStyle">@style/ActionButtonOverflow</item>
    <item name="actionOverflowButtonStyle">@style/ActionButtonOverflow</item>
    <item name="android:actionMenuTextColor">@color/black</item>
</style>

And this is how the action bar is set in the Activity:

protected void onCreate(Bundle savedInstanceState) {
    handleIntent(getIntent());
    requestWindowFeature(5);
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_documents);
    Toolbar mToolbar = (Toolbar) findViewById(R.id.tool_bar);
    setSupportActionBar(mToolbar);
    args = getIntent().getExtras();
    if (findViewById(R.id.container_documents) != null && savedInstanceState == null) {
        showDocumentsFragment();
    }
}
Songsongbird answered 14/1, 2019 at 14:43 Comment(5)
Can you please post your Apptheme code from styles.xml and onCreate where you setSupportActionBar ?Trichomoniasis
Possible duplicate of Toolbar and Contextual ActionBar with AppCompat-v7Shemikashemite
@MayurGajra I added the sourcesSongsongbird
can you share your Manifest file?Toein
@AbhinavGupta there it isSongsongbird
S
1

Actually the issue were caused by different things. First, the windowActionBar was set true, also was the attribute fitsSystemWindows.I deleted both lines in styles.xml.

Then there was in the activity layout the attribute layout_marginTop="?actionBarSize" I did not see, following in complete confusion. But this attribute needs to be there so I am handling it in the method onActivityCreated when onCreateActionMode and onDestroyActionMode are called.

After that all I had the automagically problem that the listview items disappeared. I fixed it by commiting my fragment again in onDestroyActionMode.

public void onActivityCreated(Bundle savedInstanceState) {

    getListView().setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
    getListView().setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {

        @Override
        public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {...}
    });
    getListView().setMultiChoiceModeListener(new AbsListView.MultiChoiceModeListener() {
        LinearLayout ll = ((DocumentsActivity)getActivity()).findViewById(R.id.container_documents);

        @Override
        public boolean onCreateActionMode(ActionMode mode, Menu menu) {
            DrawerLayout.LayoutParams params = (DrawerLayout.LayoutParams) ll.getLayoutParams();
            params.setMargins(0, 0, 0, 0);
            ll.setLayoutParams(params);

            ((DocumentsActivity)getActivity()).getSupportActionBar().hide();
            MenuInflater inflater = mode.getMenuInflater();
            inflater.inflate(R.menu.documents_context_menu, menu);
            return true;
        }

        @Override
        public void onDestroyActionMode(ActionMode mode) {
            DrawerLayout.LayoutParams params = (DrawerLayout.LayoutParams) ll.getLayoutParams();
            params.setMargins(0, R.attr.actionBarSize, 0, 0);
            ll.setLayoutParams(params);
            ((DocumentsActivity)getActivity()).getSupportActionBar().show();

            if (getFragmentManager() != null)
                getFragmentManager()
                .beginTransaction()
                .detach(this)
                .attach(this)
                .commit();
        }
    });

    super.onActivityCreated(savedInstanceState);
}
Songsongbird answered 25/1, 2019 at 8:37 Comment(0)
T
10

As pointed out in the link provided in comments you just need to add following line to your AppTheme style:

<item name="windowActionModeOverlay">true</item>

It just indicates that action mode should overlay window content instead of pushing it down,it tells that you don't need any reserved space for action mode.

Trichomoniasis answered 14/1, 2019 at 15:19 Comment(2)
@MarcelHofgesang How are you setting action mode then? Have tried setting acion mode on toolbar instead of activity like this : toolbar.startActionMode(callback); ?Trichomoniasis
yes I've tried that way too but it had some more bugs... Actually the action mode gets activated when the MultiChoiceModeListener gets called. See the description on android developers site developer.android.com/reference/android/widget/…Songsongbird
B
2

Well as far as i go through your code and understand it, you have done everything that you provided your Toolbar to act as ActionBar and used .NoActionBar theme except according to Android Developer you should also set the windowActionBar attribute to false in your style. enter link description here Second para clears it out.

I hope it helps!

Billhead answered 21/1, 2019 at 22:1 Comment(0)
S
2

all of this answers are fine you should try them but what you need is a ContextualMenu so you should first add views to a registerForContextMenu() so menu knows which menus are contextual then implement the onCreateContextMenu of your Activity

@Override
public void onCreateContextMenu(ContextMenu menu, View v,
                            ContextMenuInfo menuInfo) {
   super.onCreateContextMenu(menu, v, menuInfo);
   MenuInflater inflater = getMenuInflater();
   inflater.inflate(R.menu.context_menu, menu);
}

then implement onContextItemSelected() like this :

@Override
public boolean onContextItemSelected(MenuItem item) {
AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
switch (item.getItemId()) {
    case R.id.edit:
        editNote(info.id);
        return true;
    case R.id.delete:
        deleteNote(info.id);
        return true;
    default:
        return super.onContextItemSelected(item);
}
}

then you have to perform an action on views and implement AbsListView.MultiChoiceModeListener then call setChoiceMode() with the CHOICE_MODE_MULTIPLE_MODAL argument. like this :

ListView listView = getListView();
listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
listView.setMultiChoiceModeListener(new MultiChoiceModeListener() {

@Override
public void onItemCheckedStateChanged(ActionMode mode, int position,
                                      long id, boolean checked) {
    // Here you can do something when items are selected/de-selected,
    // such as update the title in the CAB
}

@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
    // Respond to clicks on the actions in the CAB
    switch (item.getItemId()) {
        case R.id.menu_delete:
            deleteSelectedItems();
            mode.finish(); // Action picked, so close the CAB
            return true;
        default:
            return false;
    }
}

@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
    // Inflate the menu for the CAB
    MenuInflater inflater = mode.getMenuInflater();
    inflater.inflate(R.menu.context, menu);
    return true;
}

@Override
public void onDestroyActionMode(ActionMode mode) {
    // Here you can make any necessary updates to the activity when
    // the CAB is removed. By default, selected items are deselected/unchecked.
}

@Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
    // Here you can perform updates to the CAB due to
    // an <code><a href="/reference/android   /view/ActionMode.html#invalidate()">invalidate()</a></code> request
    return false;
}
});

all of what i said and ultimately more, you can find in this android developer documentation

Stipulation answered 22/1, 2019 at 12:40 Comment(0)
M
1

Add:

 //Set action mode null after use
    public void setNullToActionMode() {
        if (mActionMode != null)
            mActionMode = null;
    }

Or:

//Remove selected selections
public void removeSelection() {

    mSelectedItemsIds = new SparseBooleanArray();
}
Marisolmarissa answered 17/1, 2019 at 14:23 Comment(1)
This doesn't refer on the problem that I state. The removing of an list item is not the problem, just the 2nd toolbar. Also I those methods aren't applicable in my scenario.Songsongbird
S
1

Actually the issue were caused by different things. First, the windowActionBar was set true, also was the attribute fitsSystemWindows.I deleted both lines in styles.xml.

Then there was in the activity layout the attribute layout_marginTop="?actionBarSize" I did not see, following in complete confusion. But this attribute needs to be there so I am handling it in the method onActivityCreated when onCreateActionMode and onDestroyActionMode are called.

After that all I had the automagically problem that the listview items disappeared. I fixed it by commiting my fragment again in onDestroyActionMode.

public void onActivityCreated(Bundle savedInstanceState) {

    getListView().setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
    getListView().setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {

        @Override
        public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {...}
    });
    getListView().setMultiChoiceModeListener(new AbsListView.MultiChoiceModeListener() {
        LinearLayout ll = ((DocumentsActivity)getActivity()).findViewById(R.id.container_documents);

        @Override
        public boolean onCreateActionMode(ActionMode mode, Menu menu) {
            DrawerLayout.LayoutParams params = (DrawerLayout.LayoutParams) ll.getLayoutParams();
            params.setMargins(0, 0, 0, 0);
            ll.setLayoutParams(params);

            ((DocumentsActivity)getActivity()).getSupportActionBar().hide();
            MenuInflater inflater = mode.getMenuInflater();
            inflater.inflate(R.menu.documents_context_menu, menu);
            return true;
        }

        @Override
        public void onDestroyActionMode(ActionMode mode) {
            DrawerLayout.LayoutParams params = (DrawerLayout.LayoutParams) ll.getLayoutParams();
            params.setMargins(0, R.attr.actionBarSize, 0, 0);
            ll.setLayoutParams(params);
            ((DocumentsActivity)getActivity()).getSupportActionBar().show();

            if (getFragmentManager() != null)
                getFragmentManager()
                .beginTransaction()
                .detach(this)
                .attach(this)
                .commit();
        }
    });

    super.onActivityCreated(savedInstanceState);
}
Songsongbird answered 25/1, 2019 at 8:37 Comment(0)
F
1

In Kotlin, assuming that your Activity extends from AppCompatActivity

  • You should get the instance of the support action bar and call the methods

    supportActionBar?.show() or supportActionBar?.hide()

  • If you're using a fragment, you can access the action bar from the Fragment's activity instance

    (activity as AppCompatActivity).supportActionBar?.show()

Fathomless answered 27/5, 2020 at 5:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.