Updated 2 February 2017
We all know that we can create so many custom drawables in android but when it comes for a dynamic one we still got the goosebumps. So last week I got stuck in one such issue where I want to show a drawable next to my menu item in navigation drawer.
The drawable was a simple one in which I have to create a circular square and in the center there will be the first character of the menu item text. I know its easier to create an image for them and add it but my menu item is the dynamic one coming from server so it can probably change with some changes on server. I know now you will think to get the image from server and put the image in the server but I don’t think that’s a optimal solution as for this simple work my designer have to create a new image each time something is changed on server.
That is why I took the hard road and creates a dynamic drawable for my need and I can tell you that it was pretty much simpler. So I had to make a view like
I started with creating a Drawable class with name “DrawerIcon.java“. It is responsible to create the icon we just have to pass all the required data to this class’s
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
class DrawerIcon extends Drawable { Context mContext; private String firstCharacter; private Paint mTextPaint; private DrawerIcon(Context ctx) throws ClassCastException{ this.mContext = ctx; mTextPaint = new Paint(Paint.FAKE_BOLD_TEXT_FLAG); mTextPaint.setColor(Color.GRAY); } static LayerDrawable createIcon(Context context, LayerDrawable icon, char character){ DrawerIcon drawerIcon; Drawable reuse = icon.findDrawableByLayerId(R.id.text); if (reuse != null && reuse instanceof DrawerIcon) { drawerIcon = (DrawerIcon) reuse; } else { drawerIcon = new DrawerIcon(context); } drawerIcon.setText(character); icon.mutate(); icon.setDrawableByLayerId(R.id.text, drawerIcon); return icon; } private void setText(char character) { firstCharacter = Character.toString(character); invalidateSelf(); } @Override public void setAlpha(int alpha) { } @Override public void draw(@NonNull Canvas canvas) { Rect bounds = getBounds(); mTextPaint.setTextSize(bounds.height()-20); mTextPaint.setTextAlign(Paint.Align.CENTER); canvas.drawText(firstCharacter, (bounds.width()/2) , bounds.bottom-10, mTextPaint); } @Override public void setColorFilter(ColorFilter colorFilter) { } @Override public int getOpacity() { return PixelFormat.UNKNOWN; } } |
Now from the your activity where you have created the navigation drawer you have to call the static method createIcon() and rest it will handle itself.
1 2 3 4 5 6 |
NavigationView navigationView = (NavigationView) findViewById(R.id.navigation_view); Menu languageMenu = navigationView.getMenu(); String languageEnglish = "English"; MenuItem item = languageMenu.add(languageEnglish); LayerDrawable drawer = (LayerDrawable) ContextCompat.getDrawable(this, R.drawable.drawer_icon_drawable); item.setIcon(DrawerIcon.createIcon(this, drawer, languageEnglish.charAt(0))); |
The LayerDrawable drawer_icon_drawable in defined in drawable folder as
1 2 3 4 5 6 7 8 9 10 11 12 |
<?xml version="1.0" encoding="utf-8"?> <layer-list xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="@drawable/rounded_rectangle_grey"/> <!-- Placeholder drawable so android:drawable isn't null --> <item android:id="@+id/text" android:drawable="@color/white" android:gravity="center"/> </layer-list> |
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> <corners android:radius="5dp"/> <solid android:color="#FFFFFF"> </solid> <stroke android:width="1dp" android:color="@android:color/darker_gray"> </stroke> </shape> |
And that is all you will have the required view ready for you.
If you have more details or questions, you can reply to the received confirmation email.
Back to Home
1 comments