I'm currently trying to modify the UI of an existing Android application by making some slight changes. One change I need to implement is to modify the navigation drawer / slider toggle icon between one of 3 icons (on, off, 'special'). You supply the icon on creation of the ActionBarDrawerToggle on instantiation and there doesn't seem to be a method to modify the value after the object is created. Does anyone know if it's possible to achieve this (hack or no hack) ?
Thanks in advance,
thisguy
Check out this guide here: http://www.androidhive.info/2013/11/android-sliding-menu-using-navigation-drawer/
and here: http://developer.android.com/training/implementing-navigation/nav-drawer.html
I think you may change icon on ActionBarDrawerToggle's methods:
/** Called when a drawer has settled in a completely closed state. */
public void onDrawerClosed(View view) {
super.onDrawerClosed(view);
getActionBar().setTitle(mTitle);
invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()
}
/** Called when a drawer has settled in a completely open state. */
public void onDrawerOpened(View drawerView) {
super.onDrawerOpened(drawerView);
getActionBar().setTitle(mDrawerTitle);
invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()
}
};
Related
I'm implementing an activity with two action bar drawers.
Right now I have two buttons in the action bar which show these drawers and they are working fine. Even they close the other if already opened.
These drawers are intended to be used as filters (cities and categories) for a listview, and my idea is to listen for the OnClose event, so I can get the checked items and filter the list.
With "onDrawerClosed" I can do it very easy, but the problem is when drawers are shown via sliding, as the event is not fired.
I have been dealing then with "onDrawerSlide" and finally got this code:
void initDrawer() {
drawerToggle = new ActionBarDrawerToggle(this, drawerLayout, R.drawable.ic_home_up, R.string.app_name,
R.string.app_name) {
#Override
public void onDrawerSlide(View drawerView, float slideOffset) {
if (slideOffset == 0) {
//if (!drawerLayout.isDrawerOpen(drawerView)) {
outputManager.showToast("Closed ");
//drawerClosed(drawerView);
//}
invalidateOptionsMenu(); // calls onPrepareOptionsMenu()
}
super.onDrawerSlide(drawerView, slideOffset);
}
public void onDrawerClosed(View drawerView) {
// getActionBar().setTitle(mTitle);
// calling onPrepareOptionsMenu() to show action bar icons
invalidateOptionsMenu();
drawerClosed(drawerView);
}
public void onDrawerOpened(View drawerView) {
// getActionBar().setTitle(mDrawerTitle);
// calling onPrepareOptionsMenu() to hide action bar icons
invalidateOptionsMenu();
}
};
drawerLayout.setDrawerListener(drawerToggle);
}
It kept firing the event a lot (I think it's fired several times until sliding is completed), so I checked if slideOffset is 0. It neither works, one of the sliders works, but the other doesn't fire any event.
Any idea? Maybe I could block sliding and allow to display drawers only via buttons, but how?
Finally I removed the second drawer and came up with a different approach. I think I tried to use it in a way is not intended for.
I have created navigation drawer using sherelockActionbar libs. It is working fine and loading all fregments on available list of menus. but issue is it stops in middel when menu fragments load for few milliseconds in a perticuler one menu for other it moves smoothly . how to make it smooth for all menu.
I would suggest you try doing these fragment transactions after the navigation drawer closes completely. There is a method onDrawerClosed, where you could try to implement fragment swapping if a flag is set.
navDrawerToggle = new ActionBarDrawerToggle(this, navDrawerLayout,
R.drawable.ic_drawer, R.string.drawer_open, R.string.drawer_close) {
/** Called when a drawer has settled in a completely closed state. */
public void onDrawerClosed(View view) {
super.onDrawerClosed(view);
supportInvalidateOptionsMenu();
if(makeFragmentTransaction){
// make transaction; swap fragment
}
}
/** Called when a drawer has settled in a completely open state. */
public void onDrawerOpened(View drawerView) {
super.onDrawerOpened(drawerView);
supportInvalidateOptionsMenu();
}
};
Just set the flag on drawer item click and after the drawer closes, it will check whether a transaction is to be made. If you decide to give it a shot, let me know how it works out for you.
Edit: updated the code.
/** Called when drawer is closed */
public void onDrawerClosed(View view)
{
getActionBar().setTitle(mTitle);
invalidateOptionsMenu();
}
/** Called when a drawer is opened */
public void onDrawerOpened(View drawerView)
{
getActionBar().setTitle("Select a river");
invalidateOptionsMenu();
}
};
// Setting DrawerToggle on DrawerLayout
mDrawerLayout.setDrawerListener(mDrawerToggle);
// Creating an ArrayAdapter to add items to the listview mDrawerList
ArrayAdapter<String> adapter = new ArrayAdapter<String>(
getBaseContext(),
R.layout.drawer_list_item ,
getResources().getStringArray(R.array.rivers)
);
// Setting the adapter on mDrawerList
mDrawerList.setAdapter(adapter);
// Enabling Home button
getActionBar().setHomeButtonEnabled(true);
// Enabling Up navigation
getActionBar().setDisplayHomeAsUpEnabled(true);
Try to use getSupportActionBar() instead of getActionBar().
Fragment does not have method getActionBar().
A fragment is usually used as part of an activity's user interface and contributes its own layout to the activity. To provide a layout for a fragment, you must implement the onCreateView() callback method, which the Android system calls when it's time for the fragment to draw its layout.
So, fragment requires its activity in which it is present.
So, try getActivity().getActionBar();
I use a navigation drawer in my app (the type of navigation that you open by sliding from the left side of the screen). Now, usually you can also open it by tapping the app icon, and when I looked it up, I found a whole bunch of code to add to your activity. And just for a simple button. I suppose thats not exactly what I am looking for? And if it really needs to be so much code for a single button, what is the best way to make the code more clear? Thank you, and sorry for being such an android newb.
I ran into this issue also, assuming you already have an ActionBarDrawerToggle as #Kernald suggested, you need to add the following also to your Activity:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Pass the event to ActionBarDrawerToggle, if it returns
// true, then it has handled the app icon touch event
if (mDrawerToggle.onOptionsItemSelected(item)) {
return true;
}
// Handle your other action bar items...
return super.onOptionsItemSelected(item);
}
This let's the toggle handle the icon button press on the ActionBar, causing the Drawer to slide out.
Everything you need is described in the Navigation Drawer Guide from Google. Basically, you need to enable the "up" action on the ActionBar:
getActionBar().setDisplayHomeAsUpEnabled(true);
getActionBar().setHomeButtonEnabled(true);
Then you need to bind it to a Toggle:
mDrawerToggle = new ActionBarDrawerToggle(
this, /* host Activity */
mDrawerLayout, /* DrawerLayout object */
R.drawable.ic_drawer, /* nav drawer icon to replace 'Up' caret */
R.string.drawer_open, /* "open drawer" description */
R.string.drawer_close /* "close drawer" description */
) {
/** Called when a drawer has settled in a completely closed state. */
public void onDrawerClosed(View view) {
getActionBar().setTitle(mTitle);
}
/** Called when a drawer has settled in a completely open state. */
public void onDrawerOpened(View drawerView) {
getActionBar().setTitle(mDrawerTitle);
}
};
// Set the drawer toggle as the DrawerListener
mDrawerLayout.setDrawerListener(mDrawerToggle);
At least Gmail and Youtube Android apps use a side menu (navigation drawer?) that opens by swiping, or by clicking the app icon (home button):
Is the menu indicator / icon in the screenshot above a ready-made part of Android SDK? (Or a custom icon Google uses in their apps?) In any case, what's the easiest way to get your home button to look like that, i.e., like it opens a menu?
(targetSdkVersion 18; minSdkVersion 14)
Resolution
Finally got it working. What was missing for me was 1) the actual icon and 2) deferred call to syncState() on the ActionBarDrawerToggle.
To create similar implementation / look in your application you should use ActionBarDrawerToggle and set your custom icon as indicator next to ActionBar home button. For example :
import android.app.ActionBar;
import android.support.v4.app.ActionBarDrawerToggle;
import android.support.v4.widget.DrawerLayout;
private void setUpDrawerToggle(){
ActionBar actionBar = getActionBar();
actionBar.setDisplayHomeAsUpEnabled(true);
actionBar.setHomeButtonEnabled(true);
// ActionBarDrawerToggle ties together the the proper interactions
// between the navigation drawer and the action bar app icon.
mDrawerToggle = new ActionBarDrawerToggle(
this, /* host Activity */
mDrawerLayout, /* DrawerLayout object */
R.drawable.ic_drawer, /* nav drawer image to replace 'Up' caret */
R.string.navigation_drawer_open, /* "open drawer" description for accessibility */
R.string.navigation_drawer_close /* "close drawer" description for accessibility */
) {
#Override
public void onDrawerClosed(View drawerView) {
invalidateOptionsMenu(); // calls onPrepareOptionsMenu()
}
#Override
public void onDrawerOpened(View drawerView) {
invalidateOptionsMenu(); // calls onPrepareOptionsMenu()
}
};
// Defer code dependent on restoration of previous instance state.
// NB: required for the drawer indicator to show up!
mDrawerLayout.post(new Runnable() {
#Override
public void run() {
mDrawerToggle.syncState();
}
});
mDrawerLayout.setDrawerListener(mDrawerToggle);
}
Where R.drawable.ic_drawer is actually the icon to use as indicator. You can find it in Android Asset Studio; see Navigation Drawer Indicator.
References
ActionBarDrawerToggle
Creating a Navigation Drawer
Android-Developer and HpTerm helped me in the right rirection, by
Pointing out this is indeed NavigationDrawer specific (which I was already using as in Google's example)
Telling where to find the ic_drawer.png icon (→ Android Asset Studio)
Now, unfortunately, creating ActionBarDrawerToggle like below seems not to be enough.
At least on my Nexus 7 (API 18) test device.
drawerToggle = new ActionBarDrawerToggle(this,
drawerLayout,
R.drawable.ic_navigation_drawer,
R.string.side_menu_open,
R.string.side_menu_closed) {
// ...
};
Partial solution (API level 18+)
I found one way to make the indicator show up though: setHomeAsUpIndicator(). The downside: that method was added in API level 18.
#Override
protected void onCreate(Bundle savedInstanceState) {
// ...
getActionBar().setDisplayHomeAsUpEnabled(true); // also required
if (Build.VERSION.SDK_INT >= 18) {
getActionBar().setHomeAsUpIndicator(
getResources().getDrawable(R.drawable.ic_navigation_drawer));
}
}
So now the question remains: how to make this work (in my case) for API levels 14 through 17?
I verified on a 4.1.2 (API 16) device that the ic_drawer icon does not show up. With setDisplayHomeAsUpEnabled(true) I get the normal "home" icon (small arrow pointing left) and without it, the space left to my app icon remains blank.
Final solution
Got it working using the edited version of Android-Developer's answer.
Quite curiously, what was missing from my ActionBarDrawerToggle initialisation code was this:
// Defer code dependent on restoration of previous instance state.
drawerLayout.post(new Runnable() {
#Override
public void run() {
mDrawerToggle.syncState();
}
});
With that included, calling setHomeAsUpIndicator() is not needed.
The keyword here is NavigationDrawer; there's a full working code example on the Android developer site.
READ THE END OF THE LINK GIVEN : Open and Close with the App Icon
The following code is copied from there
public class MainActivity extends Activity {
private DrawerLayout mDrawerLayout;
private ActionBarDrawerToggle mDrawerToggle;
...
public void onCreate(Bundle savedInstanceState) {
...
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
mDrawerToggle = new ActionBarDrawerToggle(
this, /* host Activity */
mDrawerLayout, /* DrawerLayout object */
R.drawable.ic_drawer, /* nav drawer icon to replace 'Up' caret */
R.string.drawer_open, /* "open drawer" description */
R.string.drawer_close /* "close drawer" description */
) {
/** Called when a drawer has settled in a completely closed state. */
public void onDrawerClosed(View view) {
getActionBar().setTitle(mTitle);
}
/** Called when a drawer has settled in a completely open state. */
public void onDrawerOpened(View drawerView) {
getActionBar().setTitle(mDrawerTitle);
}
};
// Set the drawer toggle as the DrawerListener
mDrawerLayout.setDrawerListener(mDrawerToggle);
getActionBar().setDisplayHomeAsUpEnabled(true);
getActionBar().setHomeButtonEnabled(true);
}
#Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
// Sync the toggle state after onRestoreInstanceState has occurred.
mDrawerToggle.syncState();
}
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
mDrawerToggle.onConfigurationChanged(newConfig);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Pass the event to ActionBarDrawerToggle, if it returns
// true, then it has handled the app icon touch event
if (mDrawerToggle.onOptionsItemSelected(item)) {
return true;
}
// Handle your other action bar items...
return super.onOptionsItemSelected(item);
}
...
}
Some files are available as download and the small 3 lines with the animation effect is fully exemplified.
You have to copy thoses files in the corresponding drawable folder. Depending on the theme you use, dark or light you have a different set of icons.
In my case I simply copied the drawer_shadow.9.png and ic_drawer.png in the drawable folder and followed the example and everything works just fine.
The icons are available in the link I provided, but they are NOT in the "Action Bar Icon Pack", they are in the sample app in the corresponding res/drawable folders.