Додати кількість елементів до значка на кнопці - Android


87

Я розробник. Мені потрібно реалізувати дизайн, показаний нижче. У мене вже є функціональний додаток, але цікаво, як взагалі підійти до цього? Особливо, мене цікавить, як показати кількість "нових" елементів на вкладках. Що Я ЗНАЮ, як це зробити - це створити нові піктограми з червоними крапками і просто відображати їх, коли з’являться нові речі.

Але я не уявляю, як змусити ці круглі кола плавати поверх заголовка І показувати номер всередині. Хтось має пропозицію щодо того, що теж шукати? Зразки? Напрямки?

Друге питання про поділ діяльності. Чи слід контролювати комбінування таких кнопок і просто надувати його під час діяльності? В іншому випадку я можу створити діяльність із вкладками, але я не впевнений, чи можливо її стилізувати, щоб вона виглядала так.

Частина верхньої навігації

Відповіді:


164

Зробіть свій значок a TextView, дозволяючи встановити числове значення на будь-яке, що вам подобається, зателефонувавши setText(). Встановіть фон TextViewяк XML- <shape>малюнок, за допомогою якого ви можете створити суцільне або градієнтне коло з межею. Малюнок XML, який можна малювати, масштабуватиметься відповідно до подання, оскільки його розмір буде більшим чи меншим.

res / drawable / badge_circle.xml:

<shape xmlns:android="http://schemas.android.com/apk/res/android"
  android:shape="oval">
  <solid
    android:color="#F00" />
  <stroke
    android:width="2dip"
    android:color="#FFF" />
  <padding
    android:left="5dip"
    android:right="5dip"
    android:top="5dip"
    android:bottom="5dip" />
</shape>

Вам доведеться поглянути на те, як масштабується овал / коло з великими 3-4-значними числами. Якщо цей ефект небажаний, спробуйте підхід із заокругленим прямокутником, як показано нижче. При невеликих числах прямокутник все одно буде виглядати як коло, коли радіуси сходяться між собою.

res / drawable / badge_circle.xml:

<shape xmlns:android="http://schemas.android.com/apk/res/android"
  android:shape="rectangle">
  <corners
    android:radius="10dip"/>
  <solid
    android:color="#F00" />
  <stroke
    android:width="2dip"
    android:color="#FFF" />
  <padding
    android:left="5dip"
    android:right="5dip"
    android:top="5dip"
    android:bottom="5dip" />
</shape>

Створивши масштабований фон, ви просто додаєте його на фон TextView, приблизно так:

<TextView
  android:layout_width="wrap_content"
  android:layout_height="wrap_content" 
  android:text="10"
  android:textColor="#FFF"
  android:textSize="16sp"
  android:textStyle="bold"
  android:background="@drawable/badge_circle"/>

Нарешті, ці TextViewзначки можна розмістити у своєму макеті над відповідними кнопками / вкладками. Я б, мабуть, зробив це, згрупувавши кожну кнопку з її значком у RelativeLayoutконтейнер, приблизно так:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content">
  <Button
    android:id="@+id/myButton"
    android:layout_width="65dip"
    android:layout_height="65dip"/>
  <TextView
    android:id="@+id/textOne"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignTop="@id/myButton"
    android:layout_alignRight="@id/myButton" 
    android:text="10"
    android:textColor="#FFF"
    android:textSize="16sp"
    android:textStyle="bold"
    android:background="@drawable/badge_circle"/>
</RelativeLayout>

Сподіваємось, цього достатньо для того, щоб принаймні змусити вас вказати у правильному напрямку!


Чи можна зробити щось подібне до цього за допомогою TableLayout? У мене є сітка кнопок 2x2, і відносний макет є більшим завданням для налаштування, ніж відносний макет, однак я не можу використовувати такі атрибути, як aligntTop і alignRight
Нік

НМ Я вирішив це, просто поставивши відносний макет у рядок таблиці! Дякую, код чудово працює
Нік

3
@FelipeMosso Використовуйте ovalверсію прикладу та додайте <size>елемент, щоб надати пропорції ширини / висоти
devunwired

