I am having some difficulties when trying to use a navigation drawer and fragment together.
main.xml
<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"
tools:context=".GoogleMap" >
<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 view -->
<FrameLayout
android:id="#+id/content_frame"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<!-- The navigation drawer -->
<ListView android:id="#+id/left_drawer"
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:choiceMode="singleChoice"
android:divider="#666"
android:dividerHeight="1dp"
android:background="#333"
android:paddingLeft="15sp"
android:paddingRight="15sp"
/>
<fragment
android:id="#+id/map"
android:name="com.google.android.gms.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</android.support.v4.widget.DrawerLayout>
</LinearLayout>
So the problem that I am facing is the navigation drawer only shows the content for a short moment when I rotate the device either from portrait to landscape or the other way around. The navigation drawer will remains empty if I do not tilt the device.
The fragment is basically a so-called div to show a map. Then when I click on the navigation drawer, it will be on the top of the map fragment. I wonder which part of my layout went wrong and causing this problem.
Thanks in advance.
Edited Portion
<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">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<fragment
android:id="#+id/map"
android:name="com.google.android.gms.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
<!-- The navigation drawer -->
<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>
GoogleMap.java
public class GoogleMap extends FragmentActivity {
// Google Map
private com.google.android.gms.maps.GoogleMap map;
private String[] drawerListViewItems;
private DrawerLayout drawerLayout;
private ListView drawerListView;
private ActionBarDrawerToggle actionBarDrawerToggle;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
try {
// Loading map
initilizeMap();
} catch (Exception e) {
e.printStackTrace();
}
// get list items from strings.xml
drawerListViewItems = getResources().getStringArray(R.array.items);
// get ListView defined in activity_main.xml
drawerListView = (ListView) findViewById(R.id.left_drawer);
// Set the adapter for the list view
drawerListView.setAdapter(new ArrayAdapter<String>(this,
R.layout.drawer_listview_item, drawerListViewItems));
// App Icon
drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
actionBarDrawerToggle = new ActionBarDrawerToggle(
this, /* host Activity */
drawerLayout, /* 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 */
);
// Set actionBarDrawerToggle as the DrawerListener
drawerLayout.setDrawerListener(actionBarDrawerToggle);
getActionBar().setDisplayHomeAsUpEnabled(true);
// just styling option add shadow the right edge of the drawer
drawerLayout.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START);
drawerListView.setOnItemClickListener(new DrawerItemClickListener());
}
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
actionBarDrawerToggle.onConfigurationChanged(newConfig);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// call ActionBarDrawerToggle.onOptionsItemSelected(), if it returns true
// then it has handled the app icon touch event
if (actionBarDrawerToggle.onOptionsItemSelected(item)) {
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
// Sync the toggle state after onRestoreInstanceState has occurred.
actionBarDrawerToggle.syncState();
}
private class DrawerItemClickListener implements ListView.OnItemClickListener {
#Override
public void onItemClick(AdapterView parent, View view, int position, long id) {
Toast.makeText(GoogleMap.this, ((TextView)view).getText(), Toast.LENGTH_LONG).show();
//Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse("http://maps.google.com/maps?saddr=1.3564 ,103.8311&daddr=1.3426 ,103.9254"));
//startActivity(i);
drawerLayout.closeDrawer(drawerListView);
}
}
/**
* function to load map. If map is not created it will create it for you
* */
private void initilizeMap() {
if (map == null) {
map = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(
R.id.map)).getMap();
map.moveCamera( CameraUpdateFactory.newLatLngZoom(new LatLng(1.32814,103.80679) , 11.0f) );
// check if map is created successfully or not
if (map == null) {
Toast.makeText(getApplicationContext(),
"Sorry! unable to create maps", Toast.LENGTH_SHORT)
.show();
}
}
}
#Override
protected void onResume() {
super.onResume();
initilizeMap();
}
}
There is one Problem with your Layout(i don't know others!) which is using DrawerLayout inside a LinearLayout , DrawerLayout should be root view in your Layout file.
You have 3 views directly inside your drawerlayout. The drawer must only have 2 views immediately inside it. I'd recommend wrapping the fragment and framelayout inside a linearlayout or relativelayout. Either that or nest the fragment inside the framelayout
You should code like this:
<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" />
<!-- The navigation drawer -->
<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>
Edit:
And in your Activity set the fragment in this FrameContent.
In your onCreate() add this line
if (savedInstanceState == null) {
initilizeMap();
}
Related
I have gone through similar questions and their solutions here, but I can't get past my issue after spending few hours on it. I looked at many solutions, tried them, but still can't get to see the navigation drawer on my screen. I will really appreciate if someone could tell me what am I missing here.
Thanks in advance.
Here's my xml :
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout
android:id="#+id/drawer_layout"
android:layout_width="400dp"
android:layout_height="400dp"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/content_frame" >
</FrameLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".Menu">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:textColor="#fff"
android:text="test"
android:id="#+id/text" />
</RelativeLayout>
<ListView
android:layout_width="200dp"
android:layout_height="match_parent"
android:layout_gravity="end"
android:choiceMode="singleChoice"
android:background="#fff"
android:id="#+id/left_drawer" >
</ListView>
</android.support.v4.widget.DrawerLayout>
Here's my Menu.java :
>public class Menu extends AppCompatActivity {
>
> public DrawerLayout dlayout;
> public ListView flist;
> public String[] menu;
> //public ArrayAdapter<String> mAdapter;
>
> #Override
> protected void onCreate(Bundle savedInstanceState) {
> super.onCreate(savedInstanceState);
> setContentView(R.layout.activity_menu);
>
> menu = getResources().getStringArray(R.array.nav_drawer_items);
> dlayout = (DrawerLayout) findViewById(R.id.drawer_layout);
> flist = (ListView) findViewById(R.id.left_drawer);
>
> flist.setAdapter(new ArrayAdapter<String>(this, R.layout.activity_menu, >R.id.text, menu));
> }
>}
I don't see any output.Screen output
seems that there should be problem in your layout file.
Remember that DrawerLayout allows maximum 2 child views. Have
a look at this Google Doc.
It should be like:
<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 view -->
<FrameLayout
android:id="#+id/content_frame"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<!-- The navigation drawer -->
<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>
<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">
<include
android:id="#+id/header"
layout="#layout/menu"/>
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:id="#+id/frame"
android:textSize="24sp"
android:gravity="center"
android:layout_marginTop="50dp"/>
<ListView
android:id="#+id/list_item"
android:layout_width="200dp"
android:layout_height="match_parent"
android:dividerHeight="1dp"
android:layout_gravity="left|start"
android:background="#ffeeeeee"/></android.support.v4.widget.DrawerLayout>
MainActivity.java
public class MainActivity extends Activity {
String[] names = {"android","java","spring","html"};
ListView list;
FrameLayout frame;
ActionBarDrawerToggle action;
DrawerLayout drawer;
Button but;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
frame = (FrameLayout) findViewById(R.id.frame);
list = (ListView) findViewById(R.id.list_item);
but = (Button) findViewById(R.id.menu);
ArrayAdapter adapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1, names);
list.setAdapter(adapter);
action = new ActionBarDrawerToggle(this, drawer, R.string.drawer_open, R.string.drawer_close) {
/* Called when drawer is closed */
public void onDrawerClosed(View view) {
//Put your code here
}
/* Called when a drawer is opened */
public void onDrawerOpened(View drawerView) {
//Put your code here
}
};
drawer.setDrawerListener(action);
but.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (drawer != null) {
if (drawer.isDrawerOpen(list)) {
drawer.closeDrawer(list);
} else {
drawer.openDrawer(list);
process();
}
}
}
});
}
private void process() {
list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
FragmentTransaction ft=getFragmentManager().beginTransaction();
switch (names[position])
{
case "android":
{
yourClass obj=new yourClass();
//ft.replace(R.id.frame,obj);
break
}
case "java":
{
yourClass obj=new yourClass();
//ft.replace(R.id.frame,obj);
break;
}
case "spring":
{
yourClass obj=new yourClass();
//ft.replace(R.id.frame,obj);
break;
}
case "html":
{
yourClass obj=new yourClass();
//ft.replace(R.id.frame,obj);
break;
}
default:
{
Toast.makeText(MainActivity.this,"you have to click another one",Toast.LENGTH_LONG).show();
}
}
ft.commitAllowingStateLoss();
list.setItemChecked(position, true);
drawer.closeDrawer(list);
}
});
}
}
menu.xml
<LinearLayout 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"
tools:context=".MainActivity"
android:layout_height="wrap_content">
<Button
android:id="#+id/menu"
android:title="menu"
android:icon="#drawable/menu"
android:background="#drawable/menu"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:backgroundTint="#0a0a0a" /></LinearLayout>
You need to toggle the open/close of the drawer.
To do so, you can do the following :
1 - Implement the toggleDrawer method
public void toggleDrawer(boolean shouldBeVisible){
if(shouldBeVisible){
dlayout.openDrawer(dlayout);
} else {
dlayout.closeDrawers();
}
}
2 - Call it on onCreate (note : this is just for testing)
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
toggleDrawer(View.VISIBLE);
}
3 - Like Daryl said, implement a button so you can actively toggle (open and close the drawer to your liking)
myButton = (Button) findViewById(R.id.myButton);
myButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v){
if(dlayout.getVisiblity() == View.VISIBLE) {
// drawer is visible -> close
toggleDrawer(false);
} else {
// drawer is gone/invisible -> open
toggleDrawer(true);
}
}
})
4 - (Make sure your DrawerLayout contains only 2 child views)
To add a navigation drawer, declare your user interface with a
DrawerLayout object as the root view of your layout. Inside the
DrawerLayout, add one view that contains the main content for the
screen (your primary layout when the drawer is hidden) and another
view that contains the contents of the navigation drawer.
Note : Forgot to add this but is indeed an invaluable reference (thanks to #Meet, upvoted)
I added navigation drawer to my application. Everything works fine, but now I am trying to add a simple textView to menu, and am not succeeding. The problem is the fact that text is hidden underneath actionBar itself. Even 50dp margin from top isn't enough.
Do you have any tips on how to fix this issue?
My main activity:
<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 view -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/container"
android:fitsSystemWindows="true"
android:clipToPadding="false"/>
<!-- The navigation drawer -->
<FrameLayout
android:id="#+id/left_drawer"
android:layout_width="200dp"
android:layout_height="match_parent"
android:layout_gravity="left"
android:choiceMode="singleChoice"
android:divider="#android:color/transparent"
android:dividerHeight="0dp"
android:background="#color/dark_brown">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="New Text"
android:textSize="40dp"
android:textColor="#ffffff"
android:id="#+id/textView"
android:layout_marginTop="50dp"
android:layout_marginLeft="20dp"
android:gravity="center_vertical"/>
</FrameLayout>
</android.support.v4.widget.DrawerLayout>
And my main activities class:
public class MainActivity extends ActionBarActivity {
private DrawerLayout mDrawerLayout;
private ActionBarDrawerToggle mDrawerToggle;
private DatabaseHandler database;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Handle application side menu
sideMenu();
// Set tint for android bar (only for KitKat version)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
SystemBarTintManager tintManager = new SystemBarTintManager(this);
tintManager.setStatusBarTintEnabled(true);
tintManager.setStatusBarTintResource(R.color.action_bar_bg);
}
// Create system objects
database = new DatabaseHandler(this);
final Statistics statistic = new Statistics(database);
// Create main fragment and point app to it
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.replace(R.id.container, new MainFragment(database, statistic))
.commit();
}
}
private void sideMenu() {
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);
getSupportActionBar().setTitle(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(R.string.drawer_open);
}
};
// Set the drawer toggle as the DrawerListener
mDrawerLayout.setDrawerListener(mDrawerToggle);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().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
return mDrawerToggle.onOptionsItemSelected(item) || super.onOptionsItemSelected(item);
}
#Override
protected void onDestroy() {
super.onDestroy();
database.closeDatabase();
}
}
You want to assign fitsSystemWindows and clipToPadding to the Navigation Drawer fragment (most probably the ListView)
Something like this -
<ListView 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:choiceMode="singleChoice"
android:divider="#android:color/transparent"
android:dividerHeight="0dp"
android:background="#cccc"
android:fitsSystemWindows="true"
android:clipToPadding="false"
/>
But in your case, you are using the FrameLayout on the activity_main itself to populate the Drawer contents. So you have to apply these two properties to the FrameLayout
<FrameLayout
android:id="#+id/left_drawer"
android:layout_width="200dp"
android:layout_height="match_parent"
android:layout_gravity="left"
android:choiceMode="singleChoice"
android:divider="#android:color/transparent"
android:dividerHeight="0dp"
android:fitsSystemWindows="true"
android:clipToPadding="false"
android:background="#color/dark_brown">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="New Text"
android:textSize="40dp"
android:textColor="#ffffff"
android:id="#+id/textView"
android:gravity="center_vertical"/>
</FrameLayout>
Also, notice, you don't need following to your TextView anymore.
android:layout_marginTop="50dp"
android:layout_marginLeft="20dp"
I am trying to create a NavigationDrawer as well as having a ViewPager with sliding tabs in an activity using ActionBarSherlock. I have the tabs and I have created layouts for the view pager and the drawer layout. I know that what I have is that the viewpager layout and drawerlayout are in seperate files and they should probably be in the same file to find the view. Although I do not know how to do this with the code that I have.
I have done a lot of research as to how to do this and the standard pattern is to not do this, although as many people have pointed out, Google Play Music does this. I want my application to look like that and I know that there is a workaround as people have suggested. I am just unsure on how the workaround works with ActionBarSherlock and the code that I currently have implemented. Please can anyone help me with this. Thank you in advance.
Here is my activity code:
public class SlidingTabsActivity extends SherlockFragmentActivity
{
private ViewPager viewPager;
private TabsAdapter tabsAdapter;
private ActionBar actionBarTabs;
/* Navigation drawer */
private DrawerLayout drawerLayout;
private ListView drawerListView;
private ActionBarDrawerToggle drawerToggle;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
viewPager = new ViewPager(this);
viewPager.setId(R.id.pager);
setContentView(viewPager);
/* Navigation Drawer */
drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
drawerListView = (ListView) findViewById(R.id.left_drawer);
System.out.println("Drawer Layout test:" + drawerLayout.getId());
drawerLayout.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START);
drawerListView.setAdapter(new ArrayAdapter<String>(this, R.layout.navigation_drawer_list_item, R.array.navigation_drawer_list));
drawerListView.setOnItemClickListener(new OnItemClickListener()
{
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
{
// TODO Auto-generated method stub
}
});
actionBarTabs = getSupportActionBar();
actionBarTabs.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
actionBarTabs.setDisplayHomeAsUpEnabled(true);
actionBarTabs.setHomeButtonEnabled(true);
drawerToggle = new ActionBarDrawerToggle(this, drawerLayout, R.drawable.ic_drawer, R.string.drawer_open, R.string.drawer_close)
{
public void onDrawerClosed(View view)
{
invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()
}
public void onDrawerOpened(View drawerView)
{
invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()
}
};
drawerLayout.setDrawerListener(drawerToggle);
tabsAdapter = new TabsAdapter(this, viewPager); // Declares the tabs adapter class with the view pager view
/* Adds fragments to the tabs adapter */
tabsAdapter.addTab(actionBarTabs.newTab().setText("PV"), Fragment_1.class, null);
tabsAdapter.addTab(actionBarTabs.newTab().setText("CONFIG"), Fragment_2.class, null);
tabsAdapter.addTab(actionBarTabs.newTab().setText("DIAG"), Fragment_3.class, null);
}
Here is my DrawerLayout layout xml code:
<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>
And here is my ViewPager layout xml code:
<RelativeLayout 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"
tools:context=".SlidingTabsActivity" >
<android.support.v4.view.ViewPager
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/pager" />
</RelativeLayout>
Firstly, your Activity has both Navigation Drawer and ViewPager, but I saw you put the layout descriptions in different xml files. But, you must put only one xml file for your Activity.
Considering this, the key point now is: "how to declare DrawerLayout and ViewPager in the same xml?". If you put in wrong order it won't work (I had this same problem, that's why I'm alerting you). So, the answer is to declare the DrawerLayout as root and inside it, the ViewPager, and later, after closing the ViewPager "tag", you declare the ListView of DrawerLayout.
An example:
<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">
<android.support.v4.view.ViewPager
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent">
</android.support.v4.view.ViewPager>
<ListView android:id="#+id/drawer_list"
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>
I hope the answer helps you.
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
I try to implement the latest drawer layout from support library 13.
With the following code, the drawer is always showing below the gridview. Even I try to call bringToFront() still not working. Can help to find what's wrong? Thanks.
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>
member_home_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal" >
<GridView
android:id="#+id/member_home_thumbnail_grid"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:columnWidth="90dp"
android:gravity="center"
android:horizontalSpacing="0dp"
android:numColumns="auto_fit"
android:stretchMode="columnWidth"
android:verticalSpacing="0dp" >
</GridView>
</LinearLayout>
The main activity:
public class BaseRootActivity extends BaseActivity {
private DrawerLayout mDrawerLayout;
private ListView mDrawerList;
private ActionBarDrawerToggle mDrawerToggle;
private String[] mMainMenus;
public ListView getDrawerListView() {
return this.mDrawerList;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mMainMenus = this.getResources().getStringArray(R.array.main_menu_array);
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
mDrawerList = (ListView) this.findViewById(R.id.left_drawer);
// set up the drawer's list view with items and click listener
mDrawerList.setAdapter(new ArrayAdapter<String>(this, R.layout.drawer_list_item, mMainMenus));
// 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, mDrawerLayout, R.drawable.ic_drawer, R.string.drawer_open, R.string.drawer_close) {
public void onDrawerClosed(View view) {
getActionBar().setTitle("actionbar title");
invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()
}
public void onDrawerOpened(View drawerView) {
getActionBar().setTitle("drawer title");
invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()
}
};
mDrawerLayout.setDrawerListener(mDrawerToggle);
}
...
in main fragment
public class MemberHomeFragment extends Fragment implements OnItemClickListener {
private GridView mGridListView;
private UserThumbnailAdapter memberAdapter;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.member_home_layout, container, false);
mGridListView = (GridView) rootView.findViewById(R.id.member_home_thumbnail_grid);
mGridListView.setOnItemClickListener(this);
memberAdapter = new UserThumbnailAdapter(this.getActivity(), null);
mGridListView.setAdapter(memberAdapter);
this.startLoading(); // load thumbnails
return rootView;
}
So this isn't a problem with the way you are using the drawer layout as I mentioned earlier. It's a problem with the way you are using fragments. The way the FragmentManager works is you create a fragment transaction, and you tell the fragment transaction a set piece of work and then you commit it, so that it all happens at once.
When you add, remove, or in your case Replace a fragment you have to tell the FragmentManager where to put your fragment, and you were giving it the wrong location. You were telling it to put your fragment inside android.R.id.content, a place that ALL of the content on the screen lives inside. You only want to add a fragment to one your own containers. The fact that the ID you specified (android.R.id.content) begins with 'android', is a big giveaway that it is the android systems, and not yours.
You instead want to put it in the location inside of your navigation drawer that you specified, which is R.id.content_frame. You can see how you specified that in your xml above, which I will copy here for you:
<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"/>
I cannot understand but here is the issue:
As #spierce7 pointed out, the way I call fragment replacement is not correct (but why?)
My code is:
getFragmentManager().beginTransaction().replace(android.R.id.content, new MemberHomeFragment()).commit();
and when I changed to:
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction().replace(R.id.content_frame, new MemberHomeFragment()).commit();
It works.