Добавить количество новых элементов к значку на кнопке — Android

#android #android-layout

#Android #android-layout

Вопрос:

Я разработчик. Мне нужно реализовать дизайн, показанный ниже. У меня уже есть функциональное приложение, но интересно, как вообще к этому подойти? В частности, меня интересует, как показать количество «новых» элементов во вкладках. Что я ЗНАЮ, как сделать — это создавать новые значки с красными точками и просто отображать их, когда новые материалы доступны.

Но я понятия не имею, как заставить эти круглые круги всплывать поверх заголовка И показывать номер внутри. У кого-нибудь есть предложения о том, что тоже искать? Образцы? Как добраться?

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

Часть верхней навигации

Ответ №1:

Сделайте свой значок 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>
  

Надеюсь, этой информации достаточно, чтобы, по крайней мере, направить вас в правильном направлении!

Комментарии:

1. Возможно ли сделать что-то подобное с TableLayout? У меня сетка кнопок 2×2, и относительный макет сложнее настроить, чем относительный макет, однако я не могу использовать такие атрибуты, как aligntTop и alignRight

2. NM Я решил это, просто поместив относительный макет в строку таблицы! Спасибо, код отлично работает

3. @FelipeMosso Используйте oval версию примера и добавьте <size> элемент, чтобы обеспечить пропорции для ширины / высоты

4. В моем случае значок количества скрывается за этой кнопкой. На Android 5.0. Не знаю, что не так. В графическом макете это выглядит хорошо, но не на устройстве.

5. Если я использую кнопку для значка count, все работает нормально, но если я использую Textview, он скрывается за главной кнопкой, а не отображается сверху!

Ответ №2:

Android ViewBadger

Простой способ «добавить значок» к любому заданному представлению Android во время выполнения без необходимости учитывать его в макете.

Добавьте .jar файл в свою папку libs

Нажмите, чтобы загрузить пример

смотрите Пример на github

Простой пример:

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

Комментарии:

1. Эта библиотека устарела.

Ответ №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" />
  

Результат

Ответ №4:

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

(назовите это 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. '
  

Ответ №5:

для людей, которые ищут 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 amp;amp; 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;
    }
  

Комментарии:

1. как мне уменьшить круг?

2. @khalil попробуйте создать с помощью SkiaSharp