I want to animate the drawer icon from a burger to an arrow and vice versa manually, not only when drawer is being dragged, is it possible? I'm using support library appcompat-v7:21.
Also I can't find the source code of android.support.v7.app.ActionBarDrawerToggle which would helpful.
I found a way to animate the icon with a simple ValueAnimator and .onDrawerSlide method.
ValueAnimator anim = ValueAnimator.ofFloat(start, end);
anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
float slideOffset = (Float) valueAnimator.getAnimatedValue();
drawerToggle.onDrawerSlide(drawerLayout, slideOffset);
}
});
anim.setInterpolator(new DecelerateInterpolator());
anim.setDuration(300);
anim.start();
But maybe there is a better solution.
// define your drawer layout
DrawerLayout drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
// define your actionbar toggle
final ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
// Pass in context
this,
// Pass in your drawer layout
drawerLayout,
// Pass a String resource to describe the "open drawer" action for accessibility
R.string.open_drawer,
// Pass a String resource to describe the "close drawer" action for accessibility
R.string.close_drawer
);
// add a drawerListener to your drawer layout
drawerLayout.setDrawerListener(new DrawerLayout.DrawerListener() {
#Override
public void onDrawerSlide(View drawerView, float slideOffset) {
// Here's where the animation happens.
// the provided float starts at 0 (drawer closed) and goes to 1 (drawer open) hitting all points in between.
// ActionBarDrawerToggle has an onDrawerSlide method that takes your drawer layout and the provided float from the onDrawerSlide constructor.
// By passing the slideOffSet from the drawer's OnDrawerSlide method into the toggle, it maps the animation to the provided float.
toggle.onDrawerSlide(drawerView, slideOffset);
}
#Override
public void onDrawerOpened(View view) {
}
#Override
public void onDrawerClosed(View view) {
}
#Override
public void onDrawerStateChanged(int i) {
}
});
EDIT: The above will work, but I found a much more elegant way to do this. By setting the toggle as the drawer's listener, the states are handled by default. See below:
// define your drawer layout
drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
// define your actionbar drawertoggle
drawerToggle = new ActionBarDrawerToggle(
// Pass in context
this,
// Pass in your drawer layout
drawerLayout,
// Attach the toolbar
toolbar,
// Pass a String resource to describe the "open drawer" action for accessibility
R.string.open_drawer,
// Pass a String resource to describe the "close drawer" action for accessibility
R.string.close_drawer
) {
// attach drawer listener states to the ActionBarDrawerToggle
public void onDrawerClosed(View view) {
super.onDrawerClosed(view);
invalidateOptionsMenu();
}
public void onDrawerOpened(View drawerView) {
super.onDrawerOpened(drawerView);
invalidateOptionsMenu();
}
};
drawerLayout.setDrawerListener(drawerToggle);
drawerToggle.syncState();
Related
I have a drawerLayout (support.v4) with a navigationView and have many (like many up to n menu items) menu items. To have less items on the screen at the same time, some menu items lead to another menu with many items.
The thing is, my menu switch works fine, I'm able to pass from one menu to the other one but I have no animation... I want to close the drawer when an item linked to another menu is selected and once the menu is loaded, to open it again.
Here's my code:
navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(MenuItem selectedItem) {
mDrawerLayout.closeDrawer(GravityCompat.START);
Log.d(MainActivity.class.getName(), selectedItem.toString());
MobileXMLMenu menu = UserMenu.getInstance().getMenu();
for(int i = 0; i < menu.sizeMenuItems(); i++){
if(menu.getMenuItem(i).getLabel(Utility.retreiveLanguage()).equals(selectedItem.toString())){
Log.d(MainActivity.class.getName(), menu.getMenuItem(i).sizeMenuItems() + "");
if(menu.getMenuItem(i).sizeMenuItems() > 0){
Menu nMenu = navigationView.getMenu();
nMenu.clear();
for(int j = 0; j < menu.getMenuItem(i).sizeMenuItems(); j++){
MobileXMLMenuItem item = menu.getMenuItem(i).getMenuItem(j);
nMenu.add(item.getLabel(Utility.retreiveLanguage())).setIcon(MemberOptionsManager.getInstance().getMenuItemIcon(item.getDecorator()));
}
mDrawerLayout.openDrawer(GravityCompat.START);
isInSubmenu = true;
}
}
}
return false;
}
});
I also have this for my ActionBarDrawerToggle (don't know if this could help):
mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, mToolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close){
public void onDrawerClosed(View view){
super.onDrawerClosed(view);
getSupportActionBar().setTitle(mFragment.getFragmentName());
invalidateOptionsMenu();
mDrawerToggle.syncState();
}
public void onDrawerOpened(View drawerView){
super.onDrawerClosed(drawerView);
getSupportActionBar().setTitle("Open");
invalidateOptionsMenu();
mDrawerToggle.syncState();
}
};
When I select an item not link to any sub menu, the drawer closes, but otherwise, I see no animation, just the menu content changing with no animation. How can I force my app to wait for the drawer to close before changing the menu content?
Thanks!
You can use callback methods of the drawer layout from official documentation of the android.
onDrawerClosed(View drawerView)
onDrawerOpened(View drawerView)
onDrawerSlide(View drawerView, float slideOffset)
onDrawerStateChanged(int newState)
You can find more at link:http://developer.android.com/reference/android/support/v4/widget/DrawerLayout.DrawerListener.html
You can setDrawerListener on DrawLayout like this
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, mDrawerLayout, mToolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close) {
public void onDrawerClosed(View view) {
handleClickNavigationItem(mClickedNavigationItem);
}
public void onDrawerOpened(View drawerView) {
}
};
mDrawerLayout.setDrawerListener(toggle);
handleClickNavigationItem method contains the code which handle navigation event.
And just save clicked item in onNavigationItemSelected method
public boolean onNavigationItemSelected(MenuItem item) {
mClickedNavigationItem = item.getItemId();
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
return true;
}
I am having trouble with changing my navigation drawer icon to a custom one. I've currently had to implement the standard drawer icon which has 3 horizontal lines on top, but now I want to replace this with my custom drawer icon.
This is how my mDrawerToggle is at the moment:
mDrawerToggle=new ActionBarDrawerToggle(this,
mDrawerLayout,
R.drawable.app_icon,
R.string.drawer_open) {
// My code
};
Use below code,it's working for V7 ActionBarDrawerToggle
mDrawerToggle.setDrawerIndicatorEnabled(false);
mDrawerToggle.setHomeAsUpIndicator(R.drawable.your_custom_icon);
mDrawerToggle.setToolbarNavigationClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (mDrawerLayout.isDrawerVisible(GravityCompat.START)) {
mDrawerLayout.closeDrawer(GravityCompat.START);
} else {
mDrawerLayout.openDrawer(GravityCompat.START);
}
}
});
Here is the sample code taken from
Creating a Navigation Drawer
Activity.class
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) {
super.onDrawerClosed(view);
getActionBar().setTitle(mTitle);
}
/** Called when a drawer has settled in a completely open state. */
public void onDrawerOpened(View drawerView) {
super.onDrawerOpened(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);
}
...
}
This is main activity
final DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
toggle.setDrawerIndicatorEnabled(false);
toggle.setToolbarNavigationClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
drawer.openDrawer(GravityCompat.START);
}
});
toggle.setHomeAsUpIndicator(R.drawable.menuicon);
You could use this format for your mDrawerToggle:
mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout,
R.drawable.CUSTOM_ICON, // Navigation menu toggle icon
R.string.DRAWER_OPEN, // Navigation drawer open description
R.string.DRAWER_CLOSE // Navigation drawer close description
)
Change your drawable and make sure it is the same name as the one in the code.
This is the main layout file
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<!-- Framelayout to display Fragments -->
<FrameLayout
android:id="#+id/frame_container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<!-- Listview to display slider menu -->
<ListView
android:id="#+id/list_slidermenu"
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="#color/white"
android:choiceMode="singleChoice"
android:divider="#color/black"
android:dividerHeight="1dp" />
</android.support.v4.widget.DrawerLayout>
This is the main Activity
DrawerLayout mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
ActionBarDrawerToggle mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout,
R.drawable.menuicon, // nav menu toggle icon
R.string.app_name, // nav drawer open - description for
// accessibility
R.string.app_name // nav drawer close - description for
// accessibility
) {
public void onDrawerClosed(View view) {
// getActionBar().setTitle(mTitle);
// calling onPrepareOptionsMenu() to show action bar icons
invalidateOptionsMenu();
}
public void onDrawerOpened(View drawerView) {
// getActionBar().setTitle(mDrawerTitle);
// calling onPrepareOptionsMenu() to hide action bar icons
invalidateOptionsMenu();
}
};
mDrawerLayout.setDrawerListener(mDrawerToggle);
finally at R.drawable.menuicon(you can give your image id) it will work.
I have implemented a basic ActionBarDrawerToggle using the new Toolbar in Android 5.0.
However, I am unable to figure out how to change the default hamburger icon that is supplied.
From the android documentation it says that "the given Activity will be linked to the specified DrawerLayout and the Toolbar's navigation icon will be set to a custom drawable... This drawable shows a Hamburger icon when drawer is closed and an arrow when drawer is open. It animates between these two states as the drawer opens."
I currently have this all working correctly with the following code, however I want to replace the default supplied hamburger with my own drawable.
Here is my current code:
MainActivity.java
#InjectView(R.id.main_activity_toolbar)
Toolbar mToolbar;
#InjectView(R.id.main_activity_drawer_layout)
DrawerLayout mDrawerLayout;
#Override
protected void onCreate(Bundle savedInstanceState) {
setContentView(R.layout.main_activity);
super.onCreate(savedInstanceState);
setSupportActionBar(mToolbar);
mToolbar.setNavigationIcon(R.drawable.navigation);
mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, mToolbar, R.string.drawer_open, R.string.drawer_close) {
public void onDrawerClosed(View view) {
super.onDrawerClosed(view);
invalidateOptionsMenu();
}
public void onDrawerOpened(View drawerView) {
super.onDrawerOpened(drawerView);
invalidateOptionsMenu();
}
};
mDrawerLayout.setDrawerListener(mDrawerToggle);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeButtonEnabled(true);
}
This line:
mToolbar.setNavigationIcon(R.drawable.navigation);
doesn't seem to work.
Is this possible to do? Thanks!
ActionBarToggle Documentation - https://developer.android.com/reference/android/support/v7/app/ActionBarDrawerToggle.html
You can use the toolbar as Stand Alone mode, that means you should not use your toolbar as part of your ActionBarDrawerToggle constructor, you can achieve that using the below code:
mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, null,
R.drawable.appbar, R.drawable.appbar)
(Note how the toolbar instance is not being sent to the ActionBarDrawerToggle constructor)
Also, you should inflate your menu manually
mToolbar = (Toolbar) findViewById(R.id.nav_toolbar);
mToolbar.inflateMenu(R.menu.base);
And remove the setSupportActionBar(mToolbar); line of code.
Of course, you will have to handle the navigation click by yourself:
mToolbar.setOnMenuItemClickListener(new OnMenuItemClickListener() ...
Then, you can open your drawer like this:
drawerButton = (BadgeDrawerButton) findViewById(R.id.badge_drawer_button);
drawerButton.setOnClickListener(
new View.OnClickListener() {
#Override
public void onClick(View v) {
mDrawerLayout.openDrawer(Gravity.LEFT);
}
});
Hope this may help.
These two lines of code work for me:
mDrawerToggle.setDrawerIndicatorEnabled(false); //disable "hamburger to arrow" drawable
mDrawerToggle.setHomeAsUpIndicator(R.drawable.ic_drawer); //set your own
And then call this:
mDrawerToggle.syncState();
The default menu drawable for the ActionBarDrawerToggle is DrawerArrowDrawable.
You can subclass this to add custom functionality, like badges, like so:
public class BadgedDrawerArrowDrawable extends DrawerArrowDrawable {
/**
* #param context used to get the configuration for the drawable from
*/
public BadgedDrawerArrowDrawable(Context context) {
super(context);
setColor(context.getResources().getColor(R.color.colorAccent));
}
#Override
public void draw(Canvas canvas) {
super.draw(canvas);
Paint paint = new Paint();
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.RED);
paint.setTextSize(60);
canvas.drawText("!", canvas.getWidth() - 60, 25, paint);
}
}
Usage:
actionBarDrawerToggle.setDrawerArrowDrawable(new BadgedDrawerArrowDrawable(activity));
My solution is by subclassing ActionBarDrawerToggle.
public class MyActionBarDrawerToggle extends android.support.v7.app.ActionBarDrawerToggle {
public MyActionBarDrawerToggle(Activity activity, final DrawerLayout drawerLayout, Toolbar toolbar, int openDrawerContentDescRes, int closeDrawerContentDescRes) {
super(activity, drawerLayout, toolbar, openDrawerContentDescRes, closeDrawerContentDescRes);
setHomeAsUpIndicator(R.drawable.drawer_toggle);
setDrawerIndicatorEnabled(false);
setToolbarNavigationClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
drawerLayout.openDrawer(Gravity.LEFT);
}
});
}
}
the thing that worked for me is that i just needed to call toolbar.setNavigationIcon(R.drawable.ic_camera_alt_24dp);
at the end of onCreate, or at least after mDrawerToggle = new ActionBarDrawerToggle...
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
final DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
final ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this,drawer,toolbar,R.string.navigation_drawer_open,R.string.navigation_drawer_close);
drawer.setDrawerListener(toggle);
toggle.syncState();
toolbar.setNavigationIcon(R.drawable.ic_action_name);
as of Jan 2018, this is a working solution (at least for me):
//setSupportActionBar(toolbar)
val toggle = ActionBarDrawerToggle(this, drawer_layout, null, R.string.navigation_drawer_open, R.string.navigation_drawer_close)
toolbar.inflateMenu(R.menu.menu_main)
toolbar.setNavigationIcon(R.drawable.ic_menu)
toolbar.setNavigationOnClickListener {
drawer_layout.openDrawer(Gravity.START)
}
toolbar.setOnMenuItemClickListener {
true
}
drawer_layout.addDrawerListener(toggle)
toggle.syncState()
nav_view.setNavigationItemSelectedListener(this)
things to care:
setSupportActionBar should be commented out
ActionBarDrawerToggle is not taking a reference to toolbar
We should inflate menu ourself, and handle onClicks. onCreateOptionsMenu and onOptionsItemSelected will not be functioning.
Don't forget to call toggle.syncState()
As for v7 support library - you can create your own representation of DrawerArrowDrawable.
mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close) {
public void onDrawerClosed(View view) {
supportInvalidateOptionsMenu();
}
public void onDrawerOpened(View drawerView) {
supportInvalidateOptionsMenu();
}
};
mDrawerToggle.setDrawerIndicatorEnabled(true);
DrawerArrowDrawable drawerArrowDrawable = new DrawerArrowDrawable(this);
drawerArrowDrawable.setAlpha(1);
drawerArrowDrawable.setSpinEnabled(false);
drawerArrowDrawable.setDirection(DrawerArrowDrawable.ARROW_DIRECTION_LEFT);
drawerArrowDrawable.setColor(Color.BLACK);
mDrawerToggle.setDrawerArrowDrawable(drawerArrowDrawable);
Here's how I was able to finally get mine to work.
private Toolbar toolbar;
toolbar = (Toolbar) findViewById(R.id.toolbar);
if (toolbar != null) {
setSupportActionBar(toolbar);
toolbar.setNavigationIcon(R.drawable.ic_drawer);
mDrawerToggle = new ActionBarDrawerToggle(this,
mDrawerLayout,
toolbar,
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);
}
/** Called when a drawer has settled in a completely open state. */
public void onDrawerOpened(View drawerView) {
super.onDrawerOpened(drawerView);
}
};
// Set the drawer toggle as the DrawerListener
mDrawerLayout.setDrawerListener(mDrawerToggle);
mDrawerToggle.syncState();
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeButtonEnabled(true);
}
It turned out to be the
mDrawerToggle.syncState();
That finally got everything to work.
I think it is recommended to put the call to syncState() in the onPostCreate(...) lifecycle method.
#Override
public void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
mDrawerToggle.syncState();
}
I have two fragments in an activity. When fragment A is showing, I want the navigation drawer burger icon to show and the navigation drawer to work. When fragment B is showing, I want the back arrow to show and when it's clicked do an up navigation. However, I can't seem to get the new AppCompat v7 toolbar to show the up arrow at all inside my ActionBarActivity unless the nav drawer is open.
In my activity, for my onCreate() method I have...
toolbar = (Toolbar) findViewById(R.id.toolbar);
if (toolbar != null) {
setSupportActionBar(toolbar);
}
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, toolbar, R.string.drawer_open, R.string.drawer_close);
mDrawerLayout.setDrawerListener(mDrawerToggle);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeButtonEnabled(true);
And then I call mDrawerToggle.syncState(); in my onPostCreate()
I've tried searching on how to programatically trigger the toolbar icon to the back arrow but nothing has worked. From what I've gathered, calling
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowHomeEnabled(true);
getSupportActionBar().setHomeButtonEnabled(true);
from my fragment should change the icon but that's not the case. This may be a stupid question, but what am I doing wrong?
From what I have seen in the source code of v7 ActionBarDrawerToggle, you can animate the icon to different states without having the drawer being opened.
private enum ActionDrawableState{
BURGER, ARROW
}
private static void toggleActionBarIcon(ActionDrawableState state, final ActionBarDrawerToggle toggle, boolean animate){
if(animate) {
float start = state == ActionDrawableState.BURGER ? 0f : 1.0f;
float end = Math.abs(start - 1);
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
ValueAnimator offsetAnimator = ValueAnimator.ofFloat(start, end);
offsetAnimator.setDuration(300);
offsetAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
offsetAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator animation) {
float offset = (Float) animation.getAnimatedValue();
toggle.onDrawerSlide(null, offset);
}
});
offsetAnimator.start();
}else{
//do the same with nine-old-androids lib :)
}
}else{
if(state == ActionDrawableState.BURGER){
toggle.onDrawerClosed(null);
}else{
toggle.onDrawerOpened(null);
}
}
}
Morphing between Burger and Arrow depends on values between 0f and 1.0f, basically these are values that the drawer passes to the ActionBarDrawerToggle.
I used ValueAnimator to animate values in this range, i.e mimicking the drawer toggling.
null arguments are safe because ActionBarDrawerToggle does not care at all about drawer views.
Make sure you take a look at new interpolators to do the animation fully-by-the-book of material design guidelines:
fast_out_linear_in
fast_out_slow_in
Another approach is to access mSlider private field of the ActionBarDrawer through reflection and call setPosition(float position) method to toggle between Burger and Arrow.
mSlider is of type (extends) DrawerArrowDrawable.
Personally, I always try to avoid reflection, as long as there is no other way to do your dirty work.
As Support Library updated to 23.0.0, there is a better way to play drawer-arrow animation. So I'm going to improve #Nikola's answer. Here's code:
public static void playDrawerToggleAnim(final DrawerArrowDrawable d) {
float start = d.getProgress();
float end = Math.abs(start - 1);
ValueAnimator offsetAnimator = ValueAnimator.ofFloat(start, end);
offsetAnimator.setDuration(300);
offsetAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
offsetAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator animation) {
float offset = (Float) animation.getAnimatedValue();
d.setProgress(offset);
}
});
offsetAnimator.start();
}
And call it whenever you want by:
playDrawerToggleAnim((DrawerArrowDrawable) toolbar.getNavigationIcon());
getSupportFragmentManager().addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() {
#Override
public void onBackStackChanged() {
int stackHeight = getSupportFragmentManager().getBackStackEntryCount();
if (stackHeight > 0) { // if we have something on the stack (doesn't include the current shown fragment)
getSupportActionBar().setHomeButtonEnabled(true);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
} else {
getSupportActionBar().setDisplayHomeAsUpEnabled(false);
getSupportActionBar().setHomeButtonEnabled(false);
}
}
});
After ...
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
getSupportFragmentManager().popBackStack();
return true;
....
}
In my case the icon is animating:
I have used ActionBarDrawerToggle v7.
MainActivity:
Toolbar toolbar = (Toolbar) findViewById(R.id.tool1);
setSupportActionBar(toolbar);
toolbar.setTitle("ToolBar Demo");
toolbar.setLogo(R.drawable.ic_launcher);
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawerLayout);
mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, toolbar,
R.string.open_navigation_drawer,
R.string.close_navigation_drawer) {
#Override
public void onDrawerSlide(View drawerView, float slideOffset) {
// TODO Auto-generated method stub
super.onDrawerSlide(drawerView, slideOffset);
}
/** Called when a drawer has settled in a completely closed state. */
#Override
public void onDrawerClosed(View view) {
super.onDrawerClosed(view);
getSupportActionBar().setTitle("hello");
}
/** Called when a drawer has settled in a completely open state. */
#Override
public void onDrawerOpened(View drawerView) {
super.onDrawerOpened(drawerView);
getSupportActionBar().setTitle("hi");
}
};
mDrawerLayout.setDrawerListener(mDrawerToggle);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) { // <---- added
if (mDrawerToggle.onOptionsItemSelected(item)) {
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
protected void onPostCreate(Bundle savedInstanceState) { // <---- added
super.onPostCreate(savedInstanceState);
mDrawerToggle.syncState(); // important statetment for drawer to
// identify
// its state
}
#Override
public void onConfigurationChanged(Configuration newConfig) { // <---- added
super.onConfigurationChanged(newConfig);
mDrawerToggle.onConfigurationChanged(newConfig);
}
#Override
public void onBackPressed() {
if (mDrawerLayout.isDrawerOpen(Gravity.START | Gravity.LEFT)) { // <----
// added
mDrawerLayout.closeDrawers();
return;
}
super.onBackPressed();
}
I have adapted the navigation drawer with an icon in my appliccation as shown in the figure1, it seems ok.
I want to have the icon on the right bottom side of my menu as google maps did.
code:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_map);
setupSlideMenu();
}
private void setupSlideMenu() {
mPlanetTitles = getResources().getStringArray(R.array.planets_array);
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout1);
addIcon();
mDrawerList = (ListView) findViewById(R.id.left_drawer1);
// Set the adapter for the list view
mDrawerList.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, mPlanetTitles));
// Set the list's click listener
mDrawerList.setOnItemClickListener(new DrawerItemClickListener());
log("setupSlideMenu", false);
}
private void addIcon() {
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);
}
Any idea?
Thanks in advance!
Use BottomDrawerToggle.
Solution was pretty simple:
Added ImageView to the android.R.id.content FrameLayout with gravity BOTTOM
Made ImageView half visible by setting right/left margin to negative value of the half of it's drawable width.
Resolved internal resource action_bar_icon_vertical_padding and used it as bottom padding of the image view
int id = Resources.getSystem().getIdentifier("action_bar_icon_vertical_padding", "dimen", "android");
float padding = mActivity.getResources().getDimension(id);
Created SlidingDrawable and calculated how to dynamically hide the the drawable as the drawer slides in/out in draw(Canvas canvas) method. Drawable is hid by clipping the Rect with drawer's amount of visible pixels.
public void draw(Canvas canvas)
{
float pixelsVisible = mOffset * mMinusShadow;
int target = (int) ((mWrapped.getIntrinsicWidth()/2)+pixelsVisible);
if(mGravity == GravityCompat.START || mGravity == Gravity.LEFT)
canvas.clipRect(target, 0, mWrapped.getIntrinsicWidth(), mWrapped.getIntrinsicHeight());
else
canvas.clipRect(0, 0, mWrapped.getIntrinsicWidth() - target,mWrapped.getIntrinsicHeight());
this.mWrapped.draw(canvas);
canvas.restore();
}