Incoherent DrawerLayout behavior after rotation - android

I have an activity with a DrawerLayout and a ActionBarDrawerToggle to handle a side menu.
Now, I needed this activity to rotate only on tablets but not on phone, so I added android:configChanges="orientation|..." to my manifest for that activity, and reimplemented onConfigurationChanged. On phones, nothing is done and portrait is forced, while on tablets, the new orientation is set to SCREEN_ORIENTATION_SENSOR to let the device decide and I reload the layout with setContentView().
Since I've done that, my side menu won't open past the first rotation. I discovered that onOptionsItemSelected is still called:
public boolean onOptionsItemSelected(MenuItem item)
{
if (item.getItemId() == android.R.id.home) {
if (mDrawerLayout.isDrawerVisible(GravityCompat.START)) {
mDrawerLayout.closeDrawer(GravityCompat.START);
}
else {
mDrawerLayout.openDrawer(GravityCompat.START);
}
}
return true;
}
but the test that check if the drawer is visible always returns true.
Any idea on what could cause that? Did I forget to recreate or update something after the rotation in onConfigurationChanged?
Note: I also found out that if I don't recreate the layout (with setContentView()) the drawer works fine (but then I obviously lose the landscape layout and get the portrait layout somehow scaled)

So, I somehow found a solution to this, by reconnecting the DrawerLayout to the ActionBarDrawerToggle each time the device rotates, after recreating the layout:
setContentView(R.id.my_layout_id);
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
mDrawerLayout.setDrawerListener(mDrawerToggle);
in the onConfigurationChanged method.
The only downside to that is that the drawer won't keep its state between the two orientation (if it was opened, it'll be recreated and thus end up closed in the new orientation).

Related

Material Drawer opens automatically as activity starts

When I use Material Drawer, as soon as a new activity starts, drawer is being displayed automatically, but I want that it starts hidden, so I have to use function drawer.closeDrawer() in the method onResume of activity, as described below:
#Override
protected void onResume() {
super.onResume();
drawer.closeDrawer();
}
Is this the correct way to hidden the drawer when activity starts or restarts, or there is a property to be set for this purpose in the drawer?
Thank you,
Alexandre Bianchi
There are different cases why the drawer may opens after the application starts.
Either you define withShowDrawerOnFirstLaunch, this should be removed or set to false, if you don't want this behavior.
https://github.com/mikepenz/MaterialDrawer/blob/develop/library/src/main/java/com/mikepenz/materialdrawer/DrawerBuilder.java#L1188
It could also be that you open the drawer via the Drawer's API. So make sure you don't call openDrawer programtically
https://github.com/mikepenz/MaterialDrawer/blob/develop/library/src/main/java/com/mikepenz/materialdrawer/Drawer.java#L125
The Drawer comes also with a method to close the drawer. Just call closeDrawer
https://github.com/mikepenz/MaterialDrawer/blob/develop/library/src/main/java/com/mikepenz/materialdrawer/Drawer.java#L134
Put this code in oncreate and it will check the drawer is open or not...if its open it will close the drawer
DrawerLayout layout = (DrawerLayout) findViewById(R.id.drawer_layout);
if (layout.isDrawerOpen(GravityCompat.START)) {
layout.closeDrawer(GravityCompat.START);
}

DrawerLayout.openDrawer sometimes not working

I have a DrawerLayout that usually works perfectly. I am using a button that opens the drawer by calling this method:
mDrawerLayout.openDrawer(mFragmentContainerView);
As I said, everything works fine but sometimes when the activity comes back from background the openDrawer method does nothing.
By using
mDrawerLayout.isDrawerOpen(mFragmentContainerView);
before and after calling the openDrawer method, I can see it is always closed.
I have spent several hours on this. What is going on? Any clue is appreciated!
Open and close the drawer using it's gravity like this
if (mDrawerLayout.isDrawerOpen(Gravity.START)) {
mDrawerLayout.closeDrawers();
} else {
mDrawerLayout.openDrawer(Gravity.START);
}
or use View.VISIBLE and View.GONE in place of Gravity.

Android DrawerLayout.setDrawerLockMode() not working

I have a Navigation Drawer (appcompat v7) in my app which is working perfectly fine.
Now I want to disable it, until the user buys an in-app-purchase to unlock additional functionality. So in my Activity.onCreate(), after initializing the drawer and populating it, I am calling this function:
mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
This function is not doing anything. The drawer continues to open and close as normal after tapping the drawer carat in the actionbar. I tried calling this function in Activity.onResume() without any difference.
What is the correct way to use this function?
(I tried looking online for answers, but couldn't find anything which addresses my issue). Any help is appreciated, as I am stuck on this issue for quite sometime now.
mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
is only disabling the opening drawer layout by swiping till you click navigation drawer icon
keep a boolean variable
write mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED); in onStart() and also write below lines of code
#Override
public boolean onOptionsItemSelected(android.view.MenuItem item) {
if(!disabled)
{
if (item.getItemId() == android.R.id.home) {
if (mDrawerLayout.isDrawerOpen(mDrawerLinearLayout)) {
mDrawerLayout.closeDrawer(mDrawerLinearLayout);
} else {
mDrawerLayout.openDrawer(mDrawerLinearLayout);
}
}
}
return super.onOptionsItemSelected(item);
}
this will work for sure
When you call setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED) it locks opening and closing drawer only by swipes.
The drawer continues to open and close as normal after tapping the drawer carat in the action bar because your drawer will still respond to calls to openDrawer(int), closeDrawer(int) although a drawer is locked.
You need to add some logic in your action bar menu button listener and not to call openDrawer(int) when you don't want it to open.
Btw, it is okay to call setDrawerLockMode(int) in onŠ”reate
There is a bug with DrawerLayout and used gravity. I have reported it here:
https://issuetracker.google.com/issues/136738274

