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