Как реализовать динамические значения в пункте меню в Android

У меня есть пункт меню на панели действий. Наряду с изображением пункта меню мне нужно показать некоторое число, связанное с ним, которое будет часто меняться. Я не использую панель действий Шерлок. Я не хочу использовать это. Кроме этого все остальное работает нормально. На показанном изображении значок белого цвета — мой. Мне нужно динамически генерировать число с красным фоном. Как я могу сделать это в Android?

Вот пример изображения:

введите здесь описание изображения

Обновлять:

У меня есть этот пункт меню в моем menu.xml. Это должно работать как пункт меню уведомлений, который показывает количество уведомлений. Я установил значок меню, например,

 menuItem.setIcon(image);

Теперь поверх пункта меню мне нужно разместить одно текстовое представление с общим количеством уведомлений.

можно ли реализовать эту функциональность с помощью viewbadger? URL-адрес Github


person intrepidkarthi    schedule 26.11.2012    source источник


Ответы (4)


Я обнаружил, как добавить actionView в пункт меню и получить установленные значения для представления в коде.

См. здесь: https://stackoverflow.com/a/16648170/857681

person speedynomads    schedule 20.05.2013

После долгих попыток почти всех ресурсов на SO я обратился к блогам; успешно. Я хочу поделиться тем, что сработало для меня (Api >= 13); источник.

Начнем с красивого кода, как он используется:

 public boolean onCreateOptionsMenu(Menu menu) {
    //inflate menu
    getMenuInflater().inflate(R.menu.menu_my, menu);

    // Get the notifications MenuItem and LayerDrawable (layer-list)
    MenuItem item = menu.findItem(R.id.action_notifications);
    LayerDrawable icon = (LayerDrawable) item.getIcon();

    // Update LayerDrawable's BadgeDrawable
    Utils2.setBadgeCount(this, icon, 2);

    return true;
}

menu_my.xml:

<menu 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"
    tools:context=".MainActivity">
    <item
        android:id="@+id/action_notifications"
        android:icon="@drawable/ic_menu_notifications"
        android:title="Notifications"
        app:showAsAction="always" />
</menu>

Этот класс удобно создает BadgeDrawable; его внешний вид также может быть изменен:

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);
        mTextSize = 12F;

        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;
    }
}

Этот класс помогает установить число. Я рекомендую реализовать еще больше способов, чтобы установить значок в качестве даты и т. д.:

public class Utils2 {
    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);
    }


}

И mui Importante рисуемый объект (например, макет) в res/drawable:

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:id="@+id/ic_notification"
        android:drawable="@drawable/ice_skate"
        android:gravity="center" />

    <!-- set a place holder Drawable so android:drawable isn't null -->
    <item
        android:id="@+id/ic_badge"
        android:drawable="@drawable/ice_skate" />
</layer-list>

Удачи!

person msysmilu    schedule 10.02.2015
comment
Является ли ваш ic_menu_notifications файлом со списком слоев, который вы упомянули внизу? - person Lampard; 26.10.2016
comment
Вы просто скопировали код из источника. Пожалуйста, прекрати это делать. - person Mahori; 03.05.2017
comment
@ Рави, это не то, что я сделал; ссылка на источник больше не работает; и я могу заверить вас, что этот код был в разработке в моем приложении до того, как я разместил его здесь; важно также объяснить, как работают эти 5 блоков кода. - person msysmilu; 30.06.2017
comment
Ссылка не работает. - person Pratik Butani; 28.12.2017
comment
@PratikButani, правда; вот почему я вставил фрагменты. - person msysmilu; 06.01.2018
comment
Я получал ClassCastException для преобразования из BitmapDrawable в LayerDrawable. следуйте этому для этой ошибки не может быть"> stackoverflow.com/questions/37386027/ - person Virat18; 08.01.2019

Вот что вы можете попробовать:

Создайте собственный Drawable, который рисует ваше изображение на заднем плане и текст поверх изображения. Ознакомьтесь с этой публикацией для примера.

Затем установите этот Drawable в качестве фона MenuItem динамически...

person Praful Bhatnagar    schedule 26.11.2012

Используйте вид действия. Он работает с обоими: по умолчанию ActionBar и ActionBarSherlock.

Вот пример

При таком подходе вы можете просто создать свой собственный View (например, раздув какой-то макет), а затем делать все, что хотите (изменить фон, изменить содержимое, динамически добавить другие представления, если ваше представление действий является подклассом ViewGroup и т. д.).

person Dmitry Zaytsev    schedule 26.11.2012