Add a Drawer Layout to existing Map Fragment in Android - android

I already have a working Map fragment in my Activity.
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/drawerLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/map"
tools:context=".MapsActivity"
android:name="com.google.android.gms.maps.SupportMapFragment"
android:layout_alignParentTop="true">
<android.support.design.widget.FloatingActionButton
android:id="#+id/add"
android:onClick="locate_me"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_marginTop="360dp"
android:layout_marginRight="16dp"
android:layout_marginLeft="16dp"
android:clickable="true"
android:src="#drawable/tick"
app:backgroundTint="#000"
android:layout_gravity="right|end"
app:layout_anchorGravity="right|end"/>
<android.support.design.widget.FloatingActionButton
android:id="#+id/fab"
android:onClick="locate_me"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:clickable="true"
android:src="#drawable/mylocation"
app:backgroundTint="#000000"
android:layout_gravity="bottom|end"
app:layout_anchorGravity="right|end"/>
</fragment></android.support.v4.widget.DrawerLayout>
I want to add a Drawer Layout to this existing Activity. I have tried a lot but couldn't make it work. I have tried MapView as well. Can you give me some pointers? Thanks.

So this is pretty straight forward Here is a gist, with all the code below.
Dependency section of my build.gradle :
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:23.0.0'
compile 'com.google.android.gms:play-services:7.8.0'
compile 'com.android.support:design:23.0.0'
}
XML file for my AppCompatActivity which includes the drawer layout and a SupportMapFragment, since I am using appcompat-v7 for this project:
<RelativeLayout 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"
tools:context=".MainActivity">
<android.support.v4.widget.DrawerLayout
android:id="#+id/drawer"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<FrameLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<fragment
android:name="com.google.android.gms.maps.SupportMapFragment"
android:id="#+id/map"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<android.support.design.widget.FloatingActionButton
android:id="#+id/add"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_margin="16dp"
android:clickable="true"
android:src="#drawable/ic_maps_navigation"
app:backgroundTint="#777"
android:layout_gravity="bottom|end"/>
</FrameLayout>
<FrameLayout
android:id="#+id/nav_container"
android:layout_gravity="start"
android:layout_width="240dp"
android:layout_height="fill_parent"/>
</android.support.v4.widget.DrawerLayout>
</RelativeLayout>
Then I have a single activity:
package com.test.mapdrawer;
import android.content.res.Configuration;
import android.os.Bundle;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.app.AppCompatActivity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
public class MainActivity extends AppCompatActivity implements DrawerFragment.NavCallback {
private DrawerLayout drawer;
private ActionBarDrawerToggle mDrawerToggle;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
drawer = (DrawerLayout) findViewById(R.id.drawer);
setupDrawerLayout();
if(savedInstanceState == null) {
/*
Load the fragment for the drawer
*/
getSupportFragmentManager()
.beginTransaction()
.add(R.id.nav_container, DrawerFragment.newInstance(), "Drawer")
.commit();
}
}
#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 onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
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();
// Handle the drawer Actions
if(mDrawerToggle.onOptionsItemSelected(item)){
return true;
}
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
private void setupDrawerLayout(){
// Instantiate the Drawer Toggle
mDrawerToggle = new ActionBarDrawerToggle(this, drawer, R.string.app_name, R.string.app_name){
#Override
public void onDrawerOpened(View drawerView) {
super.onDrawerOpened(drawerView);
invalidateOptionsMenu();
getSupportActionBar().setTitle(getString(R.string.app_name));
}
#Override
public void onDrawerClosed(View drawerView) {
super.onDrawerClosed(drawerView);
invalidateOptionsMenu();
getSupportActionBar().setTitle(getString(R.string.app_name));
}
};
// Set the Toggle on the Drawer, And tell the Action Bar Up Icon to show
drawer.setDrawerListener(mDrawerToggle);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeButtonEnabled(true);
}
#Override
public void onNavSelected(int position) {
Toast.makeText(this, "Selected item: "+ position + " from nav", Toast.LENGTH_SHORT).show();
}
}
And finally your typical Manifest for a Map project:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.test.mapdrawer" >
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-feature
android:glEsVersion="0x00020000"
android:required="true"/>
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<meta-data
android:name="com.google.android.gms.version"
android:value="#integer/google_play_services_version" />
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="<YOUR_MAPS_API_KEY_HERE>"/>
<activity
android:name=".MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Then you want to create and populate the Navigation Drawer Fragment:
package com.test.mapdrawer;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
public class DrawerFragment extends Fragment {
private static final String [] NAV_ITEMS = {"Home", "Nav Item 2", " Nav Item 3", "Nav Item 4"};
private ListView mListView;
private NavCallback mCallback;
public interface NavCallback{
void onNavSelected(int position);
}
/**
* Create a static method to return this fragment
* #return - this fragment
*/
public static DrawerFragment newInstance(){
return new DrawerFragment();
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
mCallback = (MainActivity) activity;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.drawer_fragment, container, false);
/*
You can really use anything you want here but for simplicity lest assume ListView
*/
mListView = (ListView) view.findViewById(R.id.listViewNav);
mListView.setOnItemClickListener(ListListener);
return view;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
// Simple adapter, Also this is for simplicity and adapter can be used
mListView.setAdapter(new ArrayAdapter<>(getActivity(), android.R.layout.simple_list_item_1, NAV_ITEMS));
}
private final AdapterView.OnItemClickListener ListListener = new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
mCallback.onNavSelected(position);
}
};
}
Which has layout:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="match_parent"
android:background="#android:color/black">
<ListView
android:id="#+id/listViewNav"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</FrameLayout>
Please note I have updated 2 files for this Change and added 2
MainActivity -> now implements interface and onCreate contains logic to load fragment
activity_main.xml -> FrameLayout background for drawer is removed
New Drawerfragment
New drawer_fragment.xml
Also, the gist has been update to reflect these changes, happy coding!

