I am currently working on an android app for 4.2.2 that uses the new NavigationDrawer. It works like a charm except for adding icons.
I found some sample code in which the List view becomes a Relative layout in which 2 parallel arrays are nested and rendered by an Array Adapter based on a menu model a way that they are synchronized, I think.
Here is the MainActivity:
package com.sorin.medisynced.main;
import android.app.Activity;
import android.app.SearchManager;
import android.content.Intent;
import android.content.res.Configuration;
import android.os.Bundle;
import android.support.v4.app.ActionBarDrawerToggle;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;
import com.sorin.medisynced.R;
import com.sorin.medisynced.filepickerio.FilepickerSaver;
import com.sorin.medisynced.filepickerio.FilepickerViewer;
import com.sorin.medisynced.qr.IntentIntegrator;
public class MediSyncedMainActivity extends Activity {
private ListView mDrawerList;
private DrawerLayout mDrawerLayout;
private String[] menuItemsData;
private String[] menuItemsTools;
private ActionBarDrawerToggle mDrawerToggle;
private String[] menuItemsEmergency;
private CharSequence mDrawerTitle;
private CharSequence mTitle;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_drawer);
mTitle = mDrawerTitle = getTitle();
// set click listener for list drawer
// mDrawerList.setOnItemClickListener(new DrawerItemClickListener());
// enable ActionBar app icon to behave as action to toggle nav drawer
getActionBar().setDisplayHomeAsUpEnabled(true);
getActionBar().setHomeButtonEnabled(true);
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
mDrawerList = (ListView) findViewById(R.id.drawer);
// set a custom shadow that overlays the main content when the drawer
// opens
mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow,
GravityCompat.START);
_initMenu();
// 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(getString(R.string.drawer_close));
invalidateOptionsMenu(); // creates call to
// onPrepareOptionsMenu()
}
@Override
public void onDrawerOpened(View drawerView) {
getActionBar().setTitle(getString(R.string.drawer_open));
invalidateOptionsMenu(); // creates call to
// onPrepareOptionsMenu()
}
};
mDrawerLayout.setDrawerListener(mDrawerToggle);
if (savedInstanceState == null) {
// selectItem(0);
}
}
private void _initMenu() {
NsMenuAdapter mAdapter = new NsMenuAdapter(this);
// Add First Header
mAdapter.addHeader(R.string.menu_data);
// Add first block
menuItemsData = getResources().getStringArray(R.array.menu_data);
String[] menuDataIcons = getResources().getStringArray(
R.array.data_menu_icons);
int dataIcons = 0;
for (String item : menuItemsData) {
int id_data_title = getResources().getIdentifier(item, "string",
this.getPackageName());
int id_data_icon = getResources()
.getIdentifier(menuDataIcons[dataIcons], "drawable",
this.getPackageName());
NsMenuItemModel mItem = new NsMenuItemModel(id_data_title,
id_data_icon);
mAdapter.addItem(mItem);
dataIcons++;
}
// Add second header
mAdapter.addHeader(R.string.menu_tools);
// Add second block
menuItemsTools = getResources().getStringArray(R.array.menu_tools);
String[] menuToolsIcons = getResources().getStringArray(
R.array.tools_menu_icons);
int toolsIcons = 0;
for (String item : menuItemsTools) {
int id_tools_title = getResources().getIdentifier(item, "string",
this.getPackageName());
int id_tools_icon = getResources().getIdentifier(
menuToolsIcons[toolsIcons], "drawable",
this.getPackageName());
// creating drawer menu model
NsMenuItemModel mItem = new NsMenuItemModel(id_tools_title,
id_tools_icon);
mAdapter.addItem(mItem);
toolsIcons++;
}
// Add third header
mAdapter.addHeader(R.string.menu_emergency);
// Add third block
menuItemsEmergency = getResources().getStringArray(
R.array.menu_emergency);
String[] menuEmerIcons = getResources().getStringArray(
R.array.emergency_menu_icons);
int emerIcons = 0;
for (String item : menuItemsEmergency) {
int id_emer_title = getResources().getIdentifier(item, "string",
this.getPackageName());
int id_emer_icon = getResources()
.getIdentifier(menuEmerIcons[emerIcons], "drawable",
this.getPackageName());
// creating drawer menu model
NsMenuItemModel mItem = new NsMenuItemModel(id_emer_title,
id_emer_icon);
mAdapter.addItem(mItem);
emerIcons++;
}
mDrawerList = (ListView) findViewById(R.id.drawer);
if (mDrawerList != null)
mDrawerList.setAdapter(mAdapter);
mDrawerList.setOnItemClickListener(new DrawerItemClickListener());
}
@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) {
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_save).setVisible(!drawerOpen);
return super.onPrepareOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
/*
* The action bar home/up 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_qrscan:
IntentIntegrator integrator = new IntentIntegrator(
MediSyncedMainActivity.this);
integrator.initiateScan();
Toast.makeText(this, "Scan Qr Code", Toast.LENGTH_SHORT).show();
return true;
case R.id.action_filepicker_save:
startActivity(new Intent(this, FilepickerSaver.class));
Toast.makeText(this, "Save data on cloud", Toast.LENGTH_SHORT)
.show();
return true;
case R.id.action_filepicker_view:
startActivity(new Intent(this, FilepickerViewer.class));
Toast.makeText(this, "View data from cloud", Toast.LENGTH_SHORT)
.show();
return true;
case R.id.action_websearch:
// create intent to perform web search for this planet
Intent intent = new Intent(Intent.ACTION_SEARCH);
intent.putExtra(SearchManager.QUERY, getApplicationContext()
.getDatabasePath(DROPBOX_SERVICE));
// catch event that there's no activity to handle intent
if (intent.resolveActivity(getPackageManager()) != null) {
startActivity(intent);
} else {
Toast.makeText(this, R.string.search_database,
Toast.LENGTH_LONG).show();
}
return true;
default:
// Handle your other action bar items...
return super.onOptionsItemSelected(item);
}
}
private class DrawerItemClickListener implements
ListView.OnItemClickListener {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
// Highlight the selected item, update the title, and close the
// drawer
// update selected item and title, then close the drawer
mDrawerList.getCount();
mDrawerList.setItemChecked(position, true);
String text = "menu click... should be implemented";
Toast.makeText(MediSyncedMainActivity.this, text, Toast.LENGTH_LONG)
.show();
mDrawerLayout.closeDrawer(mDrawerList);
}
}
@Override
public void setTitle(CharSequence title) {
mTitle = title;
getActionBar().setTitle(mTitle);
}
}
Here is the menu model:
package com.sorin.medisynced.main;
public class NsMenuItemModel {
public int title;
public int iconRes;
public boolean isHeader;
public NsMenuItemModel(int title, int iconRes,boolean header) {
this.title = title;
this.iconRes = iconRes;
this.isHeader=header;
}
public NsMenuItemModel(int title, int iconRes) {
this(title,iconRes,false);
}
}
Here ist the ArrayAdapter implementation:
package com.sorin.medisynced.main;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import com.sorin.medisynced.R;
public class NsMenuAdapter extends ArrayAdapter<NsMenuItemModel> {
/*
* public NsMenuAdapter(Context context, int resource, int
* textViewResourceId, String[] objects) { super(context,
* R.layout.ns_menu_row, textViewResourceId, objects); }
*/
public NsMenuAdapter(Context context) {
super(context, 0);
}
public void addHeader(int title) {
add(new NsMenuItemModel(title, -1, true));
}
public void addItem(int title, int icon) {
add(new NsMenuItemModel(title, icon, false));
}
public void addItem(NsMenuItemModel itemModel) {
add(itemModel);
}
@Override
public int getViewTypeCount() {
return 2;
}
@Override
public int getItemViewType(int position) {
return getItem(position).isHeader ? 0 : 1;
}
@Override
public boolean isEnabled(int position) {
return !getItem(position).isHeader;
}
public static class ViewHolder {
public final TextView textHolder;
public final ImageView imageHolder;
public ViewHolder(TextView text1, ImageView image1) {
this.textHolder = text1;
this.imageHolder = image1;
}
}
public View getView(int position, View convertView, ViewGroup parent) {
NsMenuItemModel item = getItem(position);
ViewHolder holder = null;
View view = convertView;
if (view == null) {
int layout = R.layout.ns_menu_row;
if (item.isHeader)
layout = R.layout.ns_menu_row_header;
view = LayoutInflater.from(getContext()).inflate(layout, null);
TextView text1 = (TextView) view.findViewById(R.id.menurow_title);
ImageView image1 = (ImageView) view.findViewById(R.id.menurow_icon);
view.setTag(new ViewHolder(text1, image1));
}
if (holder == null && view != null) {
Object tag = view.getTag();
if (tag instanceof ViewHolder) {
holder = (ViewHolder) tag;
}
}
if(item != null && holder != null)
{
if (holder.textHolder != null)
holder.textHolder.setText(item.title);
if (holder.imageHolder != null) {
if (item.iconRes > 0) {
holder.imageHolder.setVisibility(View.VISIBLE);
holder.imageHolder.setImageResource(item.iconRes);
} else {
holder.imageHolder.setVisibility(View.GONE);
}
}
}
return view;
}
}
The string-array xml:
<string-array name="menu_data">
<item>menu_data_patient_profile</item>
<item>menu_data_hospital_staff</item>
<item>menu_data_xray_results</item>
<item>menu_data_lab_results</item>
<item>menu_data_medical_supplies_index</item>
<item>menu_data_hospital_forms_index</item>
<item>menu_data_prescriptions_index</item>
<item>menu_data_illness_index</item>
<item>menu_data_drugs_index</item>
<item>menu_data_hospital_interactive_map</item>
</string-array>
<string-array name="menu_tools">
<item>menu_tools_ecg</item>
<item>menu_tools_pulse</item>
<item>menu_tools_microscope_feed</item>
<item>menu_tools_blood_pressure</item>
<item>menu_tools_temperature</item>
<item>menu_tools_radiation_levels</item>
<item>menu_tools_movement_log</item>
</string-array>
<string-array name="menu_emergency">
<item>menu_emergency_call_ambulance</item>
<item>menu_emergency_call_helicopter</item>
<item>menu_emergency_call_nurse</item>
<item>menu_emergency_call_doctor</item>
</string-array>
<array name="data_menu_icons">
<item>ic_patient_profile</item>
<item>ic_hospital_staff</item>
<item>ic_xray_results</item>
<item>ic_lab_results</item>
<item>ic_medical_supplies_index</item>
<item>ic_hospital_forms_index</item>
<item>ic_prescription_index</item>
<item>ic_illness_index</item>
<item>ic_drugs_index</item>
<item>ic_hospital_interactive_map</item>
</array>
<array name="tools_menu_icons">
<item>ic_ecg</item>
<item>ic_pulse</item>
<item>ic_microscope_feed</item>
<item>ic_blood_pressure</item>
<item>ic_body_temperature</item>
<item>ic_radiation_levels</item>
<item>ic_movement_logger</item>
</array>
<array name="emergency_menu_icons">
<item>ic_call_ambulance</item>
<item>ic_call_helicopter</item>
<item>ic_call_nurse</item>
<item>ic_call_doctor</item>
</array>
and the main layout:
<!-- The main content view -->
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/content_frame"
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=".MediSyncedMainActivity" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/drawer_text" />
</RelativeLayout>
<!-- The navigation drawer -->
<ListView
android:id="@+id/drawer"
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="#DADADC"
android:choiceMode="singleChoice"
android:divider="@android:color/darker_gray"
android:dividerHeight="1dp"
android:showDividers="middle" />
How can I simplify the approach. Is there a way to use one array instead of such a complicated structure.
B.t.w. you can find my project on github under: https://github.com/greenspand/MediSynced
It is a medical app, hence the name. Thx y'all.