My BaseDrawerActivity extends BaseActivity and I have a Toolbar in BaseActivity.
The toolbar shows with no issues in classes that extend BaseActivity, but ALL classes that extend BaseDrawerActivity just show a blank toolbar. The nav drawer works fine.
When I had one main activity class (BaseActivity + BaseDrawerActivity) the toolbar showed no problem and the nav drawer worked.
Why is my implementation here not showing the Toolbar? I debugged and getToolbar() is returning the toolbar for sure.
activity_base_drawer.xml
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<include layout="#layout/toolbar"/>
<android.support.v4.widget.DrawerLayout
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:foreground="?android:windowContentOverlay">
<FrameLayout
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<include layout="#layout/call_to_action_banner"/>
</FrameLayout>
<ListView
android:id="#+id/navigation_drawer"
android:layout_width="#dimen/navigation_drawer_width"
android:layout_height="match_parent"
android:layout_gravity="start"
style="#style/NavDrawerListView" />
</android.support.v4.widget.DrawerLayout>
</LinearLayout>
toolbar.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.Toolbar
xmlns:android="http://schemas.android.com/apk/res/android"
android:theme="#style/ToolbarOverlay"
android:popupTheme="#style/ToolbarOverlay"
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#android:color/white"
android:minHeight="?attr/actionBarSize"
android:elevation="10dp"/>
BaseDrawerActivity
public abstract class BaseDrawerActivity extends BaseActivity {
private static final int LAYOUT_ID = R.layout.activity_base_drawer;
private DrawerLayout mDrawerLayout;
private ActionBarDrawerToggle mDrawerToggle;
private NavDrawerAdapter mNavDrawerAdapter;
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
mDrawerToggle.onConfigurationChanged(newConfig);
}
#Override
public void onBackPressed() {
if (mDrawerLayout.isDrawerOpen(GravityCompat.START)){
mDrawerLayout.closeDrawers();
} else {
super.onBackPressed();
}
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (mDrawerToggle.onOptionsItemSelected(item)) {
return true;
} else {
return super.onOptionsItemSelected(item);
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(LAYOUT_ID);
setupNavDrawer();
}
#Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
// Sync the toggle state after onRestoreInstanceState has occurred.
mDrawerToggle.syncState();
}
private void setupNavDrawer() {
final ListView navDrawerListView = (ListView) findViewById(R.id.navigation_drawer);
View header = getLayoutInflater().inflate(R.layout.nav_drawer_header, null, false);
mNavDrawerAvatarImageView = (ImageView) header.findViewById(R.id.avatar);
mNavDrawerUsernameTextView = (CustomTextView) header.findViewById(R.id.username);
navDrawerListView.addHeaderView(header);
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
mDrawerToggle = new ActionBarDrawerToggle(
this,
mDrawerLayout,
getToolbar(),
R.string.navigation_drawer_open,
R.string.navigation_drawer_close) {
/** Called when a drawer has settled in a completely closed state. */
public void onDrawerClosed(View view) {
super.onDrawerClosed(view);
invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()
}
/** Called when a drawer has settled in a completely open state. */
public void onDrawerOpened(View drawerView) {
super.onDrawerOpened(drawerView);
updateNavDrawerUserInfo();
invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()
}
};
mDrawerLayout.setDrawerListener(mDrawerToggle);
mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START);
mNavDrawerAdapter = new NavDrawerAdapter(this);
navDrawerListView.setAdapter(mNavDrawerAdapter);
navDrawerListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
mDrawerLayout.closeDrawer(GravityCompat.START);
onNavigationDrawerItemSelected(position);
}
});
updateNavDrawerUserInfo();
}
private void updateNavDrawerUserInfo() {
final DatabaseHelper db = DatabaseHelper.getInstance(this);
if (db.doesUserExist(SharedPrefs.getUserId())) {
final User currentUser = db.getUser(SharedPrefs.getUserId());
if (currentUser != null) {
if (currentUser.getAvatarType() != null) {
try {
mNavDrawerAvatarImageView.setImageDrawable(getResources().getDrawable(
ViewUtil.getAvatarHeadDrawableId(this,
currentUser.getAvatarType())));
} catch (Resources.NotFoundException e) {
e.printStackTrace();
}
}
if (currentUser.getUsername() != null) {
mNavDrawerUsernameTextView.setText(currentUser.getUsername());
}
}
}
}
}
BaseActivity
private void setupToolbar() {
mToolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(mToolbar);
if (getSupportActionBar() != null) {
getSupportActionBar().setTitle("");
getSupportActionBar().setSubtitle("");
getSupportActionBar().setLogo(R.drawable.logo_toolbar);
}
mUpdatingSpinner = (ProgressBar) getLayoutInflater().inflate(
R.layout.toolbar_updating_spinner, null, false);
int dpInPixels = (int) getResources().getDimension(R.dimen.toolbar_updating_spinner);
Toolbar.LayoutParams spinnerLp = new Toolbar.LayoutParams(dpInPixels, dpInPixels,
Gravity.END);
mToolbar.addView(mUpdatingSpinner, spinnerLp);
}
I found the answer although I don't fully understand it.
I basically called setupToolbar() again in my BaseDrawerActivity right before I call setupNavDrawer() and for some reason this fixed it.
I think the reference to the Toolbar from BaseActivity wasn't retrieving correctly (even though I debugged and it had a reference to it). Another thing I tried is setSupportActionBar(mToolbar) right before setting up the nav drawer but that didn't work.
If anyone has any ideas as to why I have to setup the toolbar again in order for it to show I'd be glad to hear it!
go to the AndroidManifest.xml file and replace
android:theme="#style/AppTheme"
with
android:theme="#android:style/Theme.Holo.Light.DarkActionBar"
you have to use setSupportActionBar(Toolbar toolbar).
This question should help.
Related
Hiho!
I build a navigation drawer into my android app. I used the howto from http://blog.teamtreehouse.com/add-navigation-drawer-android and modified it at one place of the layout. I can activate the menu when i touch and swing my finger from left to right. But if I touch the hamburger menu nothing hapend. What ist wrong?
If i swipped in the menu the icon changed to an arrow, so there is a connection.
Hope some one can help me.
My Java Class (Main Activity):
public class AmericanFootball extends AppCompatActivity {
private MenuItem mi;
public static Context context;
private ListView mDrawerList;
private ArrayAdapter<String> mAdapter;
private ActionBarDrawerToggle mDrawerToggle;
private DrawerLayout mDrawerLayout;
private String mActivityTitle;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
context = (Context) this;
setContentView(R.layout.activity_american_football);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
toolbar.setTitle(getText(R.string.app_name));
setSupportActionBar(toolbar);
mDrawerList = (ListView)findViewById(R.id.navList);
mDrawerLayout = (DrawerLayout)findViewById(R.id.drawerLayout);
mActivityTitle = getTitle().toString();
addDrawerItems();
setupDrawer();
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeButtonEnabled(true);
checkInternet ci = new checkInternet();
boolean internet=ci.isNetzwerkVerfuegbar((Context) this);
TextView tv = (TextView) findViewById(R.id.tv_hello);
tv.setTypeface(FontManager.getTypeface((Context) this, FontManager.FONTAWESOME));
tv.setText(R.string.fa_icon_areachart);
tv.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.colorPrimaryLight));
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_american_football, menu);
MenuItem mi = menu.findItem(R.id.action_refresh);
TextDrawable td = new TextDrawable((Context) this);
td.setText(getString(R.string.fa_refresh));
td.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.colorPrimaryLight));
td.setTextSize(30);
mi.setIcon(td);
LayoutInflater inflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
ImageView iv = (ImageView)inflater.inflate(R.layout.iv_refresh, null);
iv.setImageDrawable(td);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
if (id == R.id.action_refresh) {
doRefreshGames(item);
}
return super.onOptionsItemSelected(item);
}
#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);
}
private void addDrawerItems() {
String[] osArray = { "Android", "iOS", "Windows", "OS X", "Linux" };
mAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, osArray);
mDrawerList.setAdapter(mAdapter);
mDrawerList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Toast.makeText(AmericanFootball.this, "Time for an upgrade!", Toast.LENGTH_SHORT).show();
}
});
}
private void setupDrawer() {
mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, R.string.drawer_open, R.string.drawer_close) {
/** Called when a drawer has settled in a completely open state. */
public void onDrawerOpened(View drawerView) {
super.onDrawerOpened(drawerView);
getSupportActionBar().setTitle("Navigation!");
invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()
}
/** Called when a drawer has settled in a completely closed state. */
public void onDrawerClosed(View view) {
super.onDrawerClosed(view);
getSupportActionBar().setTitle(mActivityTitle);
invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()
}
};
mDrawerToggle.setDrawerIndicatorEnabled(true);
mDrawerLayout.setDrawerListener(mDrawerToggle);
}
}
My layoutfile:
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context="k0f.de.americanfootball.AmericanFootball">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="#style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="#style/AppTheme.PopupOverlay" />
</android.support.design.widget.AppBarLayout>
<include layout="#layout/content_american_football" />
<android.support.v4.widget.DrawerLayout
android:id="#+id/drawerLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<ListView
android:id="#+id/navList"
android:layout_width="200dp"
android:layout_height="match_parent"
android:layout_gravity="left|start"
android:background="#ffeeeeee"/>
</android.support.v4.widget.DrawerLayout>
</android.support.design.widget.CoordinatorLayout>
I found my mistake. Forgot a little thing:
public boolean onOptionsItemSelected(MenuItem item) {
if (mDrawerToggle.onOptionsItemSelected(item)) {
return true;
}
}
Getting wired output
When i click on TextView of Navigation Drawer click goes to fragment in back (Main Content Fragment)
Please someone help what wrong i am doing.
layout code
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<!-- The toolbar -->
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:title="#string/app_name" />
<android.support.v4.widget.DrawerLayout
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/white">
<!-- The main content view -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<include layout="#layout/content_main" />
</LinearLayout>
<!-- The navigation drawer -->
<fragment
android:id="#+id/left_drawer"
android:name="app.compiler.fragment.FragmentDrawer"
android:layout_width="320dp"
android:layout_height="match_parent"
android:layout_gravity="start"
tools:layout="#layout/fragment_drawer"
/>
</android.support.v4.widget.DrawerLayout>
Java code
public class ActivityMain extends AppCompatActivity {
DrawerLayout mDrawerLayout;
ActionBarDrawerToggle mDrawerToggle;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_ide);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
mDrawerToggle= new ActionBarDrawerToggle(this, mDrawerLayout,toolbar, R.string.app_name, R.string.app_name)
{
/** Called when a drawer has settled in a completely open state. */
public void onDrawerOpened(View drawerView) {
}
/** Called when a drawer has settled in a completely closed state. */
public void onDrawerClosed(View view) {
}
};
mDrawerLayout.setDrawerListener(mDrawerToggle);
if (savedInstanceState == null) {
FragmentMain fragmentMain = new FragmentMain();
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.add(R.id.container, fragmentMain);
transaction.commit();
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = new MenuInflater(this);
inflater.inflate(R.menu.menu_main,menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (mDrawerToggle.onOptionsItemSelected(item)) {
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
mDrawerToggle.syncState();
}
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
mDrawerToggle.onConfigurationChanged(newConfig);
}
#Override
public void onBackPressed() {
if(mDrawerLayout.isDrawerOpen(Gravity.START | Gravity.LEFT)){
mDrawerLayout.closeDrawers();
return;
}
super.onBackPressed();
}
}
Check code output in gif image below
Make sure that everything within your left-drawer-layout is clickable. Otherwise, clicks will be passed to the underlying view, in this case to your main-content. You can do so by setting an OnClickListener to the rootview of your FragmentDrawer:
myFragmentInsideTheDrawer.getView().setOnClickListener(new OnClickListener() {
#Override
public void onClick(View pView) {
// do nothing here, just intercept click-events
}
});
In inDrawerOpen method you can use yourcontentlayout.setEnabled(false) and in onDrawerClosed method yourcontentlayout.setEnabled(true)
Hope this helps!
I have an activity with navigation drawer and toolbar
Activity
public class MainActivity extends AppCompatActivity {
private Toolbar toolbar;
private CustomTextViewMondaRegular tvTitle;
private ListView mDrawerList;
private DrawerLayout mDrawerLayout;
private ActionBarDrawerToggle mDrawerToggle;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
toolbar = (Toolbar) findViewById(R.id.tool_bar);
setSupportActionBar(toolbar);
mDrawerList = (ListView) findViewById(R.id.left_drawer);
tvTitle = (CustomTextViewMondaRegular) findViewById(R.id.actionTitle);
tvTitle.setText(getIntent().getStringExtra("title"));
mDrawerList.setAdapter(new NavAdapter(getApplicationContext()));
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
mDrawerList.setOnItemClickListener(new DrawerItemClickListener());
mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout,toolbar,
R.string.title_activity_main, R.string.title_activity_main) {
#Override
public void onDrawerClosed(View view) {
super.onDrawerClosed(view);
invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()
}
#Override
public void onDrawerOpened(View drawerView) {
super.onDrawerOpened(drawerView);
invalidateOptionsMenu();
// creates call to onPrepareOptionsMenu()
}
};
mDrawerLayout.setDrawerListener(mDrawerToggle);
if (savedInstanceState == null) {
}
}
#Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
mDrawerToggle.syncState();
}
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
mDrawerToggle.onConfigurationChanged(newConfig);
}
private class DrawerItemClickListener implements ListView.OnItemClickListener {
#Override
public void onItemClick(AdapterView parent, View view, int position, long id) {
Logger.e("pos", position + "");
}
}
}
Activity XML
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.vf.MainActivity">
<FrameLayout
android:id="#+id/frame_container"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.Toolbar
android:id="#+id/tool_bar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="#android:color/white"
android:elevation="3dp"
android:minHeight="?attr/actionBarSize"
android:theme="#style/MyDarkToolbarStyle">
<TextView
android:id="#+id/actionTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginEnd="5dp"
android:layout_marginRight="5dp"
android:drawableEnd="#drawable/logo"
android:drawableRight="#drawable/logo"
android:gravity="center"
android:text="XXXXXX"
android:textColor="#000000"
android:textSize="18sp" />
</android.support.v7.widget.Toolbar>
</FrameLayout>
<ListView
android:id="#+id/left_drawer"
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="#android:color/white"
android:choiceMode="singleChoice"
android:divider="#D8D8D8" />
The toggle icon currently shows the default icon. I need to change that icon. How can I do that?
For people who come across this SO question in future,
We have to disable drawer indicator
mDrawerToggle.setDrawerIndicatorEnabled(false);
and then set ToolBar's navigation button
mToolbar.setNavigationIcon(R.drawable.navIcon);
P.S. after that we have to set Navigation click listner on toolbar and open NavigationDrawer manualy.
like
mToolbar.setNavigationOnClickListener :D
Try the code below:
getSupportActionBar().setHomeButtonEnabled(true);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeAsUpIndicator(R.drawable.ic_menu_drawer);
mDrawerToggle.setDrawerIndicatorEnabled(false);
and open the drawer with
mImageView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
DrawerLayout drawer = findViewById(R.id.drawer_layout);
drawer.openDrawer(Gravity.START);
}
});
You can set the menu icon using setHomeAsUpIndicator, pass a drawable to this method.
See code below:
ActionBar ab = getSupportActionBar();
ab.setHomeAsUpIndicator(R.drawable.ic_menu);
ab.setDisplayHomeAsUpEnabled(true);
I'm using navigation drawer for a project, everything is working fine but one small problem, I always that arrow displayed not home button.
I tried everything found in the documentations, forums and here nothing is actually working.
What I tried so far:
mDrawerToggle.syncState();
actionBar.setDisplayShowTitleEnabled(true);
actionBar.setDisplayHomeAsUpEnabled(true);
#Override
public void onPostCreate(Bundle savedInstanceState, PersistableBundle persistentState) {
super.onPostCreate(savedInstanceState, persistentState);
mNavigationDrawerFragment.getmDrawerToggle().syncState();
}
ActionBar actionBar = getSupportActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
actionBar.setDisplayShowTitleEnabled(true);
actionBar.setDisplayHomeAsUpEnabled(true);
actionBar.setHomeButtonEnabled(true);
actionBar.setTitle(mTitle);
NavigationDrawerFragment:
// Defer code dependent on restoration of previous instance state.
mDrawerLayout.post(new Runnable() {
#Override
public void run() {
mDrawerToggle.syncState();
}
});
i have been busy making a simple app with navigation drawer..don't use template there are deprecated methods..
This is completely working.. i created this example.. try this..
your MainActivity
public class MainActivity extends ActionBarActivity {
Toolbar toolbar;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
toolbar = (Toolbar) findViewById(R.id.app_toolbar);
setSupportActionBar(toolbar);
Profile profile = (Profile) getSupportFragmentManager().findFragmentById(R.id.profileFragmentInMain);
profile.setUp((DrawerLayout) findViewById(R.id.drawer),toolbar);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
return super.onOptionsItemSelected(item);
}
This is your Fragment..
public class Profile extends Fragment {
ActionBarDrawerToggle drawerToggle;
DrawerLayout mDrawerLayout;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.profile, container, false);
return view;
}
public void setUp(DrawerLayout drawerLayout, Toolbar toolbar) {
mDrawerLayout = drawerLayout;
drawerToggle = new ActionBarDrawerToggle(getActivity(), drawerLayout, toolbar, R.string.open, R.string.close){
#Override
public void onDrawerOpened(View drawerView) {
super.onDrawerOpened(drawerView);
getActivity().invalidateOptionsMenu();
}
#Override
public void onDrawerClosed(View drawerView) {
super.onDrawerClosed(drawerView);
getActivity().invalidateOptionsMenu();
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item != null && item.getItemId() == android.R.id.home) {
if (mDrawerLayout.isDrawerOpen(Gravity.RIGHT)) {
mDrawerLayout.closeDrawer(Gravity.RIGHT);
} else {
mDrawerLayout.openDrawer(Gravity.RIGHT);
}
return true;
}
return false;
}
};
mDrawerLayout.setDrawerListener(drawerToggle);
mDrawerLayout.post(new Runnable(){
#Override
public void run(){
drawerToggle.syncState();
}
});
}
}
this is all in classes..
now xml layouts..
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:id="#+id/drawer"
android:layout_height="match_parent" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<include
android:id="#+id/app_toolbar"
layout="#layout/toolbar"/>
</LinearLayout>
<fragment
android:id="#+id/profileFragmentInMain"
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_gravity="start"
app:layout="#layout/profile"
android:name="com.example.ajay.myapplication.Profile"
tools:layout="#layout/profile"/>
</android.support.v4.widget.DrawerLayout>
your profile.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:theme="#android:style/Theme.Holo.Light.DialogWhenLarge.NoActionBar">
</LinearLayout>
your toolbar.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.Toolbar
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/app_toolbar" />
previews :
open the drawer
closed drawer
Additional Info : I have added toolbar which is Material Design implemetation of ActionBar. Its latest way to create Actionbar. You can use that. just in case, select Theme with NoActionbBar in your styles.xml file.
So I finally found the solution. I just took of this R.drawable.ic_drawer from:
drawerToggle = new ActionBarDrawerToggle(getActivity(), drawerLayout, R.drawable.ic_drawer, R.string.open, R.string.close);
And it worked like a charm.
My requirement is shown in the picture below My navigation drawer should be opened from the right side. I have implemented this. My navigation drawer open from right to left. But the problem is toggle icon is always on the left side. How can I set toggle icon to the right?
I have checked the following SO questions, but none of them came to any help:
Change toggle button image Icon In Navigation Drawer right to left
Drawer Toggle in right Drawer
enter link description here
Here is what I have tried:
code for my layout activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/drawer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:openDrawer="end">
<android.support.design.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context="com.example.nav.MainActivity"
android:foregroundGravity="right">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="end"
android:theme="#style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:layout_gravity="right"
app:popupTheme="#style/AppTheme.PopupOverlay"
android:foregroundGravity="right"
android:textAlignment="viewEnd"
android:touchscreenBlocksFocus="false" />
</android.support.design.widget.AppBarLayout>
<include layout="#layout/content_main" />
</android.support.design.widget.CoordinatorLayout>
<android.support.design.widget.NavigationView
android:id="#+id/navigation_view"
android:layout_height="match_parent"
android:layout_width="wrap_content"
android:layout_gravity="end"
app:headerLayout="#layout/nav_header"
app:menu="#menu/menu_navigation"
android:textAlignment="viewEnd" />
</android.support.v4.widget.DrawerLayout>
Code for my activity
public class MainActivity extends AppCompatActivity {
private DrawerLayout drawerLayout;
private Toolbar toolbar;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
initNavigationDrawer();
}
#TargetApi(Build.VERSION_CODES.M)
public void initNavigationDrawer() {
NavigationView navigationView = (NavigationView)findViewById(R.id.navigation_view);
navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(MenuItem menuItem) {
int id = menuItem.getItemId();
switch (id){
case R.id.home:
Toast.makeText(getApplicationContext(),"Home",Toast.LENGTH_SHORT).show();
drawerLayout.closeDrawers();
break;
case R.id.settings:
Toast.makeText(getApplicationContext(),"Settings",Toast.LENGTH_SHORT).show();
break;
case R.id.trash:
Toast.makeText(getApplicationContext(),"Trash",Toast.LENGTH_SHORT).show();
drawerLayout.closeDrawers();
break;
case R.id.logout:
finish();
}
return true;
}
});
drawerLayout = (DrawerLayout)findViewById(R.id.drawer);
ActionBarDrawerToggle actionBarDrawerToggle = new ActionBarDrawerToggle(this,drawerLayout,toolbar,R.string.drawer_open,R.string.drawer_close){
#Override
public void onDrawerClosed(View v){
super.onDrawerClosed(v);
}
#Override
public void onDrawerOpened(View v) {
super.onDrawerOpened(v);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item != null && item.getItemId() == android.R.id.home) {
if (drawerLayout.isDrawerOpen(Gravity.RIGHT)) {
drawerLayout.closeDrawer(Gravity.RIGHT);
}
else {
drawerLayout.openDrawer(Gravity.RIGHT);
}
}
return false;
}
};
drawerLayout.addDrawerListener(actionBarDrawerToggle);
actionBarDrawerToggle.syncState();
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (drawerLayout.isDrawerOpen(Gravity.RIGHT)) {
drawerLayout.closeDrawer(Gravity.RIGHT);
} else {
drawerLayout.openDrawer(Gravity.RIGHT);
}
}
});
}
}
There's really no (practical) way to make ActionBarDrawerToggle do that, as it is always set on the start/left-side navigation button. However, that class is basically just a DrawerListener that manages a specialized Drawable, and wires an ImageButton to the DrawerLayout. We can put together something similar for an end/right-side drawer with an ImageButton that we can place on that same side in a Toolbar (which is required for this example).
public class EndDrawerToggle implements DrawerLayout.DrawerListener {
private final DrawerLayout drawerLayout;
private final AppCompatImageButton toggleButton;
private final int openDrawerContentDescRes;
private final int closeDrawerContentDescRes;
private DrawerArrowDrawable arrowDrawable;
public EndDrawerToggle(DrawerLayout drawerLayout, Toolbar toolbar,
int openDrawerContentDescRes, int closeDrawerContentDescRes) {
this.drawerLayout = drawerLayout;
this.openDrawerContentDescRes = openDrawerContentDescRes;
this.closeDrawerContentDescRes = closeDrawerContentDescRes;
toggleButton = new AppCompatImageButton(toolbar.getContext(), null,
R.attr.toolbarNavigationButtonStyle);
toolbar.addView(toggleButton, new Toolbar.LayoutParams(GravityCompat.END));
toggleButton.setOnClickListener(v -> toggle());
loadDrawerArrowDrawable();
}
public void syncState() {
if (drawerLayout.isDrawerOpen(GravityCompat.END)) {
setPosition(1f);
} else {
setPosition(0f);
}
}
public void onConfigurationChanged(Configuration newConfig) {
loadDrawerArrowDrawable();
syncState();
}
#Override
public void onDrawerSlide(#NonNull View drawerView, float slideOffset) {
setPosition(Math.min(1f, Math.max(0f, slideOffset)));
}
#Override
public void onDrawerOpened(#NonNull View drawerView) {
setPosition(1f);
}
#Override
public void onDrawerClosed(#NonNull View drawerView) {
setPosition(0f);
}
#Override
public void onDrawerStateChanged(int newState) {}
private void loadDrawerArrowDrawable() {
arrowDrawable = new DrawerArrowDrawable(toggleButton.getContext());
arrowDrawable.setDirection(DrawerArrowDrawable.ARROW_DIRECTION_END);
toggleButton.setImageDrawable(arrowDrawable);
}
private void toggle() {
final int drawerLockMode = drawerLayout.getDrawerLockMode(GravityCompat.END);
if (drawerLayout.isDrawerVisible(GravityCompat.END)
&& (drawerLockMode != DrawerLayout.LOCK_MODE_LOCKED_OPEN)) {
drawerLayout.closeDrawer(GravityCompat.END);
} else if (drawerLockMode != DrawerLayout.LOCK_MODE_LOCKED_CLOSED) {
drawerLayout.openDrawer(GravityCompat.END);
}
}
private void setPosition(float position) {
if (position == 1f) {
arrowDrawable.setVerticalMirror(true);
setContentDescription(closeDrawerContentDescRes);
} else if (position == 0f) {
arrowDrawable.setVerticalMirror(false);
setContentDescription(openDrawerContentDescRes);
}
arrowDrawable.setProgress(position);
}
private void setContentDescription(int resId) {
toggleButton.setContentDescription(toggleButton.getContext().getText(resId));
}
}
The EndDrawerToggle class works exactly the same way as ActionBarDrawerToggle does when used with a Toolbar (except the constructor call doesn't need an Activity argument): first instantiate the toggle, then add it as a DrawerListener, and sync it in the Activity's onPostCreate() method. If you're already overriding the Activity's onConfigurationChanged() method, you'll want to call the toggle's corresponding method there, like you would for an ActionBarDrawerToggle.
private EndDrawerToggle drawerToggle;
public void initNavigationDrawer() {
...
drawerLayout = (DrawerLayout) findViewById(R.id.drawer);
drawerToggle = new EndDrawerToggle(drawerLayout,
toolbar,
R.string.drawer_open,
R.string.drawer_close);
drawerLayout.addDrawerListener(drawerToggle);
}
#Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
drawerToggle.syncState();
}
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
drawerToggle.onConfigurationChanged(newConfig);
}
If you have two drawers and need to use ActionBarDrawerToggle and EndDrawerToggle simultaneously, it is possible, but we'll need to handle intercepting and dispatching drawer motion events to the correct toggle.
If you prefer fewer classes, you could subclass ActionBarDrawerToggle and merge EndDrawerToggle's functionality into it, dispatching each DrawerListener method call either to the super class, or to the local end toggle code.
However, composition is arguably much cleaner here, and it will let us use EndDrawerToggle as is. This example is a DrawerListener that relays syncState() and onConfigurationChanged() calls to each toggle, but dispatches the listener method calls only to the appropriate one, depending on which drawer is moving.
public class DualDrawerToggle implements DrawerLayout.DrawerListener {
private final DrawerLayout drawerLayout;
private final Toolbar toolbar;
private final ActionBarDrawerToggle actionBarDrawerToggle;
private final EndDrawerToggle endDrawerToggle;
public DualDrawerToggle(Activity activity, DrawerLayout drawerLayout, Toolbar toolbar,
int startDrawerOpenContDescRes, int startDrawerCloseContDescRes,
int endDrawerOpenContDescRes, int endDrawerCloseContDescRes) {
this.drawerLayout = drawerLayout;
this.toolbar = toolbar;
this.actionBarDrawerToggle =
new ActionBarDrawerToggle(activity, drawerLayout, toolbar,
startDrawerOpenContDescRes, startDrawerCloseContDescRes);
this.endDrawerToggle =
new EndDrawerToggle(drawerLayout, toolbar,
endDrawerOpenContDescRes, endDrawerCloseContDescRes);
}
public void syncState() {
actionBarDrawerToggle.syncState();
endDrawerToggle.syncState();
}
public void onConfigurationChanged(Configuration newConfig) {
actionBarDrawerToggle.onConfigurationChanged(newConfig);
// Fixes bug in ABDT, which only reloads the up nav indicator, for some reason.
final DrawerArrowDrawable dad = new DrawerArrowDrawable(toolbar.getContext());
actionBarDrawerToggle.setDrawerArrowDrawable(dad);
endDrawerToggle.onConfigurationChanged(newConfig);
}
#Override
public void onDrawerSlide(#NonNull View drawerView, float slideOffset) {
if (isStartDrawerView(drawerView, drawerLayout.getLayoutDirection())) {
actionBarDrawerToggle.onDrawerSlide(drawerView, slideOffset);
} else {
endDrawerToggle.onDrawerSlide(drawerView, slideOffset);
}
}
#Override
public void onDrawerOpened(#NonNull View drawerView) {
if (isStartDrawerView(drawerView, drawerLayout.getLayoutDirection())) {
actionBarDrawerToggle.onDrawerOpened(drawerView);
} else {
endDrawerToggle.onDrawerOpened(drawerView);
}
}
#Override
public void onDrawerClosed(#NonNull View drawerView) {
if (isStartDrawerView(drawerView, drawerLayout.getLayoutDirection())) {
actionBarDrawerToggle.onDrawerClosed(drawerView);
} else {
endDrawerToggle.onDrawerClosed(drawerView);
}
}
#Override
public void onDrawerStateChanged(int newState) {}
#SuppressLint("RtlHardcoded")
static boolean isStartDrawerView(View drawerView, int layoutDirection) {
final int gravity = ((DrawerLayout.LayoutParams) drawerView.getLayoutParams()).gravity;
final int horizontalGravity = gravity & GravityCompat.RELATIVE_HORIZONTAL_GRAVITY_MASK;
if ((horizontalGravity & GravityCompat.RELATIVE_LAYOUT_DIRECTION) > 0) {
return horizontalGravity == GravityCompat.START;
} else {
if (layoutDirection == View.LAYOUT_DIRECTION_RTL) {
return horizontalGravity == Gravity.RIGHT;
} else {
return horizontalGravity == Gravity.LEFT;
}
}
}
}
Again, DualDrawerToggle works exactly the same way as ActionBarDrawerToggle does when used with a Toolbar, except for the extra content description resource IDs in the constructor.
Do note that the one DualDrawerToggle creates and manages both other toggles internally. You don't need to set up any other toggle instances in your Activity; just the DualDrawerToggle.
Notes:
If you read through the code, you'll see that EndDrawerToggle – and therefore also DualDrawerToggle – can be readily adapted to put a toggle on pretty much anything that can display a Drawable and register clicks; e.g., a FloatingActionButton, an options menu item, a TextView's compound drawable, etc. Simply replace the AppCompatImageButton with your target UI component, which can be passed in the constructor in place of the Toolbar, since the toggle won't be added to that anymore.
Additionally, this could be modified to work with the start/left-aligned drawer, too – completely replacing ActionBarDrawerToggle – so that its toggle could be placed on those various components, as well.
The AppCompatImageButton used here is a regular child of the Toolbar. If you're using a menu on the Toolbar, that menu will take precedence in the layout, and push the toggle inward. To keep it on the outside, you can modify the class as described above to set the toggle on an action menu item. I've an example of that in my answer here.
That menu item example might also be useful if your design requires you use the decor-supplied ActionBar in lieu of your own Toolbar. Though ActionBarDrawerToggle can work with a decor-supplied ActionBar, this example can not, as is.
In your android manifest add this line:
android:supportsRtl="true"
to your application, like so:
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
Then in your onCreate method, add this line:
getWindow().getDecorView().setLayoutDirection(View.LAYOUT_DIRECTION_RTL);
WARNING::: This only works for SdkVersion 17+, so if your application targets a lower minimum SDK, you will have to create a custom menu and override the OnCreateOptions method(Unless there's another way which I'm not aware of, which is definitely possible).
https://developer.android.com/guide/topics/manifest/application-element.html#supportsrtl