Czy istnieje standardowa plakietka Androida lub metoda wyświetlania ikony powiadomień na pasku działań z liczbą, jak na przykładach Google?

Jeśli nie, to jaki jest najlepszy sposób, aby to zrobić?
Jestem nowy w Androidzie, proszę o pomoc.
Czy istnieje standardowa plakietka Androida lub metoda wyświetlania ikony powiadomień na pasku działań z liczbą, jak na przykładach Google?

Jeśli nie, to jaki jest najlepszy sposób, aby to zrobić?
Jestem nowy w Androidzie, proszę o pomoc.
Odpowiedzi:
Nie jestem pewien, czy to najlepsze rozwiązanie, czy nie, ale tego potrzebuję.
Powiedz mi, jeśli wiesz, co należy zmienić, aby uzyskać lepszą wydajność lub jakość. W moim przypadku mam przycisk.
Niestandardowa pozycja w moim menu - main.xml
<item
android:id="@+id/badge"
android:actionLayout="@layout/feed_update_count"
android:icon="@drawable/shape_notification"
android:showAsAction="always">
</item>
Niestandardowy kształt do rysowania (kwadrat tła) - shape_notification.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<stroke android:color="#22000000" android:width="2dp"/>
<corners android:radius="5dp" />
<solid android:color="#CC0001"/>
</shape>
Układ dla mojego widoku - feed_update_count.xml
<?xml version="1.0" encoding="utf-8"?>
<Button xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/notif_count"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minWidth="32dp"
android:minHeight="32dp"
android:background="@drawable/shape_notification"
android:text="0"
android:textSize="16sp"
android:textColor="@android:color/white"
android:gravity="center"
android:padding="2dp"
android:singleLine="true">
</Button>
MainActivity - ustawianie i aktualizowanie mojego widoku
static Button notifCount;
static int mNotifCount = 0;
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getSupportMenuInflater();
inflater.inflate(R.menu.main, menu);
View count = menu.findItem(R.id.badge).getActionView();
notifCount = (Button) count.findViewById(R.id.notif_count);
notifCount.setText(String.valueOf(mNotifCount));
return super.onCreateOptionsMenu(menu);
}
private void setNotifCount(int count){
mNotifCount = count;
invalidateOptionsMenu();
}
MenuItem item = menu.findItem(R.id.badge); MenuItemCompat.setActionView(item, R.layout.feed_update_count); notifCount = (Button) MenuItemCompat.getActionView(item);
android:icon="..."XML w pozycji menu. android:actionLayout="..."Wystarczy, tam. W przypadku Buttonkodu XML układu można użyć samozamykającego się znacznika, <Button ... />ponieważ znacznik nie może mieć treści. Musisz zamknąć <shape>tag (ponownie: samozamykanie). I nie potrzebujesz invalidateOptionsMenu(). Dla mnie to nawet nie działa, ponieważ plakietka jest zawsze ponownie zawyżana z XML. A więc całość setNotifCount(...)jest bezużyteczna. Wystarczy zadzwonić setText(...)na odznakę. Możesz też przesyłać bezpośrednio getActionView()do Button.
Edycja Od wersji 26 biblioteki obsługi (lub systemu Androidx) nie trzeba już implementować niestandardowego sposobu OnLongClickListenerwyświetlania podpowiedzi. Po prostu nazwij to:
TooltipCompat.setTooltipText(menu_hotlist, getString(R.string.hint_show_hot_message));
Po prostu udostępnię swój kod na wypadek, gdyby ktoś chciał coś takiego:

