Подтвердить что ты не робот

Добавить счетчик значков на значок меню навигации гамбургеров в Android

Мой вопрос такой же, как этот вопрос (который не является дубликатом этого вопроса).

Единственный ответ на этот вопрос не работает для меня, так как вместо того, чтобы изменить значок гамбургера по умолчанию слева от заголовка занятия, он просто добавляет дополнительный значок гамбургера справа от заголовка занятия.

Итак, как я могу получить это:

Android hamburger icon with badge counter

Я весь день ковыряюсь в этом, но никуда не деться.

Я вижу, что Toolbar имеет setNavigationIcon(Drawable drawable). В идеале я хотел бы использовать layout (который содержит значок гамбургера и вид значка) вместо Drawable, но я не уверен, достижимо ли это/как это возможно - или есть ли лучший способ?

NB - Это не вопрос о том, как создать вид значка. Я уже создал это и реализовал это в самих пунктах меню навигации. Поэтому мне просто нужно добавить аналогичный вид значка к значку гамбургера по умолчанию.

4b9b3361

Ответ 1

Начиная с версии 24.2.0 библиотеки поддержки версия v7 ActionBarDrawerToggle предложила метод setDrawerArrowDrawable() в качестве средства настройки значка переключения. DrawerArrowDrawable - это класс, который предоставляет этот значок по умолчанию, и его можно подклассифицировать, чтобы изменить его по мере необходимости.

В качестве примера класс BadgeDrawerArrowDrawable переопределяет метод draw(), чтобы добавить базовый красный и белый значок после того, как суперкласс выполнит сам. Это позволяет сохранить анимацию стрелки гамбургера внизу.

import android.content.Context;
import android.graphics.Color;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.support.v7.graphics.drawable.DrawerArrowDrawable;
import java.util.Objects;

public class BadgeDrawerArrowDrawable extends DrawerArrowDrawable {

    // Fraction of the drawable intrinsic size we want the badge to be.
    private static final float SIZE_FACTOR = .3f;
    private static final float HALF_SIZE_FACTOR = SIZE_FACTOR / 2;

    private Paint backgroundPaint;
    private Paint textPaint;
    private String text;
    private boolean enabled = true;

    public BadgeDrawerArrowDrawable(Context context) {
        super(context);

        backgroundPaint = new Paint();
        backgroundPaint.setColor(Color.RED);
        backgroundPaint.setAntiAlias(true);

        textPaint = new Paint();
        textPaint.setColor(Color.WHITE);
        textPaint.setAntiAlias(true);
        textPaint.setTypeface(Typeface.DEFAULT_BOLD);
        textPaint.setTextAlign(Paint.Align.CENTER);
        textPaint.setTextSize(SIZE_FACTOR * getIntrinsicHeight());
    }

    @Override
    public void draw(Canvas canvas) {
        super.draw(canvas);

        if (!enabled) {
            return;
        }

        final Rect bounds = getBounds();
        final float x = (1 - HALF_SIZE_FACTOR) * bounds.width();
        final float y = HALF_SIZE_FACTOR * bounds.height();
        canvas.drawCircle(x, y, SIZE_FACTOR * bounds.width(), backgroundPaint);

        if (text == null || text.length() == 0) {
            return;
        }

        final Rect textBounds = new Rect();
        textPaint.getTextBounds(text, 0, text.length(), textBounds);
        canvas.drawText(text, x, y + textBounds.height() / 2, textPaint);
    }

    public void setEnabled(boolean enabled) {
        if (this.enabled != enabled) {
            this.enabled = enabled;
            invalidateSelf();
        }
    }

    public boolean isEnabled() {
        return enabled;
    }

    public void setText(String text) {
        if (!Objects.equals(this.text, text)) {
            this.text = text;
            invalidateSelf();
        }
    }

    public String getText() {
        return text;
    }

    public void setBackgroundColor(int color) {
        if (backgroundPaint.getColor() != color) {
            backgroundPaint.setColor(color);
            invalidateSelf();
        }
    }