Landscape + navigation drawer animation + new activity = bug?

Here's what's happening.. from my navigation drawer I select an item that then starts up a new activity. Now the thing is I want to close the navigation drawer before opening the new activity, but I don't want the delay to be too long so what I do is start the new activity with a postdelayed handler of about 200ms after a call to closeDrawer(). SO, the drawer is still closing when the new activity gets initialized. The problem kicks in when I go back to the original activity: the layout is shifted about halfway up the screen and tiled in a weird way. Doesn't seem to get fixed until you interact with it (so I'm assuming it gets fixed with the onDraw() call).
Conditions that make this crop up:
Device is in LANDSCAPE mode (doesn't happen on portrait)
The navigation drawer is animating out of view when startActivity() is called
Any insight? Bonus question: is there an easy way of making the navigation drawer close without the animation?
EDIT: Turns out the same thing happens if I'm in landscape and use startActivityForResult(). It's not an issue with only startActivity() though..
In your onAuthenticatedResume() of DrawerActivity, try configuring the DrawerManager & Toggle for drawer properly. The code looks like the snippet below ( I just added some dummy lines like 'YourDrawerManager' means whatever the manager you have )
#Override
protected void onAuthenticatedResume() {
super.onAuthenticatedResume();
//Configure NavigationDrawer
navigationDrawerManager = new YourDrawerManager();
mDrawerLayout = (DrawerLayout)findViewById(R.id.your_layout);
mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout,
R.drawable.logo, "OK",
"Close") {
public void onDrawerClosed(View view) {
getSupportActionBar().setTitle(your_title_string));
supportInvalidateOptionsMenu();
}
public void onDrawerOpened(View drawerView) {
supportInvalidateOptionsMenu();
}
};
mDrawerLayout.setDrawerListener(mDrawerToggle);
mDrawerLayout.post(new Runnable() {
#Override
public void run() {
mDrawerToggle.syncState();
}
});
}
}
I've figured out what the issue was.
The problem was that in my AndroidManifest.xml I declared the new activities as having screenOrientation="portrait" and only enabled orientation changes in the onCreate method for them if certain conditions were met.
I'm still not 100% clear on what was happening but it seems that the device would try to rotate to portrait on activity change, then go back to landscape before drawing the new activity (since it was enabled in onCreate) and then that somehow messed up the previous activity so that when I went back to it, it would get shifted weirdly.
Still an Android bug IMO, but at least I know what it stems from now.
Changed screenOrientation to "landscape" and it works fine now (this problem doesn't arise when the first activity is in portrait and the second is locked to landscape in the manifest... what???)

Show/Hide DrawerLayout depends on current fragment

I have an Activity class that have a DrawerLayout. That layout shows a list in Drawer and let user to switch between fragments. In these Fragments, there are some URLs and when user clicsk on that, a WebviewFragment would be shown. However, I don't want to show the DrawerLayout in the WebViewFragment. Instead, I would prefer user would being redirected to previous Fragment.
Is there any way for me to show/hide the DrawerLayout depends on what the current Fragment is?
I try to call mDrawerLayout.setVisibility(View.GONE), but it seems that it is not complete. At least the ActionBar icon is still the drawer icon.
You can use this method to lock or unlock the drawer: DrawerLayout.setDrawerLockMode(...). (There are also two other versions of this method to specify a lock mode for specific drawers.) To lock, use DrawerLayout.LOCK_MODE_LOCKED_CLOSED; to unlock, use DrawerLayout.LOCK_MODE_UNLOCKED.
If you are using the ActionBarDrawerToggle, you need to add some extra code to prevent the drawer from opening when they click the ActionBarDrawerToggle if you've locked the drawer.
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// check lock mode before passing to ActionBarDrawerToggle
// I assume your drawer is on the left; if not, use Gravity.RIGHT
int lockMode = mDrawer.getDrawerLockMode(Gravity.LEFT);
if (lockMode == DrawerLayout.LOCK_MODE_UNLOCKED &&
mDrawerToggle.onOptionsItemSelected(item)) {
return true;
}
// Handle your other action bar items...
return super.onOptionsItemSelected(item);
}
Why not open a new Activity that has only a WebView as its content instead? Then the user will have to press the back button to go back to the Activity with the DrawerLayout, and then there will be no problems.
Alternatively, you don't have to have such an activity yourself, you can let Android find a browser for them to open instead using this code:
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("HTTP_URL_GOES_HERE"));
startActivity(intent);

Categories

Resources