Add button with a counter into the toolbar

后端 未结 3 1759
无人共我
无人共我 2021-01-16 22:56

My ToolBar

How can I make counter under the cart?

3条回答
  •  轮回少年
    2021-01-16 23:22

    This should be the approach to achieve this

    • Create a BadgeDrawable class that draws a count of notification plus an eye-popping red background circle (like in the screenshot ).
    • Define a LayerDrawable in XML to set as the android:icon of our MenuItem. The bottom layer of the LayerDrawable is the MenuItem's icon (typically a .png), and the top layer is the BadgeDrawable.
    • Simulate querying the count of notifications in our Activity, update the BadgeDrawable's count, then call Activity#invalidateOptionsMenu() to force the ActionBar Menu to refresh.

    Output will be

    BadgeDrawable.java

    public class BadgeDrawable extends Drawable {
    
        private float mTextSize;
        private Paint mBadgePaint;
        private Paint mTextPaint;
        private Rect mTxtRect = new Rect();
    
        private String mCount = "";
        private boolean mWillDraw = false;
    
        public BadgeDrawable(Context context) {
            mTextSize = context.getResources().getDimension(R.dimen.badge_text_size);
    
            mBadgePaint = new Paint();
            mBadgePaint.setColor(Color.RED);
            mBadgePaint.setAntiAlias(true);
            mBadgePaint.setStyle(Paint.Style.FILL);
    
            mTextPaint = new Paint();
            mTextPaint.setColor(Color.WHITE);
            mTextPaint.setTypeface(Typeface.DEFAULT_BOLD);
            mTextPaint.setTextSize(mTextSize);
            mTextPaint.setAntiAlias(true);
            mTextPaint.setTextAlign(Paint.Align.CENTER);
        }
    
        @Override
        public void draw(Canvas canvas) {
            if (!mWillDraw) {
                return;
            }
    
            Rect bounds = getBounds();
            float width = bounds.right - bounds.left;
            float height = bounds.bottom - bounds.top;
    
            // Position the badge in the top-right quadrant of the icon.
            float radius = ((Math.min(width, height) / 2) - 1) / 2;
            float centerX = width - radius - 1;
            float centerY = radius + 1;
    
            // Draw badge circle.
            canvas.drawCircle(centerX, centerY, radius, mBadgePaint);
    
            // Draw badge count text inside the circle.
            mTextPaint.getTextBounds(mCount, 0, mCount.length(), mTxtRect);
            float textHeight = mTxtRect.bottom - mTxtRect.top;
            float textY = centerY + (textHeight / 2f);
            canvas.drawText(mCount, centerX, textY, mTextPaint);
        }
    
        /*
        Sets the count (i.e notifications) to display.
         */
        public void setCount(int count) {
            mCount = Integer.toString(count)
    
            // Only draw a badge if there are notifications.
            mWillDraw = count > 0;
            invalidateSelf();
        }
    
        @Override
        public void setAlpha(int alpha) {
            // do nothing
        }
    
        @Override
        public void setColorFilter(ColorFilter cf) {
            // do nothing
        }
    
        @Override
        public int getOpacity() {
            return PixelFormat.UNKNOWN;
        }
    }
    

    For /res/drawable/ic_menu_notifications.xml

    
    
        
    
        
        
    
    

    /res/menu/menu_home.xml

    
        
    
    

    Now in the HomeActivity.java

    public class HomeActivity extends Activity {
    
        private int mNotificationsCount = 0;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_home);
    
            // Run a task to fetch the notifications count
            new FetchCountTask().execute();
        }
    
    
        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            getMenuInflater().inflate(R.menu.home, menu);
    
            // Get the notifications MenuItem and 
            // its LayerDrawable (layer-list)
            MenuItem item = menu.findItem(R.id.action_notifications);
            LayerDrawable icon = (LayerDrawable) item.getIcon();
    
            // Update LayerDrawable's BadgeDrawable
            Utils.setBadgeCount(this, icon, mNotificationsCount);
    
            return true;
        }
    
        @Override
        public boolean onOptionsItemSelected(MenuItem item) {
            if (item.getItemId() == R.id.action_notifications) {
                // TODO: display unread notifications.
                return true;
            }
            return super.onOptionsItemSelected(item);
        }
    
        /*
        Updates the count of notifications in the ActionBar.
         */
        private void updateNotificationsBadge(int count) {
            mNotificationsCount = count;
    
            // force the ActionBar to relayout its MenuItems.
            // onCreateOptionsMenu(Menu) will be called again.
            invalidateOptionsMenu(); 
        }
    
        /*
        Sample AsyncTask to fetch the notifications count
        */
        class FetchCountTask extends AsyncTask {
    
            @Override
            protected Integer doInBackground(Void... params) {
                // example count. This is where you'd 
                // query your data store for the actual count.
                return 5; 
            }
    
            @Override
            public void onPostExecute(Integer count) {
                updateNotificationsBadge(count);
            }
        }
    }
    

    Utility class Utils.java

    public class Utils {
    
        public static void setBadgeCount(Context context, LayerDrawable icon, int count) {
    
            BadgeDrawable badge;
    
            // Reuse drawable if possible
            Drawable reuse = icon.findDrawableByLayerId(R.id.ic_badge);
            if (reuse != null && reuse instanceof BadgeDrawable) {
                badge = (BadgeDrawable) reuse;
            } else {
                badge = new BadgeDrawable(context);
            }
    
            badge.setCount(count);
            icon.mutate();
            icon.setDrawableByLayerId(R.id.ic_badge, badge);
        }
    }
    

    Reference Link for Full Code

提交回复
热议问题