drawer: use custom navigation component

The native NavigationView component is not customizable enough.
To implement a proper account switcher we need to have full control on
this view. The NavigationView now only serves has a container for our
navigation fragment. This fragment manages the header and the navigation
list.

Change-Id: I272c29b466022552b244edd65b725d0dc3ec29eb
Tuleap: #1218
diff --git a/ring-android/app/src/main/java/cx/ring/client/HomeActivity.java b/ring-android/app/src/main/java/cx/ring/client/HomeActivity.java
index fb48900..e6beddd 100644
--- a/ring-android/app/src/main/java/cx/ring/client/HomeActivity.java
+++ b/ring-android/app/src/main/java/cx/ring/client/HomeActivity.java
@@ -71,15 +71,15 @@
 import cx.ring.model.Account;
 import cx.ring.model.CallContact;
 import cx.ring.model.ConfigKey;
+import cx.ring.navigation.RingNavigationFragment;
 import cx.ring.service.IDRingService;
 import cx.ring.service.LocalService;
 import cx.ring.settings.SettingsFragment;
 import cx.ring.share.ShareFragment;
 import cx.ring.utils.FileUtils;
-import cx.ring.views.MenuHeaderView;
 
 public class HomeActivity extends AppCompatActivity implements LocalService.Callbacks,
-        NavigationView.OnNavigationItemSelectedListener,
+        RingNavigationFragment.OnNavigationSectionSelected,
         ActivityCompat.OnRequestPermissionsResultCallback,
         ContactListFragment.Callbacks {
 
@@ -107,11 +107,10 @@
     private boolean mNoAccountOpened = false;
     private boolean mIsMigrationDialogAlreadyShowed;
 
-    private MenuHeaderView fMenuHead = null;
     private ActionBarDrawerToggle mDrawerToggle;
 
     @BindView(R.id.left_drawer)
-    NavigationView fMenu;
+    NavigationView mNavigationView;
 
     @BindView(R.id.drawer_layout)
     DrawerLayout mNavigationDrawer;
@@ -130,6 +129,7 @@
 
     private float mToolbarSize;
     protected android.app.Fragment fContent;
+    protected RingNavigationFragment fNavigation;
 
     public interface Refreshable {
         void refresh();
@@ -167,8 +167,6 @@
 
         setSupportActionBar(mToolbar);
 
-        fMenu.setNavigationItemSelectedListener(this);
-
         getSupportActionBar().setDisplayHomeAsUpEnabled(true);
         getSupportActionBar().setHomeButtonEnabled(true);
 
@@ -186,8 +184,8 @@
             @Override
             public void onDrawerOpened(View drawerView) {
                 invalidateOptionsMenu();
-                if (null != fMenuHead) {
-                    fMenuHead.updateUserView();
+                if (mNavigationView != null) {
+                    fNavigation.updateUserView();
                 }
             }
         };
@@ -226,11 +224,12 @@
                             showMigrationDialog();
                         }
                     }
+
                     if (!mNoAccountOpened && service.getAccounts().isEmpty()) {
                         mNoAccountOpened = true;
                         startActivityForResult(new Intent(HomeActivity.this, AccountWizard.class), AccountsManagementFragment.ACCOUNT_CREATE_REQUEST);
                     } else {
-                        fMenuHead.updateAccounts(service.getAccounts());
+                        fNavigation.updateAccounts(service.getAccounts());
                     }
                     break;
             }
@@ -254,8 +253,7 @@
                     @Override
                     public void onClick(DialogInterface dialog, int which) {
                         dialog.dismiss();
-                        onNavigationItemSelected(fMenu.getMenu().findItem(R.id.menuitem_accounts));
-                        fMenu.getMenu().findItem(R.id.menuitem_accounts).setChecked(true);
+                        fNavigation.selectSection(RingNavigationFragment.Section.MANAGE);
                     }
                 })
                 .setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
@@ -429,7 +427,7 @@
         }
         if (getFragmentManager().getBackStackEntryCount() > 1) {
             popCustomBackStack();
-            fMenu.getMenu().findItem(R.id.menuitem_home).setChecked(true);
+            fNavigation.selectSection(RingNavigationFragment.Section.HOME);
             return;
         }
 
@@ -475,11 +473,11 @@
             registerReceiver(receiver, intentFilter);
             mBound = true;
 