4
Піктограма графа ховається за цією кнопкою в моєму випадку. На Android 5.0. Не знаю, що не так. У графічному компонуванні це виглядає добре, але не в пристрої.
Брадж

1
Якщо я використовую кнопку для піктограми підрахунку, все працює нормально, але якщо я використовую Textview, вона переходить за головну кнопку, а не відображається зверху!
Брадж

10

Android ViewBadger

Простий спосіб "позначити" будь-який з переглядів Android під час роботи, не маючи потреби в його оформленні.

Додайте .jarфайл у папку libs

Клацніть, щоб завантажити Приклад

див. приклад на github

Простий приклад:

View target = findViewById(R.id.target_view);
BadgeView badge = new BadgeView(this, target);
badge.setText("1");
badge.show();

4
Ця бібліотека застаріла.
wonsuc

3

Найпростіший хак, надаючи TextViewлише стилю .

        <TextView
                android:id="@+id/fabCounter"
                style="@style/Widget.Design.FloatingActionButton"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentEnd="true"
                android:layout_centerVertical="true"
                android:layout_marginEnd="10dp"
                android:padding="5dp"
                android:text="10"
                android:textColor="@android:color/black"
                android:textSize="14sp" />

Результат


1

для людей, які шукають Xamarin Android, можуть використовувати цей код

public class CountDrawable : Drawable
{
    private float mTextSize;
    private Paint mBadgePaint;
    private Paint mTextPaint;
    private Rect mTxtRect = new Rect();

    private String mCount = "";
    private bool mWillDraw = false;


    public CountDrawable(Context context)
    {
        float mTextSize = context.Resources.GetDimension(Resource.Dimension.badge_count_textsize);
        mBadgePaint = new Paint();
        // mBadgePaint.SetCol(ContextCompat.GetColor(context.ApplicationContext, Resource.Color.background_color));
        mBadgePaint.Color = new Color(Color.Red);
        mBadgePaint.AntiAlias = true;
        mBadgePaint.SetStyle(Paint.Style.Fill);

        mTextPaint = new Paint();
        mTextPaint.Color = new Color(Color.White);
        mTextPaint.SetTypeface(Typeface.DefaultBold);
        mTextPaint.TextSize = mTextSize;
        mTextPaint.AntiAlias = true;
        mTextPaint.TextAlign = Paint.Align.Center;
    }


    public override void Draw(Canvas canvas)
    {
        if(!mWillDraw)
        {
            return;
        }



        Rect bounds = GetBounds;
        float width = bounds.Right - bounds.Left;
        float height = bounds.Bottom - bounds.Top;

        float radius = ((Math.Max(width, height) / 2)) / 2;
        float centerX = (width - radius - 1) + 5;
        float centerY = radius - 5;
        if (mCount.Length <= 2)
        {
            // Draw badge circle.
            canvas.DrawCircle(centerX, centerY, (int)(radius + 5.5), mBadgePaint);
        }
        else
        {
            canvas.DrawCircle(centerX, centerY, (int)(radius + 6.5), mBadgePaint);
        }

        mTextPaint.GetTextBounds(mCount, 0, mCount.Length, mTxtRect);
        float textHeight = mTxtRect.Bottom - mTxtRect.Top;
        float textY = centerY + (textHeight / 2f);
        if (mCount.Length > 2)
            canvas.DrawText("99+", centerX, textY, mTextPaint);
        else
            canvas.DrawText(mCount, centerX, textY, mTextPaint);
    }

    public Rect GetBounds { get; set; }


    public void setCount(String count)
    {
        mCount = count;

        // Only draw a badge if there are notifications.
       // mWillDraw = !count.equalsIgnoreCase("0");
        mWillDraw = !string.Equals(count, "0", StringComparison.OrdinalIgnoreCase);
       // invalidateSelf();
    }

    public override void SetAlpha(int alpha)
    {

    }

    public override void SetColorFilter(ColorFilter colorFilter)
    {

    }

    public override int Opacity
    {
        get;
    }

}

І в MainActivity

