Ajouter un nouveau nombre d'articles à l'icône sur le bouton - Android


87

Je suis développeur. Je dois implémenter la conception ci-dessous. J'ai déjà une application fonctionnelle mais je me demande comment aborder cela? En particulier, je suis intéressé par la façon d'afficher le nombre de "nouveaux" éléments sous les onglets. Ce que JE SAIS faire - c'est créer de nouvelles icônes avec des points rouges et les afficher simplement lorsque de nouvelles choses sont disponibles.

Mais je n'ai aucune idée de comment faire flotter ces cercles ronds au-dessus du titre ET afficher le numéro à l'intérieur. Quelqu'un a-t-il des suggestions sur ce que vous recherchez? Des échantillons? Les directions?

Deuxième question sur la séparation des activités. Dois-je faire le contrôle pour combiner des boutons comme celui-ci et simplement le gonfler sur les activités? Sinon, je peux créer une activité par onglets, mais je ne suis pas sûr qu'il soit possible de la styliser pour qu'elle ressemble à ceci.

Partie de la navigation supérieure

Réponses:


164

Faites de votre badge un TextView, vous permettant de définir la valeur numérique sur ce que vous voulez en appelant setText(). Définissez l'arrière-plan du TextViewcomme un <shape>dessin XML , avec lequel vous pouvez créer un cercle plein ou dégradé avec une bordure. Un dessin XML sera mis à l'échelle pour s'adapter à la vue lors de son redimensionnement avec plus ou moins de texte.

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>

Vous devrez cependant regarder comment l'ovale / le cercle s'échelonne avec de grands nombres à 3-4 chiffres. Si cet effet n'est pas souhaitable, essayez une approche rectangle arrondie comme ci-dessous. Avec de petits nombres, le rectangle ressemblera toujours à un cercle lorsque les rayons convergent ensemble.

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>

Avec l'arrière-plan évolutif créé, il vous suffit de l'ajouter à l'arrière-plan d'un TextView, comme ceci:

<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"/>

Enfin, ces TextViewbadges peuvent être placés dans votre mise en page au-dessus des boutons / onglets appropriés. Je ferais probablement cela en regroupant chaque bouton avec son badge dans un RelativeLayoutconteneur, comme ceci:

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

Espérons que ce soit suffisamment d'informations pour au moins vous orienter dans la bonne direction!


Est-il possible de faire quelque chose de similaire avec un TableLayout? J'ai une grille 2x2 de boutons et une disposition relative est plus difficile à configurer qu'une disposition relative, mais je ne peux pas utiliser d'attributs comme aligntTop et alignRight
Nick

NM Je l'ai résolu en mettant simplement une disposition relative dans la rangée du tableau! Merci, le code fonctionne très bien
Nick

3
@FelipeMosso Utilisez la ovalversion de l'exemple et ajoutez un <size>élément pour fournir des proportions pour la largeur / hauteur
devunwired

4
L'icône de compte se cache derrière ce bouton dans mon cas. Sur Android 5.0. Je ne sais pas ce qui ne va pas. Dans la mise en page graphique, il semble bon mais pas dans l'appareil.
Braj

1
Si j'utilise Button pour l'icône de comptage, tout fonctionne bien, mais si j'utilise Textview, il passe derrière le bouton principal au lieu de s'afficher en haut!
Braj

10

Android ViewBadger

Un moyen simple de "badger" une vue Android donnée au moment de l'exécution sans avoir à en tenir compte dans la mise en page.

Ajouter un .jarfichier dans votre dossier libs

Cliquez pour télécharger l' exemple

voir Exemple sur github

Exemple simple:

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

4
Cette bibliothèque est obsolète.
wonsuc

3

Piratage le plus simple en donnant du style TextViewuniquement.

        <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" />

Résultat


1

pour les personnes qui recherchent Xamarin Android peuvent utiliser ce code

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

}

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

comment réduire le cercle?
khalil

@khalil essaie de créer avec SkiaSharp
Ronak Shethia

1

Juste pour ajouter. Si quelqu'un souhaite implémenter une bulle de cercle rempli en utilisant la forme de l'anneau au lieu de l'ovale, voici l'exemple de code d'ajout du nombre de bulles aux boutons de la barre d'action. Mais cela peut être ajouté à n'importe quel bouton.

(nommez-le 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>

Vous devrez peut-être ajuster l'épaisseur en fonction de vos besoins.

Le résultat sera quelque chose comme ceci:

entrez la description de l'image ici

Voici la disposition du bouton (nommez-le 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>

Dans le menu créer un élément:

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

Pour onCreateOptionsMenuobtenir une référence à l'élément de menu:

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

Après avoir reçu une notification pour les messages, définissez le nombre:

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

Ce code utilise Iconify-fontawesome .

compile 'com.joanzapata.iconify:android-iconify-fontawesome:2.1.+'
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.