How to implement badges in the Navigation Drawer menu ?
Sample badges: 10 and 99+ (picture)
In the badge I want to display quantitative data from the database. Created the markup:
<LinearLayout android:orientation="horizontal" android:layout_width="0dp" android:layout_height="match_parent" android:gravity="start" android:layout_weight="85" > <TextView android:id="@+id/item_name" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_marginLeft="16dp" android:layout_marginStart="16dp" android:layout_marginRight="16dp" android:drawablePadding="16dp" android:layout_marginEnd="16dp" android:textSize="14sp" android:gravity="center_vertical" android:textColor="@color/myTextPrimaryColor" /> </LinearLayout> <LinearLayout android:orientation="horizontal" android:layout_width="0dp" android:layout_height="match_parent" android:layout_margin="16dp" android:gravity="end" android:layout_weight="15" > <TextView android:id="@+id/badge" android:layout_width="fill_parent" android:layout_height="fill_parent" android:gravity="end|center_vertical" android:textSize="14sp" /> </LinearLayout> So add new items to the list. File: NavigationDrawerFregment
public List<NavigationItem> getMenu() { List<NavigationItem> items = new ArrayList<NavigationItem>(); String[] nav_items = getResources().getStringArray(R.array.views_array); items.add(new NavigationItem(nav_items[0], getResources().getDrawable(R.drawable.ic_menu_check))); items.add(new NavigationItem(nav_items[1], getResources().getDrawable(R.drawable.ic_menu_check))); items.add(new NavigationItem(nav_items[2], getResources().getDrawable(R.drawable.ic_menu_check))); items.add(new NavigationItem(nav_items[3], getResources().getDrawable(R.drawable.ic_add_tooth))); items.add(new NavigationItem(nav_items[4], getResources().getDrawable(R.drawable.ic_add_tooth_doc))); items.add(new NavigationItem(nav_items[5], getResources().getDrawable(R.drawable.ic_menu_check))); return items; } As a result, I have updated markup, but I do not know how to display the desired menu item.
NavigationItem code:
public class NavigationItem { private String mText; private Drawable mDrawable; public NavigationItem(String text, Drawable drawable) { mText = text; mDrawable = drawable; } public String getText() { return mText; } public void setText(String text) { mText = text; } public Drawable getDrawable() { return mDrawable; } public void setDrawable(Drawable drawable) { mDrawable = drawable; } }
UPD2 - my NavigationDrawerAdapter
public class NavigationDrawerAdapter extends RecyclerView.Adapter<NavigationDrawerAdapter.ViewHolder> { private List<NavigationItem> mData; private NavigationDrawerCallbacks mNavigationDrawerCallbacks; private View mSelectedView; private int mSelectedPosition; private TextView badge_tv; public NavigationDrawerAdapter(List<NavigationItem> data) { mData = data; } public NavigationDrawerCallbacks getNavigationDrawerCallbacks() { return mNavigationDrawerCallbacks; } public void setNavigationDrawerCallbacks(NavigationDrawerCallbacks navigationDrawerCallbacks) { mNavigationDrawerCallbacks = navigationDrawerCallbacks; } @Override public NavigationDrawerAdapter.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) { View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.drawer_row, viewGroup, false); final ViewHolder viewHolder = new ViewHolder(v); viewHolder.itemView.setClickable(true); viewHolder.itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (mSelectedView != null) { mSelectedView.setSelected(false); } mSelectedPosition = viewHolder.getAdapterPosition(); v.setSelected(true); mSelectedView = v; if (mNavigationDrawerCallbacks != null) mNavigationDrawerCallbacks.onNavigationDrawerItemSelected(viewHolder.getAdapterPosition()); } } ); viewHolder.itemView.setBackgroundResource(R.drawable.row_selector); badge_tv = (TextView) viewHolder.itemView.findViewById(R.id.badge); return viewHolder; } @Override public void onBindViewHolder(NavigationDrawerAdapter.ViewHolder viewHolder, int i) { viewHolder.textView.setText(mData.get(i).getText()); viewHolder.textView.setCompoundDrawablesWithIntrinsicBounds(mData.get(i).getDrawable(), null, null, null); if (mSelectedPosition == i) { if (mSelectedView != null) { mSelectedView.setSelected(false); } mSelectedPosition = i; mSelectedView = viewHolder.itemView; mSelectedView.setSelected(true); } if (mData.get(i).getBadge().equals("")) badge_tv.setVisibility(View.INVISIBLE); else { badge_tv.setVisibility(View.VISIBLE); badge_tv.setText(mData.get(i).getBadge()); } } public void setBadge(int count , int pos){ mData.get(pos).setBadge(String.valueOf(count)) ; notifyDataSetChanged(); } public void dropBage(int pos){ // убрать бэйдж из пункта pos mData.get(pos).setBadge(""); notifyDataSetChanged(); } public void selectPosition(int position) { mSelectedPosition = position; notifyItemChanged(position); } @Override public int getItemCount() { return mData != null ? mData.size() : 0; } public static class ViewHolder extends RecyclerView.ViewHolder { public TextView textView; public ViewHolder(View itemView) { super(itemView); textView = (TextView) itemView.findViewById(R.id.item_name); } } UPD3 - NavigationDrawerFragment
public class NavigationDrawerFragment extends Fragment implements NavigationDrawerCallbacks { /** * Remember the position of the selected item. */ private static final String STATE_SELECTED_POSITION = "selected_navigation_drawer_position"; /** * Per the design guidelines, you should show the drawer on launch until the user manually * expands it. This shared preference tracks this. */ private static final String PREF_USER_LEARNED_DRAWER = "navigation_drawer_learned"; /** * A pointer to the current callbacks instance (the Activity). */ private NavigationDrawerCallbacks mCallbacks; /** * Helper component that ties the action bar to the navigation drawer. */ private ActionBarDrawerToggle mActionBarDrawerToggle; private DrawerLayout mDrawerLayout; private RecyclerView mDrawerList; private View mFragmentContainerView; private int mCurrentSelectedPosition = 0; private boolean mFromSavedInstanceState; private boolean mUserLearnedDrawer; String LOG_TAG = "myLogs"; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Read in the flag indicating whether or not the user has demonstrated awareness of the // drawer. See PREF_USER_LEARNED_DRAWER for details. SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getActivity()); mUserLearnedDrawer = sp.getBoolean(PREF_USER_LEARNED_DRAWER, false); if (savedInstanceState != null) { mCurrentSelectedPosition = savedInstanceState.getInt(STATE_SELECTED_POSITION); mFromSavedInstanceState = true; } } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_navigation_drawer, container, false); mDrawerList = (RecyclerView) view.findViewById(R.id.drawerList); LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity()); layoutManager.setOrientation(LinearLayoutManager.VERTICAL); mDrawerList.setLayoutManager(layoutManager); mDrawerList.setHasFixedSize(true); final List<NavigationItem> navigationItems = getMenu(); NavigationDrawerAdapter adapter = new NavigationDrawerAdapter(navigationItems); adapter.setNavigationDrawerCallbacks(this); mDrawerList.setAdapter(adapter); selectItem(mCurrentSelectedPosition); return view; } public boolean isDrawerOpen() { return mDrawerLayout != null && mDrawerLayout.isDrawerOpen(mFragmentContainerView); } public ActionBarDrawerToggle getActionBarDrawerToggle() { return mActionBarDrawerToggle; } public DrawerLayout getDrawerLayout() { return mDrawerLayout; } @Override public void onNavigationDrawerItemSelected(int position) { selectItem(position); } public List<NavigationItem> getMenu() { List<NavigationItem> items = new ArrayList<NavigationItem>(); String[] nav_items = getResources().getStringArray(R.array.views_array); items.add(new NavigationItem(nav_items[0], getResources().getDrawable(R.drawable.ic_menu_check))); items.add(new NavigationItem(nav_items[1], getResources().getDrawable(R.drawable.ic_menu_check))); items.add(new NavigationItem(nav_items[2], getResources().getDrawable(R.drawable.ic_menu_check))); items.add(new NavigationItem(nav_items[3], getResources().getDrawable(R.drawable.ic_menu_check))); items.add(new NavigationItem(nav_items[4], getResources().getDrawable(R.drawable.ic_menu_check))); items.add(new NavigationItem(nav_items[5], getResources().getDrawable(R.drawable.ic_menu_check))); return items; } /** * Users of this fragment must call this method to set up the navigation drawer interactions. * * @param fragmentId The android:id of this fragment in its activity's layout. * @param drawerLayout The DrawerLayout containing this fragment's UI. * @param toolbar The Toolbar of the activity. */ public void setup(int fragmentId, DrawerLayout drawerLayout, Toolbar toolbar) { mFragmentContainerView = getActivity().findViewById(fragmentId); mDrawerLayout = drawerLayout; mDrawerLayout.setStatusBarBackgroundColor(getResources().getColor(R.color.myPrimaryDarkColor)); mActionBarDrawerToggle = new ActionBarDrawerToggle(getActivity(), mDrawerLayout, toolbar, R.string.drawer_open, R.string.drawer_close) { @Override public void onDrawerClosed(View drawerView) { super.onDrawerClosed(drawerView); if (!isAdded()) return; getActivity().invalidateOptionsMenu(); // calls onPrepareOptionsMenu() } @Override public void onDrawerOpened(View drawerView) { super.onDrawerOpened(drawerView); if (!isAdded()) return; if (!mUserLearnedDrawer) { mUserLearnedDrawer = true; SharedPreferences sp = PreferenceManager .getDefaultSharedPreferences(getActivity()); sp.edit().putBoolean(PREF_USER_LEARNED_DRAWER, true).apply(); } getActivity().invalidateOptionsMenu(); // calls onPrepareOptionsMenu() Log.v(LOG_TAG, "dr opened"); InputMethodManager inputMethodManager = (InputMethodManager) getActivity().getSystemService(Activity.INPUT_METHOD_SERVICE); inputMethodManager.hideSoftInputFromWindow(getActivity().getCurrentFocus().getWindowToken(), 0); } }; // If the user hasn't 'learned' about the drawer, open it to introduce them to the drawer, // per the navigation drawer design guidelines. if (!mUserLearnedDrawer && !mFromSavedInstanceState) { mDrawerLayout.openDrawer(mFragmentContainerView); } // Defer code dependent on restoration of previous instance state. mDrawerLayout.post(new Runnable() { @Override public void run() { mActionBarDrawerToggle.syncState(); } }); mDrawerLayout.setDrawerListener(mActionBarDrawerToggle); } private void selectItem(int position) { mCurrentSelectedPosition = position; if (mDrawerLayout != null) { mDrawerLayout.closeDrawer(mFragmentContainerView); } if (mCallbacks != null) { mCallbacks.onNavigationDrawerItemSelected(position); } ((NavigationDrawerAdapter) mDrawerList.getAdapter()).selectPosition(position); } public void openDrawer() { mDrawerLayout.openDrawer(mFragmentContainerView); } public void closeDrawer() { mDrawerLayout.closeDrawer(mFragmentContainerView); } @Override public void onAttach(Activity activity) { super.onAttach(activity); try { mCallbacks = (NavigationDrawerCallbacks) activity; } catch (ClassCastException e) { throw new ClassCastException("Activity must implement NavigationDrawerCallbacks."); } } @Override public void onDetach() { super.onDetach(); mCallbacks = null; } @Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putInt(STATE_SELECTED_POSITION, mCurrentSelectedPosition); } @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); // Forward the new configuration the drawer toggle component. mActionBarDrawerToggle.onConfigurationChanged(newConfig); } public void setUserData(String user, String email, Bitmap avatar) { ImageView avatarContainer = (ImageView) mFragmentContainerView.findViewById(R.id.imgAvatar); ((TextView) mFragmentContainerView.findViewById(R.id.txtUserEmail)).setText(email); ((TextView) mFragmentContainerView.findViewById(R.id.txtUsername)).setText(user); avatarContainer.setImageDrawable(new RoundImage(avatar)); } public View getGoogleDrawer() { return mFragmentContainerView.findViewById(R.id.googleDrawer); } public static class RoundImage extends Drawable { private final Bitmap mBitmap; private final Paint mPaint; private final RectF mRectF; private final int mBitmapWidth; private final int mBitmapHeight; public RoundImage(Bitmap bitmap) { mBitmap = bitmap; mRectF = new RectF(); mPaint = new Paint(); mPaint.setAntiAlias(true); mPaint.setDither(true); final BitmapShader shader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); mPaint.setShader(shader); mBitmapWidth = mBitmap.getWidth(); mBitmapHeight = mBitmap.getHeight(); } @Override public void draw(Canvas canvas) { canvas.drawOval(mRectF, mPaint); } @Override protected void onBoundsChange(Rect bounds) { super.onBoundsChange(bounds); mRectF.set(bounds); } @Override public void setAlpha(int alpha) { if (mPaint.getAlpha() != alpha) { mPaint.setAlpha(alpha); invalidateSelf(); } } @Override public void setColorFilter(ColorFilter cf) { mPaint.setColorFilter(cf); } @Override public int getOpacity() { return PixelFormat.TRANSLUCENT; } @Override public int getIntrinsicWidth() { return mBitmapWidth; } @Override public int getIntrinsicHeight() { return mBitmapHeight; } public void setAntiAlias(boolean aa) { mPaint.setAntiAlias(aa); invalidateSelf(); } @Override public void setFilterBitmap(boolean filter) { mPaint.setFilterBitmap(filter); invalidateSelf(); } @Override public void setDither(boolean dither) { mPaint.setDither(dither); invalidateSelf(); } public Bitmap getBitmap() { return mBitmap; } } }
proguardcan remove unused classes from the release assembly. - pavlofff