Dodaj liczbę nowych pozycji do ikony na przycisku - Android

87

Jestem programistą. Muszę wdrożyć projekt pokazany poniżej. Mam już funkcjonalną aplikację, ale zastanawiam się, jak w ogóle do tego podejść? Szczególnie interesuje mnie, jak wyświetlić liczbę „nowych” elementów pod zakładkami. WIEM, jak to zrobić - to tworzyć nowe ikony z czerwonymi kropkami i wyświetlać je, gdy będą dostępne nowe rzeczy.

Ale nie mam pojęcia, jak sprawić, by te okrągłe kółka unosiły się nad tytułem ORAZ pokazały numer w środku. Czy ktoś ma sugestie, czego też szukać? Próbki? Wskazówki?

Drugie pytanie o rozdzielenie czynności. Czy powinienem kontrolować łączenie takich przycisków i po prostu nadmuchać je na działania? W przeciwnym razie mogę utworzyć działanie z zakładkami, ale nie jestem pewien, czy można go tak stylizować, aby wyglądał tak.

Część nawigacji górnej

katit
źródło

Odpowiedzi:

164

Stwórz odznakę a TextView, umożliwiając ustawienie wartości numerycznej na dowolną wartość, dzwoniąc setText(). Ustaw tło TextViewjako plik XML do <shape>rysowania, za pomocą którego możesz utworzyć pełne lub gradientowe koło z obramowaniem. Plik XML do rysowania będzie skalowany, aby dopasować go do widoku w miarę zmiany rozmiaru z większą lub mniejszą ilością tekstu.

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>

Musisz jednak przyjrzeć się, jak owal / okrąg skaluje się z dużymi 3-4 cyframi. Jeśli ten efekt jest niepożądany, wypróbuj podejście zaokrąglonego prostokąta, jak poniżej. Przy małych liczbach prostokąt nadal będzie wyglądał jak okrąg, gdy promienie zbiegają się razem.

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>

Po utworzeniu skalowalnego tła po prostu dodajesz je do tła a TextView, na przykład:

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

Wreszcie, te TextViewodznaki można umieścić w swoim układzie na górze odpowiednich przycisków / zakładek. Prawdopodobnie zrobiłbym to, grupując każdy przycisk z jego znaczkiem w RelativeLayoutkontenerze, na przykład:

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

Miejmy nadzieję, że to wystarczająca ilość informacji, aby przynajmniej wskazać Ci właściwy kierunek!

devunwired
źródło
Czy można zrobić coś podobnego do tego z TableLayout? Mam siatkę przycisków 2x2, a układ względny jest bardziej uciążliwy w konfiguracji niż układ względny, jednak nie mogę używać atrybutów takich jak aligntTop i alignRight
Nick,
NM Rozwiązałem to po prostu umieszczając względny układ w wierszu tabeli! Dzięki, kod działa świetnie
Nick,
3
@FelipeMosso Skorzystaj z ovalwersji przykładu i dodaj <size>element, aby zapewnić proporcje szerokości / wysokości
devunwired
4
W moim przypadku za tym przyciskiem ukrywa się ikona Count. W systemie Android 5.0. Nie wiem, co się stało. W układzie graficznym wygląda dobrze, ale nie w urządzeniu.
Braj
1
Jeśli używam przycisku do ikony licznika, wszystko działa dobrze, ale jeśli używam Textview, przechodzi za głównym przyciskiem zamiast pojawiać się na górze!
Braj
10

Android ViewBadger

Prosty sposób na oznaczenie dowolnego widoku Androida w czasie wykonywania bez konieczności uwzględniania go w układzie.

Dodaj .jarplik do folderu libs

Kliknij, aby pobrać Przykład

zobacz przykład na github

Prosty przykład:

View target = findViewById(R.id.target_view);
BadgeView badge = new BadgeView(this, target);
badge.setText("1");
badge.show();
Mansukh Ahir
źródło
4
Ta biblioteka jest przestarzała.
wonsuc
3

Najprostszy hack, nadając styl TextViewtylko.

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

Wynik

Aks4125
źródło
1

dla osób, które szukają platformy Xamarin Android, mogą używać tego kodu

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

}

I w 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;
    }
Ronak Shethia
źródło
jak zmniejszyć krąg?
khalil
@khalil spróbuj utworzyć za pomocą SkiaSharp
Ronak Shethia
1

Wystarczy dodać. Jeśli ktoś chce zaimplementować wypełnione kółko bąbelkowe, używając kształtu pierścienia zamiast owalu, oto przykład kodu dodawania liczby bąbelków do przycisków paska akcji. Ale można to dodać do dowolnego przycisku.

(nazwij to 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>

Konieczne może być dostosowanie grubości w zależności od potrzeb.

Wynik będzie mniej więcej taki:

wprowadź opis obrazu tutaj

Oto układ przycisku (nazwij go 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>

W menu utwórz element:

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

W celu onCreateOptionsMenuuzyskania odniesienia do pozycji 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();
            }
        }
    });

Po otrzymaniu powiadomienia o wiadomościach ustaw licznik:

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

Ten kod używa Iconify-fontawesome .

compile 'com.joanzapata.iconify:android-iconify-fontawesome:2.1.+'
Abdullah Umer
źródło