Related

Activity onCreate is Called Infinitely After Screen Rotation to Landscape

I created an Android app with custom Toolbar and NavigationDrawer. I used Android API 22 and tested on Nexus 5 (Android 5.1.0). When I started the app in landscape screen (and also rotate the app from portrait to landscape), the app always showed blinking infinitely. Although, I rotated to portrait, it kept blinking. I ran debugger and found that Activity.onCreate was always called repeatedly.
This is my code:
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example">
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/MyTheme.NoActionBar">
<activity
android:name=".activity.MainActivity"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".activity.SettingsActivity"
android:configChanges="locale"
android:label="#string/settings"
android:parentActivityName=".activity.MainActivity"
android:theme="#style/MyTheme.Light">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".activity.MainActivity" />
</activity>
</application>
</manifest>
MainActivity.java
package com.example.activity;
import android.content.Intent;
import android.content.res.Configuration;
import android.content.res.TypedArray;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarActivity;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.LinearLayout;
import android.widget.ListView;
import com.example.R;
import com.example.nav.NavDrawerItem;
import com.example.nav.NavDrawerListAdapter;
import com.example.util.VersionUtil;
import java.util.ArrayList;
public class MainActivity extends ActionBarActivity {
private Toolbar mToolbar;
private DrawerLayout mDrawerLayout;
private LinearLayout mDrawerRoot;
private ListView mDrawerList;
private ActionBarDrawerToggle mDrawerToggle;
private NavDrawerListAdapter mDrawerAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mDrawerList = (ListView) findViewById(R.id.drawer_list);
mToolbar = (Toolbar) findViewById(R.id.toolbar);
mDrawerLayout = (DrawerLayout) findViewById(R.id.main_drawer_layout);
mDrawerRoot = (LinearLayout) findViewById(R.id.drawer_root);
initNavigationDrawer();
}
protected void initNavigationDrawer() {
if (mToolbar != null) {
setSupportActionBar(mToolbar);
}
mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, mToolbar, R.string.drawer_open, R.string.drawer_close) {
#Override
public void onDrawerClosed(View drawerView) {
super.onDrawerClosed(drawerView);
}
#Override
public void onDrawerOpened(View drawerView) {
super.onDrawerOpened(drawerView);
}
};
mDrawerLayout.setDrawerListener(mDrawerToggle);
String[] navMenuTitles = getResources().getStringArray(R.array.nav_drawer_items);
TypedArray navMenuIcons = getResources().obtainTypedArray(R.array.nav_drawer_icons);
TypedArray navMenuSelectedIcons = getResources().obtainTypedArray(R.array.nav_drawer_selected_icons);
ArrayList<NavDrawerItem> navDrawerItems = new ArrayList<>();
for (int i = 0, len = navMenuTitles.length; i < len; i++) {
navDrawerItems.add(new NavDrawerItem(navMenuTitles[i], navMenuIcons.getResourceId(i, -1), navMenuSelectedIcons.getResourceId(i, -1), false));
}
// Recycle the typed array
navMenuIcons.recycle();
navMenuSelectedIcons.recycle();
// setting the nav drawer list adapter
mDrawerAdapter = new NavDrawerListAdapter(getApplicationContext(), navDrawerItems);
mDrawerList.setAdapter(mDrawerAdapter);
mDrawerList.setOnItemClickListener(new DrawerItemClickListener());
mDrawerList.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
selectDrawerMenuItem(0);
}
#Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
mDrawerToggle.syncState();
}
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
mDrawerToggle.onConfigurationChanged(newConfig);
setContentView(R.layout.activity_main);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (mDrawerToggle.onOptionsItemSelected(item)) {
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
public void setTitle(CharSequence title) {
if (mToolbar != null) {
mToolbar.setTitle(title);
} else {
super.setTitle(title);
}
}
private class DrawerItemClickListener implements ListView.OnItemClickListener {
#Override
public void onItemClick(AdapterView parent, View view, int position, long id) {
selectDrawerMenuItem(position);
}
}
private void selectDrawerMenuItem(int position) {
switch (position) {
case 3: // Settings
showSettings();
break;
case 4: // Help and Feedback
sendHelpAndFeedbackEmail();
break;
default:
setSelectedNavItemMenu(position);
break;
}
mDrawerLayout.closeDrawer(mDrawerRoot);
}
private void setSelectedNavItemMenu(int position) {
for (int i = 0, size = mDrawerAdapter.getCount(); i < size; i++) {
NavDrawerItem menuItem = (NavDrawerItem) mDrawerAdapter.getItem(i);
menuItem.setSelected(i == position);
}
mDrawerList.setItemChecked(position, true);
}
private void showSettings() {
Intent settingsIntent = new Intent(this, SettingsActivity.class);
startActivity(settingsIntent);
}
private void sendHelpAndFeedbackEmail() {
Intent emailIntent = new Intent(Intent.ACTION_SENDTO);
emailIntent.setType("text/plain");
String versionName = VersionUtil.getVersionName(this);
int versionCode = VersionUtil.getVersionCode(this);
emailIntent.putExtra(Intent.EXTRA_SUBJECT, String.format(getString(R.string.email_help_subject), getText(R.string.app_name), versionName, versionCode));
emailIntent.setData(Uri.parse("mailto:" + getText(R.string.email_send_to)));
emailIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(Intent.createChooser(emailIntent, getText(R.string.email_chooser_title)));
}
}
Why was the app blinking? Is there any solution to this problem?
Thanks.
EDIT #1
This was from Logcat:
...
03-22 22:50:51.716 31125-31125/com.example W/View﹕ requestLayout() improperly called by android.widget.ListView{654f6b5 VFED.VC. ......ID 0,75-912,1080 #7f0b0042 app:id/drawer_list} during layout: running second layout pass
03-22 22:50:51.821 31125-31125/com.example W/View﹕ requestLayout() improperly called by android.widget.ListView{3df1b0fa VFED.VC. ......ID 0,75-912,1080 #7f0b0042 app:id/drawer_list} during layout: running second layout pass
03-22 22:50:51.918 31125-31125/com.example W/View﹕ requestLayout() improperly called by android.widget.ListView{7b0a09b VFED.VC. ......ID 0,75-912,1080 #7f0b0042 app:id/drawer_list} during layout: running second layout pass
...
Those errors were repeated.
EDIT #2
activity_main.xml
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/main_drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<!-- Your normal content view -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<!-- We use a Toolbar so that our drawer can be displayed
in front of the action bar -->
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
android:minHeight="?attr/actionBarSize"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light"
app:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar" />
<!-- The rest of your content view -->
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#fff">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="Activity Content"
android:textColor="#000" />
</RelativeLayout>
</LinearLayout>
<!-- Your drawer view. This can be any view, LinearLayout
is just an example. As we have set fitSystemWindows=true
this will be displayed under the status bar. -->
<LinearLayout
android:id="#+id/drawer_root"
android:layout_width="304dp"
android:layout_height="match_parent"
android:layout_gravity="left|start"
android:fitsSystemWindows="true">
<!-- Your drawer content -->
<ListView
android:id="#+id/drawer_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/white"
android:divider="#null"
android:fastScrollEnabled="false"
/>
</LinearLayout>
</android.support.v4.widget.DrawerLayout>
EDIT #3
NavDrawerListAdapter.java
import java.util.ArrayList;
import android.app.Activity;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import com.example.R;
/**
* Created by edward on 01/03/2015.
*/
public class NavDrawerListAdapter extends BaseAdapter {
private Context context;
private ArrayList<NavDrawerItem> navDrawerItems;
public NavDrawerListAdapter(Context context, ArrayList<NavDrawerItem> navDrawerItems) {
this.context = context;
this.navDrawerItems = navDrawerItems;
}
#Override
public int getCount() {
return navDrawerItems.size();
}
#Override
public Object getItem(int position) {
return navDrawerItems.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
LayoutInflater mInflater = (LayoutInflater)
context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
convertView = mInflater.inflate(R.layout.nav_list_item, null);
}
ImageView imgIcon = (ImageView) convertView.findViewById(R.id.nav_icon);
TextView txtTitle = (TextView) convertView.findViewById(R.id.nav_title);
TextView txtCount = (TextView) convertView.findViewById(R.id.nav_counter);
NavDrawerItem item = navDrawerItems.get(position);
if (item.isSelected()) {
imgIcon.setImageResource(navDrawerItems.get(position).getIconSelectedResId());
} else {
imgIcon.setImageResource(navDrawerItems.get(position).getIconResId());
}
txtTitle.setText(item.getTitle());
if (navDrawerItems.get(position).isCounterVisible()) {
txtCount.setVisibility(View.VISIBLE);
txtCount.setText(navDrawerItems.get(position).getCount());
} else {
txtCount.setVisibility(View.GONE);
}
return convertView;
}
}
nav_list_item.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/nav_background_selector"
android:minHeight="?android:attr/listPreferredItemHeightSmall">
<ImageView
android:id="#+id/nav_icon"
android:layout_width="#dimen/nav_icon_size"
android:layout_height="#dimen/nav_icon_size"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:layout_marginLeft="16dp"
android:layout_marginRight="24dp"
android:src="#drawable/ic_launcher" />
<TextView
android:id="#+id/nav_title"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_centerVertical="true"
android:layout_toRightOf="#id/nav_icon"
android:gravity="center_vertical"
android:paddingRight="40dp"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="#color/primary_text"
android:textStyle="bold"/>
<TextView
android:id="#+id/nav_counter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginRight="8dp"
android:background="#color/primary_light"
android:text="0"
android:textColor="#color/primary_text" />
</RelativeLayout>
Remove setContentView(R.layout.activity_main); from onConfigurationChanged() method
And if you are using this then remove it
android:fastScrollEnabled="true"
android:fastScrollAlwaysVisible="true"

App icon doesn't appear in action bar while using Theme.appCompat.light.DarkActionBar

I am following a tutorrial to make a Navigation Drawer using supported library V7 so i had to use Theme.appCompat.light.DarkActionBar as the app theme...
The problem is:
App Icon doesn't appear in the default place in the Action Bar.
The drawer icon is shifted to the right
Here is my Code:
package com.tutorial18nav.tutorial18nav;
import android.content.res.Configuration;
import android.os.Bundle;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarActivity;
import android.support.v7.app.ActionBarDrawerToggle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;
public class MainActivity extends ActionBarActivity implements OnItemClickListener {
private DrawerLayout mDrawerLayout;
private ListView mDrawerlist;
String[] sections;
private android.support.v4.app.ActionBarDrawerToggle mDrawerToggle;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
mDrawerlist = (ListView) findViewById(R.id.left_drawer);
sections = getResources().getStringArray(R.array.sections);
mDrawerlist.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, sections));
mDrawerlist.setOnItemClickListener(this);
mDrawerToggle = new android.support.v4.app.ActionBarDrawerToggle(this, mDrawerLayout, R.drawable.ic_drawer, R.string.drawer_open, R.string.drawer_close) {
#Override
public void onDrawerOpened(View drawerView) {
Toast.makeText(MainActivity.this, "Drawer is opened", Toast.LENGTH_SHORT).show();
}
#Override
public void onDrawerClosed(View drawerView) {
Toast.makeText(MainActivity.this, "Drawer is closed", Toast.LENGTH_SHORT).show();
}
};
mDrawerLayout.setDrawerListener(mDrawerToggle);
getSupportActionBar().setHomeButtonEnabled(true);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
#Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
mDrawerToggle.syncState();
}
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Toast.makeText(this, "Section number " + (position + 1) + " has been selected", Toast.LENGTH_SHORT).show();
selectItem(position);
}
public void selectItem(int position) {
mDrawerlist.setItemChecked(position, true);
setTitle(sections[position]);
}
public void setTitle(String title) {
getSupportActionBar().setTitle(title);
}
#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);
return true;
}
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
mDrawerToggle.onConfigurationChanged(newConfig);
}
#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();
if (id == R.id.action_settings) {
return true;
}
if(mDrawerToggle.onOptionsItemSelected(item)){
return true;
}
return super.onOptionsItemSelected(item);
}
}
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" >
</FrameLayout>
<ListView
android:background="#FF8800"
android:id="#+id/left_drawer"
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_gravity="left">
</ListView>
</android.support.v4.widget.DrawerLayout>
Manifest File:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.tutorial18nav.tutorial18nav"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="21"
android:targetSdkVersion="21" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/Theme.AppCompat.Light.DarkActionBar" >
<activity
android:name=".MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
Menu.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:context="com.tutorial18nav.tutorial18nav.MainActivity" >
<item
android:id="#+id/action_settings"
android:orderInCategory="100"
android:showAsAction="never"
android:title="#string/action_settings"/>
</menu>

