i am Using Material Design Navigation View..i created Menu item And linked activity(Activity2.java) with an item(Starred)...and in that activity i extend my Main activity in which there is navigation view so that i can slide the navigation view from that activity too.. but when i slide the navigation view from the second activity the item is not checked and if i press the back button and go to the Main activity the previously checked menu item is shown...how to update the check item in other activity.please help
MainActivity.java
public class MainActivity extends AppCompatActivity {
//Defining Variables
private Toolbar toolbar;
private NavigationView navigationView;
private DrawerLayout drawerLayout;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Initializing Toolbar and setting it as the actionbar
toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
//Initializing NavigationView
navigationView = (NavigationView) findViewById(R.id.navigation_view);
//Setting Navigation View Item Selected Listener to handle the item click of the navigation menu
navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
// This method will trigger on item Click of navigation menu
#Override
public boolean onNavigationItemSelected(MenuItem menuItem) {
//Checking if the item is in checked state or not, if not make it in checked state
if(menuItem.isChecked()) menuItem.setChecked(false);
else menuItem.setChecked(true);
//Closing drawer on item click
drawerLayout.closeDrawers();
//Check to see which item was being clicked and perform appropriate action
switch (menuItem.getItemId()){
//Replacing the main content with ContentFragment Which is our Inbox View;
case R.id.inbox:
Toast.makeText(getApplicationContext(),"Inbox Selected",Toast.LENGTH_SHORT).show();
ContentFragment fragment = new ContentFragment();
android.support.v4.app.FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.frame,fragment);
fragmentTransaction.commit();
return true;
// For rest of the options we just show a toast on click
case R.id.starred:
startActivity(new Intent(MainActivity.this,Activity2.class));
drawerLayout.closeDrawers();
Toast.makeText(getApplicationContext(),"Stared Selected",Toast.LENGTH_SHORT).show();
return true;
case R.id.sent_mail:
Toast.makeText(getApplicationContext(),"Send Selected",Toast.LENGTH_SHORT).show();
return true;
case R.id.drafts:
Toast.makeText(getApplicationContext(),"Drafts Selected",Toast.LENGTH_SHORT).show();
return true;
case R.id.allmail:
Toast.makeText(getApplicationContext(),"All Mail Selected",Toast.LENGTH_SHORT).show();
return true;
case R.id.trash:
Toast.makeText(getApplicationContext(),"Trash Selected",Toast.LENGTH_SHORT).show();
return true;
case R.id.spam:
Toast.makeText(getApplicationContext(),"Spam Selected",Toast.LENGTH_SHORT).show();
return true;
default:
Toast.makeText(getApplicationContext(),"Somethings Wrong",Toast.LENGTH_SHORT).show();
return true;
}
}
});
// Initializing Drawer Layout and ActionBarToggle
drawerLayout = (DrawerLayout) findViewById(R.id.drawer);
ActionBarDrawerToggle actionBarDrawerToggle = new ActionBarDrawerToggle(this,drawerLayout,toolbar,R.string.openDrawer, R.string.closeDrawer){
#Override
public void onDrawerClosed(View drawerView) {
// Code here will be triggered once the drawer closes as we dont want anything to happen so we leave this blank
super.onDrawerClosed(drawerView);
}
#Override
public void onDrawerOpened(View drawerView) {
// Code here will be triggered once the drawer open as we dont want anything to happen so we leave this blank
super.onDrawerOpened(drawerView);
}
};
//Setting the actionbarToggle to drawer layout
drawerLayout.setDrawerListener(actionBarDrawerToggle);
//calling sync state is necessay or else your hamburger icon wont show up
actionBarDrawerToggle.syncState();
}
}
Activity2.java
public class Activity2 extends MainActivity{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
FrameLayout frameLayout = (FrameLayout)findViewById(R.id.frame);
// inflate the custom activity layout
LayoutInflater layoutInflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View activityView = layoutInflater.inflate(R.layout.activity_2, null,false);
// add the custom layout of this activity to frame layout.
frameLayout.addView(activityView);
}
}
activity_main.xml
<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:id="#+id/drawer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context=".MainActivity">
<LinearLayout
android:layout_height="match_parent"
android:layout_width="match_parent"
android:orientation="vertical"
>
<include
android:id="#+id/toolbar"
layout="#layout/tool_bar"
/>
<FrameLayout
android:id="#+id/frame"
android:layout_width="match_parent"
android:layout_height="match_parent">
</FrameLayout>
</LinearLayout>
<android.support.design.widget.NavigationView
android:id="#+id/navigation_view"
android:layout_height="match_parent"
android:layout_width="wrap_content"
android:layout_gravity="start"
app:headerLayout="#layout/header"
app:menu="#menu/drawer"
/>
</android.support.v4.widget.DrawerLayout>
drawer.xml(menu_drawer)
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<group android:checkableBehavior="single">
<item
android:id="#+id/inbox"
android:checked="false"
android:icon="#drawable/ic_inbox_black"
android:title="#string/inbox_string" />
<item
android:id="#+id/starred"
android:checked="false"
android:icon="#drawable/ic_star_black"
android:title="#string/starred_string" />
<item
android:id="#+id/sent_mail"
android:checked="false"
android:icon="#drawable/ic_send_black"
android:title="#string/sent_mail_string" />
<item
android:id="#+id/drafts"
android:checked="false"
android:icon="#drawable/ic_drafts_black"
android:title="#string/draft_string" />
<item
android:id="#+id/allmail"
android:checked="false"
android:icon="#drawable/ic_email_black"
android:title="#string/all_mail_string" />
<item
android:id="#+id/trash"
android:checked="false"
android:icon="#drawable/ic_delete_black"
android:title="#string/trash_string" />
<item
android:id="#+id/spam"
android:checked="false"
android:icon="#drawable/ic_error_black"
android:title="#string/spam_string" />
</group>
</menu>
Add a protected int variable for storing id of checked menu item
From NavigationView's clickListener add checked menu item id to intent's extras; start yours second Activity with this intent
In second activity get menu item id from extras and set it to class variable from (see 1)
add onPrepareOptionsMenu in yours super-Activity
#Override
public boolean onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
//recreate navigationView's menu, uncheck all items and set new checked item
navigationView.getMenu().clear();
navigationView.inflateMenu(R.menu.drawer);
//setChecked(false) to all yours menu items in NavigationView
navigationView.getMenu().findItem(R.id.SOME_ID_0).setChecked(false);
navigationView.getMenu().findItem(R.id.SOME_ID_1).setChecked(false);
navigationView.getMenu().findItem(R.id.SOME_ID_2).setChecked(false);
...etc
navigationView.setCheckedItem(checkedDrawerItemId);
}
in yours NavigationView's clickListener do not forget to set clicked item's id to Activities class variable and call supportInvalidateOptionsMenu();
Try this in your Activity 2 :
#Override
public boolean onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
menu.findItem(R.id.starred).setChecked(true);
return true;
}
Related
I am new to android. I would like to implement a navigation drawer consisting of a list of items, which when clicked opens a new activity. Basically a navigation drawer across all the activities. When I select an item from the navigation drawer that particular activity opens.navigation drawer code is implemented by taking empty activity. I would like to implement navigation drawer functionality in all activities that activities are taken as empty activity in that activities already have some functionality along with this functionality the navigation drawer functionality also works. Please help me.
This is activity_header File
<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:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/drawer"
tools:context=".MainActivity">
<android.support.design.widget.NavigationView
app:headerLayout="#layout/header"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:background="#color/white"
app:menu="#menu/drawermenu"
android:layout_gravity="start"
android:id="#+id/navigationView"
>
</android.support.design.widget.NavigationView>
</android.support.v4.widget.DrawerLayout>
This is My Main Activity
<GridView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/gridview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:columnWidth="90dp"
android:numColumns="2"
android:verticalSpacing="10dp"
android:horizontalSpacing="10dp"
android:stretchMode="columnWidth"
android:gravity="center"
android:layout_marginTop="30dp"/>
This is Header Activity java code
public class HeaderActivity extends AppCompatActivity {
protected DrawerLayout myDrawerLayout;
protected ActionBarDrawerToggle toggle;
protected NavigationView navigationView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_header);
myDrawerLayout=(DrawerLayout)findViewById(R.id.drawer);
navigationView=(NavigationView) findViewById(R.id.navigationView);
navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem menuItem) {
Log.e("log_cat", "Error Response" + "Error");
switch (menuItem.getItemId())
{
case R.id.dashboard:
Toast.makeText(HeaderActivity.this,"Dashboard Clicked",Toast.LENGTH_LONG).show();
break;
case R.id.devotional:
Toast.makeText(HeaderActivity.this,"devotional Clicked",Toast.LENGTH_LONG).show();
break;
case R.id.inspiration:
Toast.makeText(HeaderActivity.this,"inspiration Clicked",Toast.LENGTH_LONG).show();
break;
case R.id.happy:
Toast.makeText(HeaderActivity.this,"happy Clicked",Toast.LENGTH_LONG).show();
break;
case R.id.sad:
Toast.makeText(HeaderActivity.this,"sad Clicked",Toast.LENGTH_LONG).show();
break;
case R.id.love:
Toast.makeText(HeaderActivity.this,"love Clicked",Toast.LENGTH_LONG).show();
break;
}
return false;
}
});
toggle = new ActionBarDrawerToggle(
this,
myDrawerLayout,
R.string.open,
R.string.close
) {
public void onDrawerClosed(View view) {
//Snackbar.make(view, R.string.drawer_close, Snackbar.LENGTH_SHORT).show();
}
public void onDrawerOpened(View drawerView) {
//Snackbar.make(drawerView, R.string.drawer_open, Snackbar.LENGTH_SHORT).show();
}
};
myDrawerLayout.addDrawerListener(toggle);
toggle.syncState();
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
// gridview.setAdapter(i);
}
#Override
public boolean onOptionsItemSelected (MenuItem item) {
if (toggle.onOptionsItemSelected (item)) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
This is My main activity java code
public class MainActivity extends HeaderActivity {
GridView grid;
public static String[] osNameList = {
"Devotional",
"Inspirational",
"Happy",
"Sad",
"Love"
} ;
public static int[] osImages = {
R.drawable.devotional,
R.drawable.inspirational,
R.drawable.happy,
R.drawable.sad,
R.drawable.love
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getLayoutInflater().inflate(R.layout.activity_main, myDrawerLayout);
GridView gridview = (GridView) findViewById(R.id.gridview);
gridview.setAdapter(new ImageAdapter(this, osNameList, osImages));
}
}
In this code setNavigationItemSelectedListener is not working in mainactivity but setOnClickListener on Grid is working. When we click on any navigation menu element it move to that activity.
If you want to include NavigationDrawer in all pages, you should use Fragment for feature pages.
If you want to see an example, you can see at here
Additionally I want you to recommend to use Android Jetpack Navigation Component with NavigationUI and DrawerLayout.
there is two way to implement the drawer in all activity you can use fragment or you can create a NavigationDrawer into base activity and implement this where you want. Same Navigation Drawer in different Activities
I have a double-drawer layout set up and am trying to handle selecting items inside the drawers. The way I have it set up though, I can see that neither onNavigationItemSelected nor onOptionsItemSelected is getting called when I tap something on the menu (I put a log statement right inside the functions). I'm also not totally clear which of those functions should be called.
EDIT: It looks like onOptionsItemSelected() is being called after all, but whichever item I click on, I always get the same id. So maybe it's only allowing me to click some other layer?
There are a lot of other questions similar to this, but none of the answers have been helpful to me. I'd appreciate any insight you may have.
Here is the relevant code inside my onCreate() function in MainActivity.java:
// Adding Toolbar to Main screen
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this, drawer, toolbar, R.string.drawer_open, R.string.drawer_close);
drawer.addDrawerListener(toggle);
toggle.syncState();
NavigationView leftNavigationView = (NavigationView) findViewById(R.id.notifications_view);
leftNavigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(MenuItem item) {
Log.i("left", "left"); // this is never called
// Handle left navigation view item clicks here
int id = item.getItemId();
switch(id) {
case R.id.emerg_con_menuitem:
break;
case R.id.ride_hist_menuitem:
Log.i("I'm hit", "I'm hit");
intent = new Intent(MainActivity.this, loc_report.class); // The action I want to happen when this menu item is tapped
MainActivity.this.startActivity(intent);
break;
case R.id.settings_menuitem:
break;
}
drawer.closeDrawer(GravityCompat.START);
return true;
}
});
NavigationView rightNavigationView = (NavigationView) findViewById(R.id.nav_view);
rightNavigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(MenuItem item) {
Log.i("right", "right"); // this is also never called
// Handle Right navigation view item clicks here.
int id = item.getItemId();
Log.i("I am firing", "I am firing");
switch(id) {
case R.id.emerg_con_menuitem:
break;
case R.id.ride_hist_menuitem:
Log.i("I'm hit navigation", "I'm hit navigation");
intent = new Intent(MainActivity.this, loc_report.class);
MainActivity.this.startActivity(intent);
break;
case R.id.settings_menuitem:
break;
}
drawer.closeDrawer(GravityCompat.END);
return true;
}
});
// Adding menu icon to Toolbar
ActionBar supportActionBar = getSupportActionBar();
if (supportActionBar != null) {
supportActionBar.setHomeAsUpIndicator(R.drawable.ic_notifications);
supportActionBar.setDisplayHomeAsUpEnabled(true);
supportActionBar.setDisplayShowTitleEnabled(false);
}
And the onOptionsItemSelected() that is being called, although not on the correct menu:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main_menu, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here.
Log.i("I'm hit options", "I'm hit options"); // also never called...what is going on??
int id = item.getItemId();
switch(id) {
case R.id.emerg_con_menuitem:
break;
case R.id.ride_hist_menuitem:
Log.i("I'm hit options", "I'm hit options");
Intent intent = new Intent(MainActivity.this, loc_report.class);
this.startActivity(intent);
break;
case R.id.settings_menuitem:
break;
case R.id.menu_navigation:
drawer.openDrawer(GravityCompat.END); /*Opens the Right Drawer*/
return true;
}
return super.onOptionsItemSelected(item);
}
Here is the main view activity_mail.xml:
<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_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:background="#drawable/main_background"
style="#style/Theme.AppCompat.DayNight">
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/main_content"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.AppBarLayout
android:id="#+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="#style/Protectors"
app:elevation="0dp">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:layout_scrollFlags="scroll|enterAlways"
app:popupTheme="#style/Protectors"
android:textAlignment="center">
</android.support.v7.widget.Toolbar>
</android.support.design.widget.AppBarLayout>
</android.support.design.widget.CoordinatorLayout>
<android.support.design.widget.NavigationView
android:id="#+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="end"
android:fitsSystemWindows="true"
app:headerLayout="#layout/navheader"
app:menu="#menu/menu_navigation" />
<android.support.design.widget.NavigationView
android:id="#+id/notifications_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="true"
app:headerLayout="#layout/navheader"
app:menu="#menu/notifications" />
...
The main menu with the clickable icon to open the drawer:
<?xml version="1.0" encoding="utf-8"?>
<menu 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"
tools:context=".MainActivity">
<group android:checkableBehavior="single">
<item // this is the item that's being called on a click
android:id="#+id/menu_navigation"
android:icon="#drawable/ic_menu"
android:title="#string/action_notifications"
android:orderInCategory="100"
app:showAsAction="always" />
</group>
</menu>
and the stuff inside the drawer (the right-hand one):
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="#+id/emerg_con_menuitem"
android:title="Emergency Contacts"
/>
<item
android:id="#+id/ride_hist_menuitem"
android:title="Ride History" />
<item
android:id="#+id/settings_menuitem"
android:title="Settings" />
</menu>
Ok, I think I figured this out. I'm still having trouble with the right-drawer links, but I got the left-drawer links to work. It was a layering problem--so I was clicking on the main_menu item (which contains the clickable icon that makes the drawer open) instead of the menu items underneath. To fix this, I added this line of code to fix the order:
NavigationView leftNavigationView = (NavigationView) findViewById(R.id.nav_view);
leftNavigationView.bringToFront(); // <- added this line
And then the OnNavigationItemSelectedListener actually fires as expected.
I know how to create android hamburger menu, many tutorials are available.
I want to create Hamburger menu in each class, to call one method in common class which method have hamburger menu code. Also my hamburger menu inside listview with options.
How to create like this hamburger menu. I want to reduce my code and provide reusable code to others. Please help me.
You need to take an Activity and in that Activity's layout file put the following code:
<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:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:elevation="4dp"
android:layout_height="fill_parent"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<include
android:id="#+id/tool_bar"
layout="#layout/toolbar"
android:layout_height="wrap_content"
android:layout_width="match_parent"
/>
<FrameLayout
android:id="#+id/content_frame"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/bg_new">
<put your layout here................>
</FrameLayout>
</LinearLayout>
<android.support.design.widget.NavigationView
android:id="#+id/navigation"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="true"
android:background="#drawable/bg_all"
app:itemIconTint="#android:color/white"
app:itemTextColor="#android:color/white"
app:theme="#style/list_item_appearance"
app:menu="#menu/drawer_menu" >
</android.support.design.widget.NavigationView>
</android.support.v4.widget.DrawerLayout>
After that in your Activity file:
drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
navigationView=(NavigationView)findViewById(R.id.navigation);
if (drawerLayout != null) {
drawerLayout.setDrawerShadow(R.drawable.list_back, GravityCompat.START);
mDrawerToggle = new ActionBarDrawerToggle(HomeActivity.this, drawerLayout,
toolbar, R.string.drawer_open, R.string.drawer_close) {
public void onDrawerClosed(View view) {
super.onDrawerClosed(view);
invalidateOptionsMenu();
}
public void onDrawerOpened(View drawerView) {
getSupportActionBar().setTitle(mDrawerTitle);
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
super.onDrawerOpened(drawerView);
invalidateOptionsMenu();
}
};
drawerLayout.setDrawerListener(mDrawerToggle);
}
#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);
// Pass any configuration change to the drawer toggles
mDrawerToggle.onConfigurationChanged(newConfig);
}
And then take some fragments for adding the same navigation menu in every layout and call them like:
navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
// This method will trigger on item Click of navigation menu
#Override
public boolean onNavigationItemSelected(MenuItem menuItem) {
//Checking if the item is in checked state or not, if not make it in checked state
if (menuItem.isChecked()) menuItem.setChecked(false);
else menuItem.setChecked(true);
//Closing drawer on item click
drawerLayout.closeDrawers();
//Check to see which item was being clicked and perform appropriate action
switch (menuItem.getItemId()) {
//Replacing the main content with ContentFragment Which is our Inbox View;
case R.id.drawer_home:
txt_title.setText("Home");
Intent intent=new Intent(HomeActivity.this, HomeActivity.class);
startActivity(intent);
overridePendingTransition(0, 0);
finish();
return true;
// For rest of the options we just show a toast on click
case R.id.drawer_artist:
txt_title.setText("Artists");
android.support.v4.app.FragmentManager fragmentManager=getSupportFragmentManager();
android.support.v4.app.FragmentTransaction fragmentTransaction=fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.content_frame, new ArtistsFragment());
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
return true;
}
});
I have a navigation drawer like this image. I want to add a section separator (like the line separating Neptune). It seems simple but I can't find anything on the web that was useful for my case.
Here is my MainActivity:
public class MainActivity extends Activity {
private DrawerLayout mDrawerLayout;
private ListView mDrawerList;
private ActionBarDrawerToggle mDrawerToggle;
private CharSequence mDrawerTitle;
private CharSequence mTitle;
private String[] mPlanetTitles;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTitle = mDrawerTitle = getTitle();
mPlanetTitles = getResources().getStringArray(R.array.planets_array);
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
mDrawerList = (ListView) findViewById(R.id.left_drawer);
// set a custom shadow that overlays the main content when the drawer opens
mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START);
// set up the drawer's list view with items and click listener
mDrawerList.setAdapter(new ArrayAdapter<String>(this,
R.layout.drawer_list_item, mPlanetTitles));
mDrawerList.setOnItemClickListener(new DrawerItemClickListener());
// enable ActionBar app icon to behave as action to toggle nav drawer
getActionBar().setDisplayHomeAsUpEnabled(true);
getActionBar().setHomeButtonEnabled(true);
// ActionBarDrawerToggle ties together the the proper interactions
// between the sliding 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.drawer_open, /* "open drawer" description for accessibility */
R.string.drawer_close /* "close drawer" description for accessibility */
) {
public void onDrawerClosed(View view) {
getActionBar().setTitle(mTitle);
invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()
}
public void onDrawerOpened(View drawerView) {
getActionBar().setTitle(mDrawerTitle);
invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()
}
};
mDrawerLayout.setDrawerListener(mDrawerToggle);
if (savedInstanceState == null) {
selectItem(0);
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main, menu);
return super.onCreateOptionsMenu(menu);
}
/* Called whenever we call invalidateOptionsMenu() */
#Override
public boolean onPrepareOptionsMenu(Menu menu) {
// If the nav drawer is open, hide action items related to the content view
boolean drawerOpen = mDrawerLayout.isDrawerOpen(mDrawerList);
menu.findItem(R.id.action_websearch).setVisible(!drawerOpen);
return super.onPrepareOptionsMenu(menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// The action bar home/up action should open or close the drawer.
// ActionBarDrawerToggle will take care of this.
if (mDrawerToggle.onOptionsItemSelected(item)) {
return true;
}
// Handle action buttons
switch(item.getItemId()) {
case R.id.action_websearch:
// create intent to perform web search for this planet
Intent intent = new Intent(Intent.ACTION_WEB_SEARCH);
intent.putExtra(SearchManager.QUERY, getActionBar().getTitle());
// catch event that there's no activity to handle intent
if (intent.resolveActivity(getPackageManager()) != null) {
startActivity(intent);
} else {
Toast.makeText(this, R.string.app_not_available, Toast.LENGTH_LONG).show();
}
return true;
default:
return super.onOptionsItemSelected(item);
}
}
/* The click listner for ListView in the navigation drawer */
private class DrawerItemClickListener implements ListView.OnItemClickListener {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
selectItem(position);
}
}
private void selectItem(int position) {
// update the main content by replacing fragments
Fragment fragment = new PlanetFragment();
Bundle args = new Bundle();
args.putInt(PlanetFragment.ARG_PLANET_NUMBER, position);
fragment.setArguments(args);
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction().replace(R.id.content_frame, fragment).commit();
// update selected item and title, then close the drawer
mDrawerList.setItemChecked(position, true);
setTitle(mPlanetTitles[position]);
mDrawerLayout.closeDrawer(mDrawerList);
}
#Override
public void setTitle(CharSequence title) {
mTitle = title;
getActionBar().setTitle(mTitle);
}
/**
* When using the ActionBarDrawerToggle, you must call it during
* onPostCreate() and onConfigurationChanged()...
*/
#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);
// Pass any configuration change to the drawer toggls
mDrawerToggle.onConfigurationChanged(newConfig);
}
/**
* Fragment that appears in the "content_frame", shows a planet
*/
public static class PlanetFragment extends Fragment {
public static final String ARG_PLANET_NUMBER = "planet_number";
public PlanetFragment() {
// Empty constructor required for fragment subclasses
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_planet, container, false);
int i = getArguments().getInt(ARG_PLANET_NUMBER);
String planet = getResources().getStringArray(R.array.planets_array)[i];
int imageId = getResources().getIdentifier(planet.toLowerCase(Locale.getDefault()),
"drawable", getActivity().getPackageName());
((ImageView) rootView.findViewById(R.id.image)).setImageResource(imageId);
getActivity().setTitle(planet);
return rootView;
}
}
}
activity_main.xml:
<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
android:id="#+id/content_frame"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<ListView
android:id="#+id/left_drawer"
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:choiceMode="singleChoice"
android:divider="#android:color/transparent"
android:dividerHeight="0dp"
android:background="#111"/>
</android.support.v4.widget.DrawerLayout>
drawer_list_item.xml:
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#android:id/text1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceListItemSmall"
android:gravity="center_vertical"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:textColor="#fff"
android:background="?android:attr/activatedBackgroundIndicator"
android:minHeight="?android:attr/listPreferredItemHeightSmall"/>
I want this to be simple but I can't find anything good on the web. Is there a way that I can isolate Neptune and create a section for it? Does anyone have any suggestions? Thanks.
Make sure you define each group with a unique ID, separator won't appear without the ID.
For example, this is my drawer_menu.xml:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<group
android:id="#+id/menu_top"
android:checkableBehavior="single">
<item
android:checked="true"
android:id="#+id/drawer_item_timeline"
android:icon="#drawable/ic_timer_grey600_24dp"
android:title="#string/drawer_timeline"/>
<item
android:id="#+id/drawer_item_reports"
android:icon="#drawable/ic_timetable_grey600_24dp"
android:title="#string/drawer_reports"/>
</group>
<group
android:id="#+id/menu_bottom"
android:checkableBehavior="none">
<item
android:id="#+id/drawer_item_settings"
android:icon="#drawable/ic_settings_black_24dp"
android:title="#string/drawer_settings" >
</item>
</group>
</menu>
Gabriel adds below in the comments that if the group doesn't have an id, the separator will not appear.
To separate menu items by a divider line, only group items with a unique id like following example:
activity_main_drawer.xml:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:showIn="navigation_view">
<item
android:id="#+id/nav_apps_and_games"
android:icon="#drawable/ic_apps_black_24dp"
android:title="#string/my_apps_and_games" />
<item
android:id="#+id/nav_bookmarked_apps"
android:icon="#drawable/ic_add_bookmark_black_24dp"
android:title="#string/bookmarked_apps" />
<item
android:id="#+id/nav_manage_downloads"
android:icon="#drawable/ic_downloading_file_black_24dp"
android:title="#string/manage_downloads" />
<!-- SET A UNIQUE ID TO THE BELOW GROUP -->
<group android:id="#+id/group1">
<item
android:id="#+id/nav_settings"
android:icon="#drawable/ic_settings_black_24dp"
android:title="#string/settings" />
<item
android:id="#+id/nav_sign_up"
android:icon="#drawable/ic_card_membership_black_24dp"
android:title="#string/sign_up_login" />
</group>
</menu>
Visual Result:
My hacky method is similar to Mostrapotski's.
In my Layout for my custom adapter, I'm adding a horizontal separator at the beginning of each item and setting it's visibility to gone.
For the elements that mark the beginning of a new group, I set their visibility to visible so that the separator shows up on top of it.
You have two choices
Your items can be separated (a list at the top, and classic views at the bottom).
Then instead of the listview in your main layout (android:id="#+id/left_drawer") you can have a rather complex LinearLayout including those 3 items (list, separator, and bottom views)
Your items must be exactly as in your example, then you need the separator in the list, you can use some logic in your adapter to draw a view on top of the list item where you need the separator. (meaning your list item won't be a single textview anymore, but a LinearLayout with a gone separator (and visible sometimes, according to your adapter's logic).
To help you with some sample code, can you please post all the items you need in your menu ? We need to know exactly what will be static and what will be scrollable.
Edit: If you want that working with the exemple, get rid of the line
mDrawerList.setAdapter(new ArrayAdapter<String>(this, ...)
You need to supply a home made adapter like this:
https://github.com/codepath/android_guides/wiki/Using-an-ArrayAdapter-with-ListView
As i said in 2, in your adapter, you will have logic, and thus you can say in the getView() method
if(myPlanet.isNeptune())
holder.mSepatator.setVisibility(View.VISIBLE);
else
holder.mSepatator.setVisibility(View.GONE);
Add group in Menu file to add divider
enter image description here
<group android:checkableBehavior="none">
<item android:title="______________________________________________________________"
android:iconTint="#color/colorWhite"
android:enabled="false">
</item>
</group>
I use the ActionBarDrawerToggle to open and close the DrawerLayout.
But the listView inside my drawerlayout is not shown.
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
mDrawerList = (ListView) mDrawerLayout.findViewById(R.id.left_drawer);
mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START);
mDrawerList.setBackgroundColor(getResources().getColor(R.color.abs__background_holo_light));
mDrawerList.setAdapter(menuAdapter);
mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, R.drawable.ic_navigation_drawer,
R.string.open, R.string.close) {
/** Called when a drawer has settled in a completely closed state. */
public void onDrawerClosed(View view) {
invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()
}
/** Called when a drawer has settled in a completely open state. */
public void onDrawerOpened(View drawerView) {
invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()
}
};
// Set the drawer toggle as the DrawerListener
mDrawerLayout.setDrawerListener(mDrawerToggle);
It shows only a black drawer without entries.
The drawerList should be white as set in "setBackgroundColor" and the drawerList should display the entries form the adapter.
When I open the drawer with openDrawer(mDrawerList) it works, but not on swipe.
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;
//}
switch (item.getItemId()) {
case android.R.id.home:
if (mDrawerLayout.isDrawerOpen(mDrawerList)) {
mDrawerLayout.closeDrawer(mDrawerList);
} else {
mDrawerLayout.openDrawer(mDrawerList);
}
break;
Here is the main.xml layout with the DrawerLayout:
<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" >
<!-- The main content -->
<fragment
android:id="#+id/activeRemindersList"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
class="com.colapps.reminder.fragments.ActiveRemindersFragment" />
<!-- The navigation drawer -->
<ListView
android:id="#+id/left_drawer"
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="#111"
android:choiceMode="singleChoice"
android:divider="#android:color/transparent"
android:dividerHeight="0dp" />
Can anybody help?
UPDATE:
The problem seems is the Fragment.
If I add instead of the Fragment a simple FrameLayout all is working fine:
<!-- The main content -->
<FrameLayout
android:layout_width="match_parent"
android:layout_height="0dp" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Test" />
</FrameLayout>
<!-- The navigation drawer -->
<ListView
android:id="#+id/left_drawer"
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="#111"
android:choiceMode="singleChoice"
android:divider="#android:color/transparent"
android:dividerHeight="0dp" />
Problem solved!
The problem was that in the Fragment Layout was also a "DrawerLayout".
I have changed a lot and forgotten to remove it from the Fragment Layout.
Thanks to all who have tried to help me.
I think you are missing a <FrameLayout> in your XML (notice the one I have wrapping the fragment content).
It should look something like this:
<android.support.v4.widget.DrawerLayout
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="fill_parent" >
<FrameLayout
android:id="#+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<fragment
android:id="#+id/app_info_fragment_phone"
... />
</FrameLayout>
<ListView
android:id="#+id/drawer"
... />
</android.support.v4.widget.DrawerLayout>
I am quite sure this has either something to do with:
the ListView not having a weight property
the ListView adapter being empty
the ListView being hidden by the Fragment
Try changing the layot file so that the ListView has a weight property as well and change the height property of the Fragment. Furthermore, put both of them in a LinearLayout.
Also make sure you have thesemethods overridden in your Activity:
/**
* When using the ActionBarDrawerToggle, you must call it during
* onPostCreate() and onConfigurationChanged()...
*/
#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);
// Pass any configuration change to the drawer toggls
mDrawerToggle.onConfigurationChanged(newConfig);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// The action bar home/up action should open or close the drawer.
// ActionBarDrawerToggle will take care of this.
if (mDrawerToggle.onOptionsItemSelected(item)) {
return true;
} else
return false;
}
UPDATE:
Use the onDrawerItemSelected(int pos) method to add / replace Fragments.
#Override
public void onDrawerItemSelected(int pos) {
// update the main content by replacing fragments
Fragment fragment = null;
switch (pos) {
case 0:
fragment = new FragOne();
break;
case 1:
fragment = new FragTwo();
break;
case 2:
fragment = new FragThree();
break;
}
// R.id.content_frame is the id of the FrameLayout
getFragmentManager().beginTransaction().replace(R.id.content_frame, fragment).commit()
// update selected item then close the drawer
mDrawerList.setItemChecked(pos, true);
mDrawerLayout.closeDrawer(mDrawerList);
}
Here you have a detailed tutorial / example of how to implement the NavigationDrawer. When I first used the NavigationDrawer I went by this tutorial and was able to successfully implement it.
http://developer.android.com/training/implementing-navigation/nav-drawer.html