-            fMenuHead = (MenuHeaderView) fMenu.getHeaderView(0);
-            if (fMenuHead == null) {
-                fMenuHead = new MenuHeaderView(HomeActivity.this);
-                fMenuHead.setCallbacks(service);
-                fMenu.addHeaderView(fMenuHead);
+            if (fNavigation == null) {
+                fNavigation = new RingNavigationFragment();
+                getFragmentManager().beginTransaction()
+                        .replace(R.id.navigation_container, fNavigation, null)
+                        .commit();
             }
 
             FragmentManager fragmentManager = getFragmentManager();
@@ -488,9 +486,7 @@
                 fContent = new SmartListFragment();
                 fragmentManager.beginTransaction().replace(R.id.main_frame, fContent, HOME_TAG).addToBackStack(HOME_TAG).commit();
 
-                if (fMenuHead != null) {
-                    fMenuHead.registerAccountSelectionListener((MenuHeaderView.MenuHeaderAccountSelectionListener) fContent);
-                }
+
             } else if (fContent instanceof Refreshable) {
                 fragmentManager.beginTransaction().replace(R.id.main_frame, fContent).addToBackStack(HOME_TAG).commit();
                 ((Refreshable) fContent).refresh();
@@ -501,14 +497,23 @@
         @Override
         public void onServiceDisconnected(ComponentName className) {
             Log.d(TAG, "onServiceDisconnected " + className.getClassName());
-            if (fMenuHead != null) {
-                fMenuHead.setCallbacks(null);
-                fMenuHead = null;
+            if (fNavigation != null) {
+                fNavigation.setCallbacks(null);
+                fNavigation = null;
             }
             mBound = false;
         }
     };
 
+    // TODO: Remove this when low level services are ready
+    public void onNavigationViewReady() {
+            if (fNavigation != null) {
+                fNavigation.setCallbacks(service);
+                fNavigation.setNavigationSectionSelectedListener(HomeActivity.this);
+                fNavigation.registerAccountSelectionListener((RingNavigationFragment.MenuHeaderAccountSelectionListener) fContent);
+            }
+    }
+
     @Override
     public boolean onOptionsItemSelected(MenuItem item) {
         return mDrawerToggle.onOptionsItemSelected(item);
@@ -523,8 +528,8 @@
                 mNoAccountOpened = false;
             case REQUEST_CODE_PREFERENCES:
             case AccountsManagementFragment.ACCOUNT_EDIT_REQUEST:
-                if (fMenuHead != null) {
-                    fMenuHead.updateAccounts(service.getAccounts());
+                if (fNavigation != null) {
+                    fNavigation.updateAccounts(service.getAccounts());
                 }
                 break;
             case REQUEST_CODE_CALL:
@@ -534,12 +539,12 @@
                 break;
             case REQUEST_CODE_PHOTO:
                 if (resultCode == RESULT_OK && data != null) {
-                    fMenuHead.updatePhoto((Bitmap) data.getExtras().get("data"));
+                    fNavigation.updatePhoto((Bitmap) data.getExtras().get("data"));
                 }
                 break;
             case REQUEST_CODE_GALLERY:
                 if (resultCode == RESULT_OK && data != null) {
-                    fMenuHead.updatePhoto(data.getData());
+                    fNavigation.updatePhoto(data.getData());
                 }
                 break;
         }
@@ -556,12 +561,11 @@
     }
 
     @Override
-    public boolean onNavigationItemSelected(@NonNull MenuItem pos) {
-        pos.setChecked(true);
+    public void onNavigationSectionSelected(RingNavigationFragment.Section section) {
         mNavigationDrawer.closeDrawers();
 
-        switch (pos.getItemId()) {
-            case R.id.menuitem_home:
+        switch (section) {
+            case HOME:
                 if (fContent instanceof SmartListFragment) {
                     break;
                 }
@@ -572,7 +576,7 @@
                 popCustomBackStack();
                 fContent = getFragmentManager().findFragmentByTag(HOME_TAG);
                 break;
-            case R.id.menuitem_accounts:
+            case MANAGE:
                 if (fContent instanceof AccountsManagementFragment) {
                     break;
                 }
@@ -582,7 +586,7 @@
                         .replace(R.id.main_frame, fContent, ACCOUNTS_TAG)
                         .addToBackStack(ACCOUNTS_TAG).commit();
                 break;
-            case R.id.menuitem_about:
+            case ABOUT:
                 if (fContent instanceof AboutFragment) {
                     break;
                 }
@@ -592,16 +596,15 @@
                         .replace(R.id.main_frame, fContent, ABOUT_TAG)
                         .addToBackStack(ABOUT_TAG).commit();
                 break;
-            case R.id.menuitem_prefs:
+            case SETTINGS:
                 this.goToSettings();
                 break;
-            case R.id.menuitem_share:
+            case SHARE:
                 goToShare();
                 break;
             default:
-                return false;
+                break;
         }
-        return true;
     }
 
     private void goToShare() {
@@ -617,12 +620,6 @@
     }
 
     public void goToSettings() {
-        if (fMenu != null) {
-            MenuItem settingsItem = fMenu.getMenu().findItem(R.id.menuitem_prefs);
-            if (settingsItem != null) {
-                settingsItem.setChecked(true);
-            }
-        }
         if (mNavigationDrawer != null) {
             mNavigationDrawer.closeDrawers();
         }
diff --git a/ring-android/app/src/main/java/cx/ring/dependencyinjection/RingInjectionComponent.java b/ring-android/app/src/main/java/cx/ring/dependencyinjection/RingInjectionComponent.java
index 4a2c33c..48e3744 100755
--- a/ring-android/app/src/main/java/cx/ring/dependencyinjection/RingInjectionComponent.java
+++ b/ring-android/app/src/main/java/cx/ring/dependencyinjection/RingInjectionComponent.java
@@ -32,7 +32,7 @@
 import cx.ring.settings.SettingsPresenter;
 import cx.ring.share.ShareFragment;
 import cx.ring.share.SharePresenter;
-import cx.ring.views.MenuHeaderView;
+import cx.ring.navigation.RingNavigationFragment;
 import dagger.Component;
 
 @Singleton
@@ -40,7 +40,7 @@
 public interface RingInjectionComponent {
     void inject(RingApplication app);
 
-    void inject(MenuHeaderView view);
+    void inject(RingNavigationFragment view);
 
     void inject(AboutFragment fragment);
 
diff --git a/ring-android/app/src/main/java/cx/ring/fragments/SmartListFragment.java b/ring-android/app/src/main/java/cx/ring/fragments/SmartListFragment.java
index 5e0428f..e58b450 100644
--- a/ring-android/app/src/main/java/cx/ring/fragments/SmartListFragment.java
+++ b/ring-android/app/src/main/java/cx/ring/fragments/SmartListFragment.java
@@ -76,7 +76,7 @@
 import cx.ring.service.LocalService;
 import cx.ring.utils.BlockchainInputHandler;
 import cx.ring.utils.ClipboardHelper;
-import cx.ring.views.MenuHeaderView;
+import cx.ring.navigation.RingNavigationFragment;
 
 public class SmartListFragment extends Fragment implements SearchView.OnQueryTextListener,
         HomeActivity.Refreshable,
@@ -84,7 +84,7 @@
         Conversation.ConversationActionCallback,
         ClipboardHelper.ClipboardHelperCallback,
         LocalService.NameLookupCallback,
-        MenuHeaderView.MenuHeaderAccountSelectionListener {
+        RingNavigationFragment.MenuHeaderAccountSelectionListener {
     private static final String TAG = SmartListFragment.class.getSimpleName();
 
     private static final int USER_INPUT_DELAY = 300;
diff --git a/ring-android/app/src/main/java/cx/ring/navigation/NavigationAdapter.java b/ring-android/app/src/main/java/cx/ring/navigation/NavigationAdapter.java
new file mode 100644
index 0000000..dfc1fbb
--- /dev/null
+++ b/ring-android/app/src/main/java/cx/ring/navigation/NavigationAdapter.java
@@ -0,0 +1,119 @@
+/*
+ *  Copyright (C) 2016 Savoir-faire Linux Inc.
+ *
+ *  Author: Alexandre Lision <alexandre.lision@savoirfairelinux.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package cx.ring.navigation;
+
+import android.graphics.Color;
+import android.graphics.drawable.Drawable;
+import android.support.v4.graphics.drawable.DrawableCompat;
+import android.support.v7.widget.AppCompatImageView;
+import android.support.v7.widget.RecyclerView;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import butterknife.BindColor;
+import butterknife.BindView;
+import butterknife.ButterKnife;
+import cx.ring.R;
+
+class NavigationAdapter extends RecyclerView.Adapter<NavigationAdapter.NavigationItemView> {
+
+    private List<RingNavigationFragment.NavigationItem> mDataset;
+    private OnNavigationItemClicked mListener;
+    private int mItemSelected;
+
+    interface OnNavigationItemClicked {
+        void onNavigationItemClicked(int position);
+    }
+
+    NavigationAdapter(ArrayList<RingNavigationFragment.NavigationItem> menu) {
+        mDataset = menu;
+    }
+
+    class NavigationItemView extends RecyclerView.ViewHolder implements View.OnClickListener {
+
+        @BindView(R.id.navigation_item_icon)
+        AppCompatImageView icon;
+
+        @BindView(R.id.navigation_item_title)
+        TextView title;
+
+        @BindColor(R.color.color_primary_light)
+        int tintColor;
+
+        @BindColor(R.color.transparent_grey)
+        int backgroundHighlightColor;
+
+        NavigationItemView(View view) {
+            super(view);
+            ButterKnife.bind(this, view);
+            view.setOnClickListener(this);
+        }
+
+        @Override
+        public void onClick(View v) {
+            if (mListener != null) {
+                mItemSelected = getAdapterPosition();
+                setSelection(mItemSelected);
+                mListener.onNavigationItemClicked(mItemSelected);
+            }
+        }
+    }
+
+    void setSelection(int position) {
+        mItemSelected = position;
+        notifyDataSetChanged();
+    }
+
+    void setOnNavigationItemClickedListener(OnNavigationItemClicked listener) {
+        mListener = listener;
+    }
+
+    @Override
+    public NavigationItemView onCreateViewHolder(ViewGroup parent,
+                                                 int viewType) {
+        View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_menu, parent, false);
+        return new NavigationItemView(v);
+    }
+
+    @Override
+    public void onBindViewHolder(NavigationItemView holder, int position) {
+        holder.title.setText(mDataset.get(position).mResTitleId);
+        holder.icon.setImageResource(mDataset.get(position).mResImageId);
+
+        if (position == mItemSelected) {
+            Drawable wrapDrawable = DrawableCompat.wrap(holder.icon.getDrawable());
+            DrawableCompat.setTint(wrapDrawable, holder.tintColor);
+            holder.itemView.setBackgroundColor(holder.backgroundHighlightColor);
+        } else {
+            holder.itemView.setBackgroundColor(Color.TRANSPARENT);
+            Drawable wrapDrawable = DrawableCompat.wrap(holder.icon.getDrawable());
+            DrawableCompat.setTint(wrapDrawable, Color.BLACK);
+        }
+    }
+
+    @Override
+    public int getItemCount() {
+        return mDataset.size();
+    }
+}
\ No newline at end of file
diff --git a/ring-android/app/src/main/java/cx/ring/views/MenuHeaderView.java b/ring-android/app/src/main/java/cx/ring/navigation/RingNavigationFragment.java
similarity index 62%
rename from ring-android/app/src/main/java/cx/ring/views/MenuHeaderView.java
rename to ring-android/app/src/main/java/cx/ring/navigation/RingNavigationFragment.java
index 52f417e..2ccebd5 100644
--- a/ring-android/app/src/main/java/cx/ring/views/MenuHeaderView.java
+++ b/ring-android/app/src/main/java/cx/ring/navigation/RingNavigationFragment.java
@@ -17,22 +17,24 @@
  *  You should have received a copy of the GNU General Public License
  *  along with this program. If not, see <http://www.gnu.org/licenses/>.
  */
-package cx.ring.views;
+package cx.ring.navigation;
 
 import android.Manifest;
-import android.app.Activity;
 import android.app.AlertDialog;
-import android.content.Context;
+import android.app.Fragment;
 import android.content.DialogInterface;
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.graphics.Bitmap;
 import android.net.Uri;
+import android.os.Bundle;
 import android.provider.MediaStore;
+import android.support.annotation.Nullable;
 import android.support.v4.app.ActivityCompat;
 import android.support.v4.content.ContextCompat;
 import android.support.v4.content.res.ResourcesCompat;
-import android.util.AttributeSet;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
 import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -41,7 +43,6 @@
 import android.widget.AdapterView.OnItemSelectedListener;
 import android.widget.Button;
 import android.widget.EditText;
-import android.widget.FrameLayout;
 import android.widget.ImageButton;
 import android.widget.ImageView;
 import android.widget.Spinner;
@@ -74,14 +75,18 @@
 import ezvcard.property.Photo;
 import ezvcard.property.RawProperty;
 
-public class MenuHeaderView extends FrameLayout {
-    private static final String TAG = MenuHeaderView.class.getSimpleName();
+public class RingNavigationFragment extends Fragment implements NavigationAdapter.OnNavigationItemClicked {
+    private static final String TAG = RingNavigationFragment.class.getSimpleName();
 
     private AccountSelectionAdapter mAccountAdapter;
 
     @Inject
     StateService mStateService;
 
+    /***************
+     * Header views
+     ***************/
+
     @BindView(R.id.account_selection)
     Spinner mSpinnerAccounts;
 
@@ -97,28 +102,107 @@
     private ImageView mProfilePhoto;
     private VCard mVCardProfile;
 
+    /**************
+     * Menu views
+     **************/
+
+    @BindView(R.id.drawer_menu)
+    RecyclerView mMenuView;
+
+    private NavigationAdapter mMenuAdapter;
+    private OnNavigationSectionSelected mSectionListener;
     private List<WeakReference<MenuHeaderAccountSelectionListener>> mListeners;
 
-    public MenuHeaderView(Context context, AttributeSet attrs, int defStyle) {
-        super(context, attrs, defStyle);
-        initViews();
+    public interface OnNavigationSectionSelected {
+        void onNavigationSectionSelected(Section position);
     }
 
-    public MenuHeaderView(Context context, AttributeSet attrs) {
-        super(context, attrs);
-        initViews();
+    public interface MenuHeaderAccountSelectionListener {
+        void accountSelected(Account account);
     }
 
-    public MenuHeaderView(Context context) {
-        super(context);
+    /**
+     * Exposed enumeration listing app sections
+     */
+    public enum Section {
+        HOME(0),
+        MANAGE(1),
+        SETTINGS(2),
+        SHARE(3),
+        ABOUT(4);
 
-        if (context instanceof Activity) {
-            ((RingApplication)((Activity)context).getApplication()).getRingInjectionComponent().inject(this);
+        int position;
+
+        Section(int pos) {
+            position = pos;
         }
 
-        initViews();
+        public static Section valueOf(int sectionInt) {
+            for (Section section : Section.values()) {
+                if (section.position == sectionInt) {
+                    return section;
+                }
+            }
+            return HOME;
+        }
     }
 
+    /**
+     * Internal class describing navigation sections
+     */
+    class NavigationItem {
+        int mResTitleId;
+        int mResImageId;
+
+        NavigationItem(int resTitle, int resId) {
+            mResTitleId = resTitle;
+            mResImageId = resId;
+        }
+    }
+
+    @Nullable
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+        super.onCreateView(inflater, container, savedInstanceState);
+
+        View inflatedView = inflater.inflate(R.layout.frag_navigation, container, false);
+
+        ButterKnife.bind(this, inflatedView);
+
+        // dependency injection
+        ((RingApplication) getActivity().getApplication()).getRingInjectionComponent().inject(this);
+
+        mAccountAdapter = new AccountSelectionAdapter(getActivity(), new ArrayList<Account>());
+        mSpinnerAccounts.setAdapter(mAccountAdapter);
+        mVCardProfile = VCardUtils.loadLocalProfileFromDisk(getActivity());
+
+        updateUserView();
+
+        mListeners = new ArrayList<>();
+
+        setupNavigationMenu();
+        return inflatedView;
+    }
+
+    @Override
+    public void onViewCreated(View view, Bundle savedInstanceState) {
+        super.onViewCreated(view, savedInstanceState);
+        // TODO: Remove this when low level services are ready
+        ((HomeActivity) getActivity()).onNavigationViewReady();
+    }
+
+    public void selectSection(Section manage) {
+        mMenuAdapter.setSelection(manage.position);
+    }
+
+    @Override
+    public void onNavigationItemClicked(int position) {
+        if (mSectionListener != null) {
+            mSectionListener.onNavigationSectionSelected(Section.valueOf(position));
+        }
+    }
+
+
     public void setCallbacks(final LocalService service) {
         if (service != null) {
             mSpinnerAccounts.setOnItemSelectedListener(new OnItemSelectedListener() {
@@ -156,23 +240,21 @@
     }
 
     public void updateUserView() {
-        LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
         Log.d(TAG, "updateUserView");
-        if (null != inflater) {
-            mVCardProfile = VCardUtils.loadLocalProfileFromDisk(getContext());
-            if (!mVCardProfile.getPhotos().isEmpty()) {
-                Photo tmp = mVCardProfile.getPhotos().get(0);
-                mUserImage.setImageBitmap(CropImageUtils.cropImageToCircle(tmp.getData()));
-            } else {
-                mUserImage.setImageDrawable(ResourcesCompat.getDrawable(getResources(), R.drawable.ic_contact_picture, null));
-            }
-            mUserName.setText(mVCardProfile.getFormattedName().getValue());
-            Log.d(TAG, "User did change, updating user view.");
+        mVCardProfile = VCardUtils.loadLocalProfileFromDisk(getActivity());
+        if (!mVCardProfile.getPhotos().isEmpty()) {
+            Photo tmp = mVCardProfile.getPhotos().get(0);
+            mUserImage.setImageBitmap(CropImageUtils.cropImageToCircle(tmp.getData()));
+        } else {
+            mUserImage.setImageDrawable(ResourcesCompat.getDrawable(getResources(), R.drawable.ic_contact_picture, null));
         }
+        mUserName.setText(mVCardProfile.getFormattedName().getValue());
+        Log.d(TAG, "User did change, updating user view.");
+
     }
 
     public void updatePhoto(Uri uriImage) {
-        Bitmap imageProfile = ContactDetailsTask.loadProfilePhotoFromUri(getContext(), uriImage);
+        Bitmap imageProfile = ContactDetailsTask.loadProfilePhotoFromUri(getActivity(), uriImage);
         updatePhoto(imageProfile);
     }
 
@@ -181,37 +263,39 @@
         mProfilePhoto.setImageBitmap(CropImageUtils.cropImageToCircle(image));
     }
 
-    private void initViews() {
-        final LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-        View inflatedView = inflater.inflate(R.layout.frag_menu_header, this);
+    @OnClick(R.id.addaccount_btn)
+    public void addNewAccount(View sender) {
+        getActivity().startActivity(new Intent(getActivity(), AccountWizard.class));
+    }
 
-        ButterKnife.bind(this, inflatedView);
+    private void setupNavigationMenu() {
+        mMenuView.setHasFixedSize(true);
+        LinearLayoutManager mLayoutManager2 = new LinearLayoutManager(getActivity());
+        mMenuView.setLayoutManager(mLayoutManager2);
 
-        mNewAccountBtn.setOnClickListener(new View.OnClickListener() {
-            @Override
-            public void onClick(View v) {
-                getContext().startActivity(new Intent(v.getContext(), AccountWizard.class));
-            }
-        });
+        ArrayList<NavigationItem> menu = new ArrayList<>();
+        menu.add(0, new NavigationItem(R.string.menu_item_home, R.drawable.ic_home_black));
+        menu.add(1, new NavigationItem(R.string.menu_item_accounts, R.drawable.ic_group_black));
+        menu.add(2, new NavigationItem(R.string.menu_item_settings, R.drawable.ic_settings_black));
+        menu.add(3, new NavigationItem(R.string.menu_item_share, R.drawable.ic_share_black));
+        menu.add(4, new NavigationItem(R.string.menu_item_about, R.drawable.ic_info_black));
 
-        mAccountAdapter = new AccountSelectionAdapter(inflater.getContext(), new ArrayList<Account>());
+        mMenuAdapter = new NavigationAdapter(menu);
+        mMenuView.setAdapter(mMenuAdapter);
+        mMenuAdapter.setOnNavigationItemClickedListener(this);
+    }
 
-        mSpinnerAccounts.setAdapter(mAccountAdapter);
-
-        mVCardProfile = VCardUtils.loadLocalProfileFromDisk(getContext());
-
-        updateUserView();
-
-        mListeners = new ArrayList<>();
+    public void setNavigationSectionSelectedListener(OnNavigationSectionSelected listener) {
+        mSectionListener = listener;
     }
 
     @OnClick(R.id.profile_container)
     public void profileContainerClicked() {
         Log.d(TAG, "Click on the edit profile");
-        AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
+        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
         builder.setTitle(R.string.profile);
 
-        LayoutInflater inflater = ((Activity) getContext()).getLayoutInflater();
+        LayoutInflater inflater = LayoutInflater.from(getActivity());
         ViewGroup view = (ViewGroup) inflater.inflate(R.layout.dialog_profile, null);
 
         final EditText editText = (EditText) view.findViewById(R.id.user_name);
@@ -220,16 +304,16 @@
         mProfilePhoto.setImageDrawable(mUserImage.getDrawable());
 
         ImageButton cameraView = (ImageButton) view.findViewById(R.id.camera);
-        cameraView.setOnClickListener(new OnClickListener() {
+        cameraView.setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View v) {
-                boolean hasPermission = ContextCompat.checkSelfPermission(getContext(), Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED &&
-                        ContextCompat.checkSelfPermission(getContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED;
+                boolean hasPermission = ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED &&
+                        ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED;
                 if (hasPermission) {
                     Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
-                    ((Activity) getContext()).startActivityForResult(intent, HomeActivity.REQUEST_CODE_PHOTO);
+                    getActivity().startActivityForResult(intent, HomeActivity.REQUEST_CODE_PHOTO);
                 } else {
-                    ActivityCompat.requestPermissions((Activity) getContext(),
+                    ActivityCompat.requestPermissions(getActivity(),
                             new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE},
                             HomeActivity.REQUEST_PERMISSION_CAMERA);
                 }
@@ -237,15 +321,15 @@
         });
 
         ImageButton gallery = (ImageButton) view.findViewById(R.id.gallery);
-        gallery.setOnClickListener(new OnClickListener() {
+        gallery.setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View v) {
-                boolean hasPermission = ContextCompat.checkSelfPermission(getContext(), Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED;
+                boolean hasPermission = ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED;
                 if (hasPermission) {
                     Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
-                    ((Activity) getContext()).startActivityForResult(intent, HomeActivity.REQUEST_CODE_GALLERY);
+                    getActivity().startActivityForResult(intent, HomeActivity.REQUEST_CODE_GALLERY);
                 } else {
-                    ActivityCompat.requestPermissions((Activity) getContext(),
+                    ActivityCompat.requestPermissions(getActivity(),
                             new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
                             HomeActivity.REQUEST_PERMISSION_READ_STORAGE);
                 }
@@ -266,7 +350,7 @@
             public void onClick(DialogInterface dialog, int which) {
                 String username = editText.getText().toString().trim();
                 if (username.isEmpty()) {
-                    username = getContext().getString(R.string.unknown);
+                    username = getActivity().getString(R.string.unknown);
                 }
                 mVCardProfile.setFormattedName(new FormattedName(username));
 
@@ -279,7 +363,7 @@
                 }
 
                 mVCardProfile.removeProperties(RawProperty.class);
-                VCardUtils.saveLocalProfileToDisk(mVCardProfile, getContext());
+                VCardUtils.saveLocalProfileToDisk(mVCardProfile, getActivity());
                 updateUserView();
             }
         });
@@ -292,6 +376,7 @@
     }
 
     public void updateAccounts(List<Account> accounts) {
+
         if (accounts.isEmpty()) {
             mNewAccountBtn.setVisibility(View.VISIBLE);
             mSpinnerAccounts.setVisibility(View.GONE);
@@ -310,8 +395,4 @@
             mStateService.setCurrentAccount(getSelectedAccount());
         }
     }
-
-    public interface MenuHeaderAccountSelectionListener {
-        void accountSelected(Account account);
-    }
 }
diff --git a/ring-android/app/src/main/res/layout/activity_home.xml b/ring-android/app/src/main/res/layout/activity_home.xml
index 71646e5..6dc9c89 100644
--- a/ring-android/app/src/main/res/layout/activity_home.xml
+++ b/ring-android/app/src/main/res/layout/activity_home.xml
@@ -40,37 +40,36 @@
             android:layout_alignParentStart="true"
             android:layout_alignParentTop="true"
             android:background="@color/color_primary_light"
+            android:elevation="@dimen/toolbar_elevation"
             android:minHeight="?attr/actionBarSize"
             android:popupTheme="@style/Theme.AppCompat.Light.NoActionBar"
             android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
             android:titleTextAppearance="@style/ToolbarTitle"
             app:contentInsetStart="@dimen/toolbar_content_inset"
-            android:elevation="@dimen/toolbar_elevation"
             app:elevation="@dimen/toolbar_elevation"
-            app:titleTextAppearance="@style/ToolbarTitle"/>
+            app:titleTextAppearance="@style/ToolbarTitle" />
 
         <LinearLayout
             android:id="@+id/toolbar_spacer"
             android:layout_width="match_parent"
             android:layout_height="72sp"
-            android:orientation="horizontal"
-            android:elevation="@dimen/toolbar_elevation"
             android:layout_below="@+id/main_toolbar"
             android:background="@color/color_primary_light"
-            android:visibility="gone"
+            android:elevation="@dimen/toolbar_elevation"
+            android:gravity="center_vertical"
+            android:orientation="horizontal"
             android:paddingLeft="@dimen/toolbar_content_inset"
-            android:gravity="center_vertical">
+            android:visibility="gone">
 
-                <TextView
-                    android:id="@+id/toolbar_spacer_title"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:text="@string/menu_item_accounts"
-                    style="@style/ToolbarTitle"
-                    android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
-                    />
+            <TextView
+                android:id="@+id/toolbar_spacer_title"
+                style="@style/ToolbarTitle"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/menu_item_accounts"
+                android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" />
 
-            </LinearLayout>
+        </LinearLayout>
 
         <FrameLayout
             android:id="@+id/main_frame"
@@ -109,7 +108,13 @@
         android:fitsSystemWindows="true"
         android:theme="@style/AppThemeBase"
         android:windowBackground="@color/white"
-        app:itemTextColor="?android:textColorPrimary"
-        app:menu="@menu/drawer" />
+        app:itemTextColor="?android:textColorPrimary">
+
+        <FrameLayout
+            android:id="@+id/navigation_container"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content" />
+
+    </android.support.design.widget.NavigationView>
 
 </android.support.v4.widget.DrawerLayout>
\ No newline at end of file
diff --git a/ring-android/app/src/main/res/layout/frag_menu_header.xml b/ring-android/app/src/main/res/layout/frag_menu_header.xml
deleted file mode 100644
index 6f0a299..0000000
--- a/ring-android/app/src/main/res/layout/frag_menu_header.xml
+++ /dev/null
@@ -1,86 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<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="wrap_content"
-    android:background="@color/color_primary_dark"
-    android:paddingLeft="16dp"
-    android:paddingRight="16dp"
-    android:paddingTop="30dp"
-    android:theme="@style/MenuHeader">
-
-    <RelativeLayout
-        android:id="@+id/profile_container"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content">
-
-        <ImageView
-            android:id="@+id/user_photo"
-            android:layout_width="80dp"
-            android:layout_height="80dp"
-            android:layout_alignParentTop="true"
-            android:layout_centerHorizontal="true"
-            tools:src="@drawable/ic_contact_picture" />
-
-        <View
-            android:id="@+id/anchor"
-            android:layout_width="20dp"
-            android:layout_height="20dp"
-            android:layout_alignBottom="@+id/user_photo"
-            android:layout_centerHorizontal="true" />
-
-        <android.support.design.widget.FloatingActionButton
-            android:id="@+id/edit_profile"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_alignTop="@+id/anchor"
-            android:layout_toEndOf="@+id/anchor"
-            android:layout_toRightOf="@+id/anchor"
-            android:src="@drawable/ic_action_edit"
-            app:backgroundTint="@color/transparent_light"
-            app:fabSize="mini" />
-
-        <TextView
-            android:id="@+id/user_name"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_below="@+id/edit_profile"
-            android:layout_centerHorizontal="true"
-            android:layout_marginBottom="8dp"
-            android:layout_marginTop="8dp"
-            android:maxLines="1"
-            android:textColor="@color/white"
-            android:textSize="20sp"
-            android:textStyle="bold"
-            tools:text="Username" />
-
-    </RelativeLayout>
-
-    <Spinner
-        android:id="@+id/account_selection"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_alignParentEnd="true"
-        android:layout_alignParentLeft="true"
-        android:layout_alignParentRight="true"
-        android:layout_alignParentStart="true"
-        android:layout_below="@+id/profile_container"
-        android:layout_toEndOf="@+id/profile_container"
-        android:layout_toRightOf="@+id/profile_container"
-        android:visibility="visible"
-        tools:listitem="@layout/item_account_selected" />
-
-    <Button
-        android:id="@+id/addaccount_btn"
-        style="@style/Widget.AppCompat.Button.Borderless"
-        android:layout_width="wrap_content"
-        android:layout_height="72dp"
-        android:layout_alignParentEnd="true"
-        android:layout_alignParentLeft="true"
-        android:layout_alignParentRight="true"
-        android:layout_alignParentStart="true"
-        android:layout_below="@+id/profile_container"
-        android:text="@string/action_create"
-        android:visibility="gone" />
-</RelativeLayout>
\ No newline at end of file
diff --git a/ring-android/app/src/main/res/layout/frag_navigation.xml b/ring-android/app/src/main/res/layout/frag_navigation.xml
new file mode 100644
index 0000000..d894b9c
--- /dev/null
+++ b/ring-android/app/src/main/res/layout/frag_navigation.xml
@@ -0,0 +1,116 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<android.support.v4.widget.NestedScrollView 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="wrap_content"
+    android:theme="@style/AppThemeBase">
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="vertical">
+
+        <RelativeLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:background="@color/color_primary_dark"
+            android:paddingLeft="16dp"
+            android:paddingRight="16dp"
+            android:paddingTop="30dp"
+            android:theme="@style/MenuHeader">
+
+            <RelativeLayout
+                android:id="@+id/profile_container"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content">
+
+                <ImageView
+                    android:id="@+id/user_photo"
+                    android:layout_width="80dp"
+                    android:layout_height="80dp"
+                    android:layout_alignParentTop="true"
+                    android:layout_centerHorizontal="true"
+                    tools:src="@drawable/ic_contact_picture" />
+
+                <View
+                    android:id="@+id/anchor"
+                    android:layout_width="20dp"
+                    android:layout_height="20dp"
+                    android:layout_alignBottom="@+id/user_photo"
+                    android:layout_centerHorizontal="true" />
+
+                <android.support.design.widget.FloatingActionButton
+                    android:id="@+id/edit_profile"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_alignTop="@+id/anchor"
+                    android:layout_toEndOf="@+id/anchor"
+                    android:layout_toRightOf="@+id/anchor"
+                    android:src="@drawable/ic_action_edit"
+                    app:backgroundTint="@color/transparent_light"
+                    app:fabSize="mini" />
+
+                <TextView
+                    android:id="@+id/user_name"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_below="@+id/edit_profile"
+                    android:layout_centerHorizontal="true"
+                    android:layout_marginBottom="8dp"
+                    android:layout_marginTop="8dp"
+                    android:maxLines="1"
+                    android:textColor="@color/white"
+                    android:textSize="20sp"
+                    android:textStyle="bold"
+                    tools:text="Username" />
+
+            </RelativeLayout>
+
+            <Spinner
+                android:id="@+id/account_selection"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_alignParentEnd="true"
+                android:layout_alignParentLeft="true"
+                android:layout_alignParentRight="true"
+                android:layout_alignParentStart="true"
+                android:layout_below="@+id/profile_container"
+                android:layout_toEndOf="@+id/profile_container"
+                android:layout_toRightOf="@+id/profile_container"
+                android:visibility="visible"
+                tools:listitem="@layout/item_account_selected" />
+
+            <Button
+                android:id="@+id/addaccount_btn"
+                style="@style/Widget.AppCompat.Button.Borderless"
+                android:layout_width="wrap_content"
+                android:layout_height="72dp"
+                android:layout_alignParentEnd="true"
+                android:layout_alignParentLeft="true"
+                android:layout_alignParentRight="true"
+                android:layout_alignParentStart="true"
+                android:layout_below="@+id/profile_container"
+                android:text="@string/action_create"
+                android:visibility="gone" />
+        </RelativeLayout>
+
+        <FrameLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:paddingTop="8dp">
+
+            <android.support.v7.widget.RecyclerView
+                android:id="@+id/drawer_menu"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:nestedScrollingEnabled="false"
+                tools:targetApi="lollipop" />
+
+        </FrameLayout>
+
+    </LinearLayout>
+</android.support.v4.widget.NestedScrollView>
+
+
diff --git a/ring-android/app/src/main/res/layout/item_menu.xml b/ring-android/app/src/main/res/layout/item_menu.xml
index 340fd37..6de729d 100644
--- a/ring-android/app/src/main/res/layout/item_menu.xml
+++ b/ring-android/app/src/main/res/layout/item_menu.xml
@@ -1,12 +1,36 @@
 <?xml version="1.0" encoding="utf-8"?>
-<TextView xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/menu_title_categorie"
+
+<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="?android:attr/listPreferredItemHeight"
-    android:gravity="center_vertical"
-    android:paddingBottom="10dip"
-    android:paddingLeft="15dip"
-    android:paddingTop="10dip"
-    android:background="?android:attr/activatedBackgroundIndicator"
-    android:textColor="@color/black"
-    android:textSize="20sp" />
+    android:layout_height="48dp"
+    android:background="?android:attr/selectableItemBackground"
+    android:drawSelectorOnTop="true">
+
+    <android.support.v7.widget.AppCompatImageView
+        android:id="@+id/navigation_item_icon"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_centerVertical="true"
+        android:layout_marginLeft="16dp"
+        android:layout_marginStart="16dp"
+        android:alpha="0.54"
+        tools:src="@drawable/ic_home_black" />
+
+    <TextView
+        android:id="@+id/navigation_item_title"
+        android:layout_width="match_parent"
+        android:layout_height="?android:attr/listPreferredItemHeight"
+        android:layout_centerVertical="true"
+        android:layout_marginEnd="16dp"
+        android:layout_marginLeft="72dp"
+        android:layout_marginRight="16dp"
+        android:layout_marginStart="72dp"
+        android:alpha="0.87"
+        android:fontFamily="sans-serif-medium"
+        android:gravity="center_vertical"
+        android:textColor="@color/black"
+        android:textSize="14sp"
+        tools:text="Home" />
+
+</RelativeLayout>
diff --git a/ring-android/app/src/main/res/menu/drawer.xml b/ring-android/app/src/main/res/menu/drawer.xml
deleted file mode 100644
index a58603c..0000000
--- a/ring-android/app/src/main/res/menu/drawer.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<menu xmlns:android="http://schemas.android.com/apk/res/android">
-    <group android:checkableBehavior="single">
-        <item
-            android:id="@+id/menuitem_home"
-            android:checked="true"
-            android:icon="@drawable/ic_home_black"
-            android:title="@string/menu_item_home"/>
-        <item
-            android:id="@+id/menuitem_accounts"
-            android:icon="@drawable/ic_group_black"
-            android:title="@string/menu_item_accounts"/>
-        <item
-            android:id="@+id/menuitem_prefs"
-            android:icon="@drawable/ic_settings_black"
-            android:title="@string/menu_item_settings"/>
-        <item
-            android:id="@+id/menuitem_share"
-            android:icon="@drawable/ic_share_black"
-            android:title="@string/menu_item_share"/>
-        <item
-            android:id="@+id/menuitem_about"
-            android:icon="@drawable/ic_info_black"
-            android:title="@string/menu_item_about"/>
-    </group>
-</menu>
\ No newline at end of file