Why is my DrawerLayout still open on activity resume, in spite of closing it?

984 views Asked by At

I have a DrawerLayout which contains a ListView of items that link to other Activities. The OnItemClick event of the ListView is a switch-case for each menu element, which runs the code

...
case targetActivity:
    listViewInstance.ClearChoices();
    drawerInstance.CloseDrawer(MainMenuLayout);
    drawerInstance.RequestLayout();

    StartActivity(targetIntent);
    break;
...

This works mostly as expected, but if I change device orientation and targetIntent returns to the base activity with the ClearTop flag, the DrawerLayout is still open! In spite of the very explicit call to CloseDrawer, and despite the fact that I can see it closing as the new activity is starting. What am I doing wrong? (I am using Xamarin.Android, if this is relevant).

[Edit 1: I suspect that CloseDrawer only registers the drawer as closed when the closing animation is completed, and that the base activity is paused before this occurs. If I call CloseDrawer in a different thread and pause the current thread for a moment before the call to StartActivity, the drawer works as expected, although of course this is not a suitable solution. Does anyone have a better idea how to solve this in a clean fashion?].

[Edit 2: One possible solution, linked here, is to create an event listener for the drawer's OnDrawerClosed event:

public class DrawerListener2 : DrawerLayout.SimpleDrawerListener
    {
        public override void OnDrawerClosed(View view)
        {
            base.OnDrawerClosed(view);

            var listParent = (RelativeLayout)view;
            var listViewInstance = listParent.FindViewById<ListView>(Resource.Id.mainmenu);

            int selectedIndex = menuListView.CheckedItemPosition;

            switch (selectedIndex)
            {
                case 0:
                    // Start activity A
                    break;
                case 2: // Element 1 is a menu spacer
                    // Start activity B
                    break;
                case 3:
                    // Start activity C
                    break;
            }
        }
    }

...
// In base activity's OnResume:
drawerInstance.SetDrawerListener(new DrawerListener2());
...

This has two problems that make it a no-go: I have to recreate my menu item order in the switch-case since I can't reach the object that contains this information in the OnDrawerClosed handler, and I also can't start the required activities from the event handler since these require intent information from the base activity].

1

There are 1 answers

0
Geir Smestad On BEST ANSWER

Solved by semi-ugly hack:

In base activity, create property that stores its value as an Extra:

private bool ForceDrawerMenuCloseOnActivityResume
    {
        get { return Intent.GetBooleanExtra("ForceDrawerMenuCloseOnActivityResumeKey", false); }
        set { Intent.PutExtra("ForceDrawerMenuCloseOnActivityResumeKey", value); } 
    }

In the base activity's OnResume(), re-close the drawer if this property is set:

if (ForceDrawerMenuCloseOnActivityResume) { 
            drawerInstance.CloseDrawer(MainMenuLayout);
            ForceDrawerMenuCloseOnActivityResume = false;
        }

When closing drawer, immediately before starting the activity that causes the drawer to remain open on activity resume:

case targetActivity:
    drawerInstance.CloseDrawer(MainMenuLayout);
    listViewInstance.ClearChoices();
    ForceDrawerMenuCloseOnActivityResume = true;

    StartActivity(targetIntent);