Why won't my Android Navigation Drawer Open

I am trying to set up a listview for some actions that is displayed on a Navigation Drawer that opens from the right. The project will compile with no errors and I tried out my BaseAdapter on a ListView that is already in view and that works fine. There is no action bar in my app so the user has to open the drawer by sliding from the right edge of the screen. All the info to be displayed in the listview is handled in the adapter.
Here is what is in onCreate that is related to the drawer (On the official tutorial it seemed the only reason they would reference the actual DrawerLayout is to give it a toggle on the action bar, which I don't have):
I am now getting a null pointer exception when I try to assign the adapter.
ListView drawerList = (ListView) findViewById(R.id.drawerList); returns null
UPDATED CODE
ListView drawerList = (ListView) findViewById(R.id.drawerList);
SectionedAdapter DrawerAdapter = new SectionedAdapter(this);
drawerList.setAdapter(DrawerAdapter);
main_activity.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/left_drawer">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/drawer_frame">
<AllOfMyStuff/>
<FrameLayout/>
<!--Always returns null-->
<ListView android:id="#+id/drawerList"
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_gravity="right"
android:background="#ff1f1f1f"
android:drawSelectorOnTop="true"/>
</android.support.v4.widget.DrawerLayout>
Your xml seems to be fine but y r u inflating the menu_drawer.xml in fragment and not on an Activity ..Check out this video for better idea :: https://www.youtube.com/watch?v=K8hSIP2ha-g
this is my code..
activity_main.xml
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/drawerlayout">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/maincontent"></FrameLayout>
<ListView
android:background="#FFFFFF"
android:divider="#null"
android:layout_width="240dp"
android:layout_height="match_parent"
android:id="#+id/drawerlist"
android:layout_gravity="left">
</ListView>
</android.support.v4.widget.DrawerLayout>
MainActivity.java
package com.example.nav;
import android.app.ActionBar;
import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.support.v4.app.ActionBarDrawerToggle;
import android.support.v4.widget.DrawerLayout;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.ListView;
public class MainActivity extends Activity {
DrawerLayout mdrawer;
private ListView list;
private String[] planets;
ActionBar action;
ActionBarDrawerToggle mtoggle;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
list=(ListView)findViewById(R.id.drawerlist);
mdrawer=(DrawerLayout)findViewById(R.id.drawerlayout);
action=getActionBar();
mtoggle=new ActionBarDrawerToggle(this, mdrawer, R.drawable.ic_drawer,R.string.OndrawerOpen,R.string.OndrawerClose){
public void onDrawerClosed(View drawerView) {
super.onDrawerClosed(drawerView);
}
#Override
public void onDrawerOpened(View drawerView) {
super.onDrawerOpened(drawerView);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
return super.onOptionsItemSelected(item);
}
};
mdrawer.setDrawerListener(mtoggle);
getActionBar().setHomeButtonEnabled(true);
getActionBar().setDisplayHomeAsUpEnabled(true);
planets=getResources().getStringArray(R.array.planets);
list.setAdapter(new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,planets));
list.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> arg0, View arg1, int position,long arg3) {
setTitle(planets[position]);
}
});
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if(mtoggle.onOptionsItemSelected(item)){
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
mtoggle.syncState();
}
void setTitle(String value){
getActionBar().setTitle(value);
}
}
This might help!!
I have a solution for your problem:
1/ It should set a
android:theme="#style/AppThemeNoBar"
style in your manifest.
Add style
<style name="AppThemeNoBar" parent="Theme.AppCompat.Light">
<item name="android:windowNoTitle">true</item>
</style>
2/ menu_drawer :
<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 -->
<RelativeLayout
android:id="#+id/content_frame"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</RelativeLayout>
<!-- 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>
3/ MainActivity:
DrawerLayout mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
mDrawerToggle = new ActionBarDrawerToggle(
this, mDrawerLayout, R.drawable.menu_icon, R.string.drawer_open,
R.string.drawer_close
) {
#Override
public void onDrawerClosed(View view) {
invalidateOptionsMenu();
}
#Override
public void onDrawerOpened(View drawerView) {
invalidateOptionsMenu();
}
};
As a result you get a swipe-menu without ActionBar.
Maybe you made a mistake in view id name:
findViewById(R.id.drawList);
it should be R.id.drawerList instead of R.id.drawList.
P.S. I don't have enough rating to comment on answer.