układ / menu / menu_actionbar.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
...
<item android:id="@+id/menu_hotlist"
android:actionLayout="@layout/action_bar_notifitcation_icon"
android:showAsAction="always"
android:icon="@drawable/ic_bell"
android:title="@string/hotlist" />
...
</menu>układ / action_bar_notifitcation_icon.xml
Styl notatki i Android: klikalne właściwości. Dzięki temu układ ma rozmiar przycisku, a po dotknięciu tło jest szare.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:orientation="vertical"
android:gravity="center"
android:layout_gravity="center"
android:clickable="true"
style="@android:style/Widget.ActionButton">
<ImageView
android:id="@+id/hotlist_bell"
android:src="@drawable/ic_bell"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:layout_margin="0dp"
android:contentDescription="bell"
/>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/hotlist_hot"
android:layout_width="wrap_content"
android:minWidth="17sp"
android:textSize="12sp"
android:textColor="#ffffffff"
android:layout_height="wrap_content"
android:gravity="center"
android:text="@null"
android:layout_alignTop="@id/hotlist_bell"
android:layout_alignRight="@id/hotlist_bell"
android:layout_marginRight="0dp"
android:layout_marginTop="3dp"
android:paddingBottom="1dp"
android:paddingRight="4dp"
android:paddingLeft="4dp"
android:background="@drawable/rounded_square"/>
</RelativeLayout>drawable-xhdpi / ic_bell.png
Obraz 64x64 piksele z 10-pikselowymi wypełnieniami ze wszystkich stron. Powinieneś mieć wypełnienie o szerokości 8 pikseli, ale uważam, że większość domyślnych elementów jest nieco mniejsza. Oczywiście będziesz chciał użyć różnych rozmiarów dla różnych gęstości.
drawable / rounded_square.xml
Tutaj # ff222222 (kolor # 222222 z alfa #ff (w pełni widoczny)) jest kolorem tła mojego paska akcji.
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="2dp" />
<solid android:color="#ffff0000" />
<stroke android:color="#ff222222" android:width="2dp"/>
</shape>com / ubergeek42 / WeechatAndroid / WeechatActivity.java
Tutaj sprawiamy, że jest klikalny i aktualizowany! Stworzyłem abstrakcyjny detektor, który zapewnia tworzenie Toast na onLongClick, kod został pobrany ze źródeł ActionBarSherlock .
private int hot_number = 0;
private TextView ui_hot = null;
@Override public boolean onCreateOptionsMenu(final Menu menu) {
MenuInflater menuInflater = getSupportMenuInflater();
menuInflater.inflate(R.menu.menu_actionbar, menu);
final View menu_hotlist = menu.findItem(R.id.menu_hotlist).getActionView();
ui_hot = (TextView) menu_hotlist.findViewById(R.id.hotlist_hot);
updateHotCount(hot_number);
new MyMenuItemStuffListener(menu_hotlist, "Show hot message") {
@Override
public void onClick(View v) {
onHotlistSelected();
}
};
return super.onCreateOptionsMenu(menu);
}
// call the updating code on the main thread,
// so we can call this asynchronously
public void updateHotCount(final int new_hot_number) {
hot_number = new_hot_number;
if (ui_hot == null) return;
runOnUiThread(new Runnable() {
@Override
public void run() {
if (new_hot_number == 0)
ui_hot.setVisibility(View.INVISIBLE);
else {
ui_hot.setVisibility(View.VISIBLE);
ui_hot.setText(Integer.toString(new_hot_number));
}
}
});
}
static abstract class MyMenuItemStuffListener implements View.OnClickListener, View.OnLongClickListener {
private String hint;
private View view;
MyMenuItemStuffListener(View view, String hint) {
this.view = view;
this.hint = hint;
view.setOnClickListener(this);
view.setOnLongClickListener(this);
}
@Override abstract public void onClick(View v);
@Override public boolean onLongClick(View v) {
final int[] screenPos = new int[2];
final Rect displayFrame = new Rect();
view.getLocationOnScreen(screenPos);
view.getWindowVisibleDisplayFrame(displayFrame);
final Context context = view.getContext();
final int width = view.getWidth();
final int height = view.getHeight();
final int midy = screenPos[1] + height / 2;
final int screenWidth = context.getResources().getDisplayMetrics().widthPixels;
Toast cheatSheet = Toast.makeText(context, hint, Toast.LENGTH_SHORT);
if (midy < displayFrame.height()) {
cheatSheet.setGravity(Gravity.TOP | Gravity.RIGHT,
screenWidth - screenPos[0] - width / 2, height);
} else {
cheatSheet.setGravity(Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL, 0, height);
}
cheatSheet.show();
return true;
}
}app:actionLayout="@layout/action_bar_notifitcation_icon"zamiast, android:actionLayout="@layout/action_bar_notifitcation_icon"jeśli chcesz używać MenuItemCompat.getActionViewzamiast w menu.findItem(R.id.menu_hotlist).getActionView();przypadku problemów ze zgodnością. MenuItem.getActionViewnie jest kompatybilny z poziomem API <11.
android:actionLayout; AppCompat: app:actionLayoutw pozycji menu.
Wystarczy dodać. Jeśli ktoś chce zaimplementować bąbelek wypełniony kółkiem, oto kod (nazwij go 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.

EDYCJA:
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.+'
Nie lubię ActionViewrozwiązań opartych na rozwiązaniach, mój pomysł to:
TextView, który TextViewzostanie wypełniony przez aplikacjękiedy musisz narysować MenuItem:
2.1. nadmuchać układ
2.2. call measure()& layout()(w przeciwnym razie viewbędzie to 0px x 0px, jest za mały dla większości przypadków użycia)
2.3. ustawić TextViewtekst
2.4. zrobić „zrzut ekranu” widoku
2.6. MenuItemikona zestawu oparta na bitmapie utworzonej w wersji 2.4
zysk!
więc wynik powinien być podobny

<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/counterPanel" android:layout_width="32dp" android:layout_height="32dp" android:background="@drawable/ic_menu_gallery"> <RelativeLayout android:id="@+id/counterValuePanel" android:layout_width="wrap_content" android:layout_height="wrap_content" > <ImageView android:id="@+id/counterBackground" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/unread_background" /> <TextView android:id="@+id/count" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="1" android:textSize="8sp" android:layout_centerInParent="true" android:textColor="#FFFFFF" /> </RelativeLayout> </FrameLayout>
@drawable/unread_backgroundjest to, że zielone TextViewtło @drawable/ic_menu_gallerynie jest tutaj wymagane ,
służy tylko do podglądu wyniku układu w IDE.
dodaj kod do onCreateOptionsMenu/onPrepareOptionsMenu
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
MenuItem menuItem = menu.findItem(R.id.testAction);
menuItem.setIcon(buildCounterDrawable(count, R.drawable.ic_menu_gallery));
return true;
}Zaimplementuj metodę build-the-icon:
private Drawable buildCounterDrawable(int count, int backgroundImageId) {
LayoutInflater inflater = LayoutInflater.from(this);
View view = inflater.inflate(R.layout.counter_menuitem_layout, null);
view.setBackgroundResource(backgroundImageId);
if (count == 0) {
View counterTextPanel = view.findViewById(R.id.counterValuePanel);
counterTextPanel.setVisibility(View.GONE);
} else {
TextView textView = (TextView) view.findViewById(R.id.count);
textView.setText("" + count);
}
view.measure(
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());
view.setDrawingCacheEnabled(true);
view.setDrawingCacheQuality(View.DRAWING_CACHE_QUALITY_HIGH);
Bitmap bitmap = Bitmap.createBitmap(view.getDrawingCache());
view.setDrawingCacheEnabled(false);
return new BitmapDrawable(getResources(), bitmap);
}Pełny kod jest tutaj: https://github.com/cvoronin/ActionBarMenuItemCounter
Ok, aby rozwiązanie @AndrewS działało z biblioteką appCompat w wersji 7 :
<menu
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:someNamespace="http://schemas.android.com/apk/res-auto" >
<item
android:id="@+id/saved_badge"
someNamespace:showAsAction="always"
android:icon="@drawable/shape_notification" />
</menu>
.
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
menu.clear();
inflater.inflate(R.menu.main, menu);
MenuItem item = menu.findItem(R.id.saved_badge);
MenuItemCompat.setActionView(item, R.layout.feed_update_count);
View view = MenuItemCompat.getActionView(item);
notifCount = (Button)view.findViewById(R.id.notif_count);
notifCount.setText(String.valueOf(mNotifCount));
}
private void setNotifCount(int count){
mNotifCount = count;
supportInvalidateOptionsMenu();
}
Reszta kodu jest taka sama.
android:actionLayoutna app:actionLayoutto działa jak urok.
Spróbuj spojrzeć na odpowiedzi na te pytania, szczególnie na drugie, które zawiera przykładowy kod:
Jak zaimplementować wartości dynamiczne w elemencie menu w systemie Android
Jak uzyskać tekst na ikonie ActionBar?
Z tego, co widzę, musisz stworzyć własną niestandardową ActionViewimplementację. Alternatywą może być zwyczaj Drawable. Zauważ, że wydaje się, że nie ma natywnej implementacji liczby powiadomień dla paska akcji.
EDYCJA: Odpowiedź, której szukałeś, z kodem: Niestandardowy widok powiadomień z przykładową implementacją
Drawables, jak widać w następujących dwóch linkach: stackoverflow.com/questions/6691818/ ... i stackoverflow.com/questions/3972445/ ...
Drawableza pomocą czegoś takiego jak link tutaj, a następnie utworzyć atrybut dla swojego niestandardowego, Drawablektóry ma nadpisany tekst, abyś mógł stworzyć całość w formacie XML i dopasuj go tak, jak chcesz. Alternatywnie możesz dodać Drawable w Javie, jeśli jest to zbyt trudne.
Podczas korzystania z paska narzędzi:
....
private void InitToolbar() {
toolbar = (Toolbar) findViewById(R.id.my_awesome_toolbar);
toolbartitle = (TextView) findViewById(R.id.titletool);
toolbar.inflateMenu(R.menu.show_post);
toolbar.setOnMenuItemClickListener(this);
Menu menu = toolbar.getMenu();
MenuItem menu_comments = menu.findItem(R.id.action_comments);
MenuItemCompat
.setActionView(menu_comments, R.layout.menu_commentscount);
View v = MenuItemCompat.getActionView(menu_comments);
v.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
// Your Action
}
});
comment_count = (TextView) v.findViewById(R.id.count);
}
oraz w wywołaniu danych ładowania refreshMenu ():
private void refreshMenu() {
comment_count.setVisibility(View.VISIBLE);
comment_count.setText("" + post_data.getComment_count());
}
Znalazłem bardzo dobre rozwiązanie tutaj , używam go z Kotlin.
Najpierw w folderze do rysowania musisz utworzyć item_count.xml:
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="8dp" />
<solid android:color="#f20000" />
<stroke
android:width="2dip"
android:color="#FFF" />
<padding
android:bottom="5dp"
android:left="5dp"
android:right="5dp"
android:top="5dp" />
</shape>
W Twoim Activity_Mainukładzie niektóre z nich:
<RelativeLayout
android:id="@+id/badgeLayout"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_toRightOf="@+id/badge_layout1"
android:layout_gravity="end|center_vertical"
android:layout_marginEnd="5dp">
<RelativeLayout
android:id="@+id/relative_layout1"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<Button
android:id="@+id/btnBadge"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@mipmap/ic_notification" />
</RelativeLayout>
<TextView
android:id="@+id/txtBadge"
android:layout_width="18dp"
android:layout_height="18dp"
android:layout_alignRight="@id/relative_layout1"
android:background="@drawable/item_count"
android:text="22"
android:textColor="#FFF"
android:textSize="7sp"
android:textStyle="bold"
android:gravity="center"/>
</RelativeLayout>
I możesz modyfikować jak:
btnBadge.setOnClickListener { view ->
Snackbar.make(view,"badge click", Snackbar.LENGTH_LONG) .setAction("Action", null).show()
txtBadge.text = "0"
}
Znalazłem lepszy sposób na zrobienie tego. jeśli chcesz użyć czegoś takiego
Użyj tej zależności
compile 'com.nex3z:notification-badge:0.1.0'
utwórz jeden plik xml do rysowania i zapisz go jako Badge.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="oval">
<solid android:color="#66000000"/>
<size android:width="30dp" android:height="40dp"/>
</shape>
</item>
<item android:bottom="1dp" android:right="0.6dp">
<shape android:shape="oval">
<solid android:color="@color/Error_color"/>
<size android:width="20dp" android:height="20dp"/>
</shape>
</item>
</layer-list>
Teraz, gdziekolwiek chcesz użyć tej plakietki, użyj następującego kodu w XML. dzięki temu będziesz mógł zobaczyć tę odznakę w prawym górnym rogu swojego obrazu lub cokolwiek innego.
<com.nex3z.notificationbadge.NotificationBadge
android:id="@+id/badge"
android:layout_toRightOf="@id/Your_ICON/IMAGE"
android:layout_alignTop="@id/Your_ICON/IMAGE"
android:layout_marginLeft="-16dp"
android:layout_marginTop="-8dp"
android:layout_width="28dp"
android:layout_height="28dp"
app:badgeBackground="@drawable/Badge"
app:maxTextLength="2"
></com.nex3z.notificationbadge.NotificationBadge>
Teraz w końcu na yourFile.java użyj dwóch prostych rzeczy: 1) Zdefiniuj
NotificationBadge mBadge;
2) gdzie twoja pętla lub cokolwiek, co liczy tę liczbę, używa tego:
mBadge.setNumber(your_LoopCount);
tutaj mBadge.setNumber(0)nic nie pokaże.
Mam nadzieję, że to pomoże.