    public int getBackgroundColor() {
        return backgroundPaint.getColor();
    }

    public void setTextColor(int color) {
        if (textPaint.getColor() != color) {
            textPaint.setColor(color);
            invalidateSelf();
        }
    }

    public int getTextColor() {
        return textPaint.getColor();
    }
}

Экземпляр этого может быть задан при переключении в любое время после его создания, а свойства значка задаются непосредственно при рисовании по мере необходимости.

Как указано ниже, OP, Context, используемый для пользовательского DrawerArrowDrawable, должен быть получен с помощью ActionBar#getThemedContext() или Toolbar#getContext(), чтобы убедиться, что используются правильные значения стиля. Например:

private ActionBarDrawerToggle toggle;
private BadgeDrawerArrowDrawable badgeDrawable;
...

toggle = new ActionBarDrawerToggle(this, ...);
badgeDrawable = new BadgeDrawerArrowDrawable(getSupportActionBar().getThemedContext());

toggle.setDrawerArrowDrawable(badgeDrawable);
badgeDrawable.setText("1");
...

screenshots


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

import android.app.Activity;
import android.content.Context;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.widget.Toolbar;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class BadgeDrawerToggle extends ActionBarDrawerToggle {

    private BadgeDrawerArrowDrawable badgeDrawable;

    public BadgeDrawerToggle(Activity activity, DrawerLayout drawerLayout,
                             int openDrawerContentDescRes,
                             int closeDrawerContentDescRes) {
        super(activity, drawerLayout, openDrawerContentDescRes,
              closeDrawerContentDescRes);
        init(activity);
    }

    public BadgeDrawerToggle(Activity activity, DrawerLayout drawerLayout,
                             Toolbar toolbar, int openDrawerContentDescRes,
                             int closeDrawerContentDescRes) {
        super(activity, drawerLayout, toolbar, openDrawerContentDescRes,
              closeDrawerContentDescRes);
        init(activity);
    }

    private void init(Activity activity) {
        Context c = getThemedContext();
        if (c == null) {
            c = activity;
        }
        badgeDrawable = new BadgeDrawerArrowDrawable(c);
        setDrawerArrowDrawable(badgeDrawable);
    }

    public void setBadgeEnabled(boolean enabled) {
        badgeDrawable.setEnabled(enabled);
    }

    public boolean isBadgeEnabled() {
        return badgeDrawable.isEnabled();
    }

    public void setBadgeText(String text) {
        badgeDrawable.setText(text);
    }

    public String getBadgeText() {
        return badgeDrawable.getText();
    }

    public void setBadgeColor(int color) {
        badgeDrawable.setBackgroundColor(color);
    }

    public int getBadgeColor() {
        return badgeDrawable.getBackgroundColor();
    }

    public void setBadgeTextColor(int color) {
        badgeDrawable.setTextColor(color);
    }

    public int getBadgeTextColor() {
        return badgeDrawable.getTextColor();
    }

    private Context getThemedContext() {
        // Don't freak about the reflection. ActionBarDrawerToggle
        // itself is already using reflection internally.
        try {
            Field mActivityImplField = ActionBarDrawerToggle.class
                .getDeclaredField("mActivityImpl");
            mActivityImplField.setAccessible(true);
            Object mActivityImpl = mActivityImplField.get(this);
            Method getActionBarThemedContextMethod = mActivityImpl.getClass()
                .getDeclaredMethod("getActionBarThemedContext");
            return (Context) getActionBarThemedContextMethod.invoke(mActivityImpl);
        }
        catch (Exception e) {
            return null;
        }
    }
}

Таким образом, пользовательский идентификационный знак будет установлен автоматически, и все связанные с переключением управления могут управляться через один объект.

BadgeDrawerToggle является замещающей заменой для ActionBarDrawerToggle, а ее конструкторы точно совпадают.

private BadgeDrawerToggle badgeToggle;
...

badgeToggle = new BadgeDrawerToggle(this, ...);
badgeToggle.setBadgeText("1");
...

Ответ 2

как изменить значок гамбургера по умолчанию на другой пользовательский значок