Android Navigation Drawer not being closed by dragging it

I'm trying to implement a Navigation Drawer and I managed successfully to integrate it with the Action Bar: it opens and closes when the application button is pressed and it closes when I press on a blank part of the screen, but it does not allow to be dragged back to its original position. Once opened, I can't close it with a swipe (as in every application I have seen so far).
Here is my Java code:
package com.example.notificationswhisperer;
import java.util.ArrayList;
import java.util.List;
import android.app.Activity;
import android.content.res.Configuration;
import android.os.Bundle;
import android.support.v4.app.ActionBarDrawerToggle;
import android.support.v4.widget.DrawerLayout;
import android.view.Gravity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;
public class MainActivity
extends Activity {
private DrawerLayout drawerLayout;
private ListView drawerList;
private ActionBarDrawerToggle drawerToggle;
private List<AppDrawerItem> drawerItems;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_notifications_whisperer);
drawerItems = new ArrayList<AppDrawerItem>();
drawerItems.add(
new AppDrawerItem("Settings",
getResources().getDrawable(R.drawable.ic_action_settings)));
drawerItems.add(
new AppDrawerItem("Test",
getResources().getDrawable(R.drawable.ic_action_settings)));
getActionBar().setDisplayHomeAsUpEnabled(true);
getActionBar().setHomeButtonEnabled(true);
drawerLayout = (DrawerLayout) findViewById(R.id.layout_app_drawer);
drawerToggle = new ActionBarDrawerToggle(
this, // Context
drawerLayout, // DrawerLayout object
R.drawable.ic_drawer, // Drawer icon
0, // Open Drawer description
0) { // Closed Drawer description
public void onDrawerOpened(View view) {
super.onDrawerOpened(view);
invalidateOptionsMenu();
}
public void onDrawerSlide(View view, float offset) {
if (offset > .5) {
onDrawerOpened(view);
} else {
onDrawerClosed(view);
}
}
public void onDrawerClosed(View view) {
super.onDrawerClosed(view);
invalidateOptionsMenu();
}
};
drawerLayout.setDrawerListener(drawerToggle);
drawerLayout.setDrawerShadow(R.drawable.drawer_shadow, Gravity.START);
drawerList = (ListView) findViewById(R.id.list_app_drawer);
drawerList.setAdapter(new AppDrawerAdapter(this, drawerItems));
drawerList.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
drawerList.setItemChecked(position, true);
drawerLayout.closeDrawer(drawerList);
}
});
}
#Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
// Sync the toggle state after onRestoreInstanceState has occurred.
drawerToggle.syncState();
}
#Override
public void onConfigurationChanged(Configuration config) {
super.onConfigurationChanged(config);
drawerToggle.onConfigurationChanged(config);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.notifications_whisperer, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (drawerToggle.onOptionsItemSelected(item)) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
This is my layout for the activity:
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/layout_app_drawer"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.notificationswhisperer.NotificationsWhisperer" >
<ListView
android:id="#+id/list_app_drawer"
android:layout_width="280dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:choiceMode="singleChoice"
android:divider="#android:color/black"
android:dividerHeight="0.5dp"
android:background="#android:color/white" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/hello_world" />
</android.support.v4.widget.DrawerLayout>
And this is for the List entries:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="48dp"
android:orientation="vertical" >
<ImageView
android:id="#+id/list_item_app_drawer_image"
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_marginLeft="8dp"
android:layout_centerVertical="true" />
<TextView
android:id="#+id/list_item_app_drawer_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_centerVertical="true"
android:layout_toRightOf="#+id/list_item_app_drawer_image"
android:textSize="18sp" />
</RelativeLayout>
Am I missing something? Thank you in advance.
ADDENDUM: Additionally, the back button won't close the Drawer.
I had the very same issue : the drawer could be opened by a swipe, but could only be closed by a click on the actionbar button.
After some research, it appeared that the underlying activity had several critical bugs : some fragments were added which were adding an un-initialized pager (with a null adapter)
Anyway, when I fixed these bugs (which had nothing to do with the drawer implementation), then behavior went correct.

Cannot add object with Parse

With my Android project created with latest version of Eclipse+ADT I cannot access parse.com api. If I use the prepackaged project from parse.com I can access. But If I create a new Android project from scratch I cannot. I suspect the problem is because of parse initialization and fragments. As prepackaged project from parse.com doesn't use fragments. In this program first button should add an object to database but that doesnt work.. Can anyone know solution for this?
activity_main.xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.deneme.MainActivity"
tools:ignore="MergeRootFrame" />
fragment_main.xml:
<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"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context="com.example.deneme.MainActivity$PlaceholderFragment" >
<LinearLayout
android:id="#+id/mainLayout"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:orientation="vertical"
android:paddingBottom="1.0dip"
android:paddingLeft="4.0dip"
android:paddingRight="4.0dip"
android:paddingTop="5.0dip"
android:layout_below="#+id/txtTitle">
<Button
android:id="#+id/btnCreate"
android:layout_width="fill_parent"
android:layout_height="0.0dip"
android:layout_weight="1.0"
android:text="Add Object"
android:textColor="#android:color/white"
android:textSize="25sp" />
<Button
android:id="#+id/btnIncrement"
android:layout_width="fill_parent"
android:layout_height="0.0dip"
android:layout_weight="1.0"
android:text="Increment votes"
android:textColor="#android:color/white"
android:textSize="25sp" />
</LinearLayout>
AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.deneme"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="19" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<application
android:name="denemeApp"
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name="com.example.deneme.MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
denemeApp.java
package com.example.deneme;
import com.parse.Parse;
import com.parse.ParseACL;
import com.parse.ParseUser;
import android.app.Application;
public class denemeApp extends Application {
#Override
public void onCreate() {
super.onCreate();
// Add your initialization code here
Parse.initialize(this, "KEY1", "KEY2");
ParseUser.enableAutomaticUser();
ParseACL defaultACL = new ParseACL();
// If you would like all objects to be private by default, remove this line.
defaultACL.setPublicReadAccess(true);
ParseACL.setDefaultACL(defaultACL, true);
}
}
MainActivity.java:
package com.example.deneme;
import com.example.deneme.R;
import com.parse.GetCallback;
import com.parse.ParseException;
import com.parse.ParseObject;
import com.parse.ParseQuery;
import android.support.v7.app.ActionBarActivity;
import android.support.v7.app.ActionBar;
import android.support.v4.app.Fragment;
import android.content.Intent;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.os.Build;
public class MainActivity extends ActionBarActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.add(R.id.container, new PlaceholderFragment())
.commit();
}
}
#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);
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();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
/**
* A placeholder fragment containing a simple view.
*/
public static class PlaceholderFragment extends Fragment {
public PlaceholderFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
Button btnCreate = (Button)rootView.findViewById(R.id.btnCreate);
btnCreate.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
ParseObject testObject = new ParseObject("testobject");
testObject.put("total_votes", 0);
testObject.saveInBackground();
}
});
Button btnIncrement = (Button)rootView.findViewById(R.id.btnIncrement);
btnIncrement.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//works with "testobject" and "7erUqKQn1P"
//doesnt work "testobject2" and "1g68ZP1ikc"
ParseQuery<ParseObject> query = ParseQuery.getQuery("testobject");
query.getInBackground("7erUqKQn1P", new GetCallback<ParseObject>()
{
public void done(ParseObject vote, ParseException e)
{
if(e == null)
{
vote.increment("total_votes");
vote.saveInBackground();
}
}//done
}//new GetCallback
);//query.getInBackground
}
});
return rootView;
}
}
}
You need to add this permission to your AndroidManifest.xml file
<uses-permission android:name="android.permission.INTERNET" />

Categories

Resources