public override bool OnCreateOptionsMenu(IMenu menu)
    {
        // return base.OnCreateOptionsMenu(menu);
        MenuInflater.Inflate(Resource.Menu.actionmenu, menu);
        // var dd = menu.FindItem(Resource.Id.icon_group);
        IMenuItem item = menu.FindItem(Resource.Id.ic_group);
        LayerDrawable icon = item.Icon as LayerDrawable;

        // LayerDrawable icon = (LayerDrawable)item.Icon;
        CountDrawable badge;
        Drawable reuse = icon.FindDrawableByLayerId(Resource.Id.ic_group_count);
        if (reuse != null && reuse is CountDrawable)
        {
            badge = (CountDrawable)reuse;
        }
        else
        {
            badge = new CountDrawable(this);

        }
        badge.setCount("8");
        badge.GetBounds=icon.Bounds;

        icon.Mutate();
        icon.SetDrawableByLayerId(Resource.Id.ic_group_count, badge);
        return true;
    }

як зробити круг меншим?
халіл

@khalil спробуйте створити за допомогою SkiaSharp
Ronak Shethia

1

Просто додати. Якщо хтось хоче застосувати міхур із заповненим колом, використовуючи форму кільця замість овалу, ось приклад коду додавання кількості міхурів до кнопок панелі дій. Але це можна додати до будь-якої кнопки.

(назвіть це bage_circle.xml):

<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="ring"
    android:useLevel="false"
    android:thickness="9dp"
    android:innerRadius="0dp"
    >

    <solid
        android:color="#F00"
        />
    <stroke
        android:width="1dip"
        android:color="#FFF" />

    <padding
        android:top="2dp"
        android:bottom="2dp"/>

</shape>

Можливо, вам доведеться регулювати товщину відповідно до ваших потреб.

Результат буде приблизно такий:

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

Ось макет кнопки (назвіть її badge_layout.xml):

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">

    <com.joanzapata.iconify.widget.IconButton
        android:layout_width="44dp"
        android:layout_height="44dp"
        android:textSize="24sp"
        android:textColor="@color/white"
        android:background="@drawable/action_bar_icon_bg"
        android:id="@+id/badge_icon_button"/>

    <TextView
        android:id="@+id/badge_textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignTop="@id/badge_icon_button"
        android:layout_alignRight="@id/badge_icon_button"
        android:layout_alignEnd="@id/badge_icon_button"
        android:text="10"
        android:paddingEnd="8dp"
        android:paddingRight="8dp"
        android:paddingLeft="8dp"
        android:gravity="center"
        android:textColor="#FFF"
        android:textSize="11sp"
        android:background="@drawable/badge_circle"/>
</RelativeLayout>

У меню створення пункту:

<item
        android:id="@+id/menu_messages"
        android:showAsAction="always"
        android:actionLayout="@layout/badge_layout"/>

Щоб onCreateOptionsMenuотримати посилання на пункт меню:

    itemMessages = menu.findItem(R.id.menu_messages);

    badgeLayout = (RelativeLayout) itemMessages.getActionView();
    itemMessagesBadgeTextView = (TextView) badgeLayout.findViewById(R.id.badge_textView);
    itemMessagesBadgeTextView.setVisibility(View.GONE); // initially hidden

    iconButtonMessages = (IconButton) badgeLayout.findViewById(R.id.badge_icon_button);
    iconButtonMessages.setText("{fa-envelope}");
    iconButtonMessages.setTextColor(getResources().getColor(R.color.action_bar_icon_color_disabled));

    iconButtonMessages.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            if (HJSession.getSession().getSessionId() != null) {

                Intent intent = new Intent(getThis(), HJActivityMessagesContexts.class);
                startActivityForResult(intent, HJRequestCodes.kHJRequestCodeActivityMessages.ordinal());
            } else {
                showLoginActivity();
            }
        }
    });

Отримавши сповіщення про повідомлення, встановіть кількість:

itemMessagesBadgeTextView.setText("" + count);
itemMessagesBadgeTextView.setVisibility(View.VISIBLE);
iconButtonMessages.setTextColor(getResources().getColor(R.color.white));

Цей код використовує Iconify-fontawesome .

compile 'com.joanzapata.iconify:android-iconify-fontawesome:2.1.+'
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.