1

I created a NavigationDrawerFragment, which is actually just a slightly modified version of the code Android Studio generates.

I have a Dashboard activity that contains NavigationDrawerFragment and that can launch several other activities, each of which also contain the NavigationDrawerFragment. Let's call one of these activities Foo.

If I enter Foo from the Dashboard using the Dashboard's nav drawer, then open Foo's nav drawer, the back button will correctly close the nav drawer. HOWEVER, if I entered Foo using a UI element (that was in place before I implemented a nav drawer), then open Foo's nav drawer, the back button returns to the Dashboard activity rather than closing the nav drawer.

I can't figure out why this is occuring. For the NavigationDrawerFragment I have an ItemClickListener and for the UI element I have a ClickListener, but in both situations I am launching a new Foo activity using an intent.

I am wondering if there is something being set that I just don't realize, and if I have control over that something.

I know that I could override onBackPressed to check for the drawer being open (as shown here), but that feels hacky as there is obviously some behavior happening here that I am not aware of.

Edit: This has something to do with ActionBar-PullToRefresh. I removed it from Foo and the nav drawer works correctly.

Edit 2: I was wrong about pull-to-refresh, as @adneal pointed out. There must have been a coincidence that made me think that. I ended up overriding onBackPressed and conditionally checking if the drawer is open or not. Also as @adneal pointed out, the problem has to do with focus. I am still so very curious as to how the focus could be different when launching the activities the same way, but from different places.

Community
  • 1
  • 1
theblang
  • 10,215
  • 9
  • 69
  • 120
  • So, when you press the "back" button after starting `Foo` from a `View.OnClickListener`, the `DrawerLayout` in `Foo` doesn't close and instead you go back to your previous `Activity`. Is that right? – adneal Mar 27 '14 at 08:06
  • @adneal That is exactly right. – theblang Mar 27 '14 at 13:16
  • Sorry, but I want to be even more clear. Your `DrawerLayout` in `Foo`, being fully visible after you drag it out, does not respond to the "back" button being pressed when you launch `Foo` from a `View.OnClickListener`, but does respond when you launch it in the same manner from an `AdapterView.OnItemClickListener`? Also, how are you implementing your `NavigationDrawerFragment`? Is it embedded the in layout of your `Activity` or do your use a `FragmentTransaction`? – adneal Mar 27 '14 at 14:12
  • @adneal What you described is exactly right, and it is embedded in the Activity's `layout`. I just discovered an important clue, the error doesn't occur if I remove Chris Bane's `PullToRefresh`. – theblang Mar 27 '14 at 14:19

1 Answers1

1

So, I'm fairly certain I understand what's going on, but I'm still unsure about why it only seem to happen when you use a View.OnClicklistener. Maybe there's a little more to your code that I don't know about or maybe I overlooked something in those regards.

But the reason you're having this problem is due to how Android handles the View.onKey... event. DrawerLayout overrides View.onKeyDown and View.onKeyUp, checking each time if you're pressing the "back" button so it can determine whether or not to close the drawer. But this event isn't taking place, in your case, because the AdapterView you have set will take the focus away from the DrawerLayout after you call AdapterView.setAdpater.

How to fix it

Short of copying over the DrawerLayout source and modifying it, which you could definitely do; it's only one class, I would recommend converting each Foo Activity into a Fragment, then use the FrameLayout you typically place when creating a DrawerLayout to display them. You should create a NavigationDrawerActivity instead of a Fragment to host everything.

This has to do with the way DrawerLayout is laid out, in that it has to use MeasureSpec.EXACTLY. In other words, when you place your NavigationDrawerFragment ontop of your Foo layout, it takes up the entire space. If you called View.setFocusableInTouchMode after you set your ListAdapter in Foo, the DrawerLayout would work like it should, but the AdapterView wouldn't scroll anymore. And you can't toggle that focus based on the open or closed position of the DrawerLayout, because either way it takes up the entire space and always return true in View.onTouchEvent.

Or just override Activity.onBackPressed, which really isn't as "hacky" as you may think, but I understand what you mean.

At any rate, I hope this is clear and/or helpful at the very least. Took me a little bit to reproduce your problem, but after I did it didn't take long to rule out the pull-to-refresh library. In short, I think it's a focus issue. Prove me wrong.

Source

You can view the source for the DrawerLayout here to look over how it handles the "back" event

You can see here how AdapterView.checkFocus works

You can see here in ListView (GridView is the same), when AdapterView.checkFocus is called

adneal
  • 30,484
  • 10
  • 122
  • 151
  • You are absolutely correct about `pull-to-refresh` not being involved. Some coincidence must have made me think that. You are also correct that it is a focus issue. I have an `EditText` above the `ListView` in `Foo`, and if I put focus on it, then close the keyboard, the `back button` will always go back an `activity` instead of closing the drawer. Maybe overriding `onBackPressed` is the proper way to do this? – theblang Mar 27 '14 at 18:36
  • I am still so very curious what is causing the difference when I launch `Foo` from Dashboard's nav drawer, or launch `Foo` using the UI element. Is Android doing something under the hood to make the `Drawer` have focus when I go to `Foo` from a Drawer? – theblang Mar 27 '14 at 18:40
  • Regarding your recommendation to move to a one activity approach, I want to do that but I didn't have time to engage in that large of a refactor (this is a project I am on at work). Instead I decided to at least put all of my old activities into fragments for now, and maybe go with a one activity approach in the future. So essentially, every activity has one main fragment at the moment. – theblang Mar 27 '14 at 18:44
  • No, it is not. I'll probably dig into this some more later, I'm curious too. But that would certainly be the simplest solution. On a completely unrelated note, I grew up in Clinton about two hours from Starkville. Eh, thought it was kinda interesting. – adneal Mar 27 '14 at 18:47