Existe-t-il un badge ou une méthode standard Android permettant d'afficher l'icône de notification de la barre d'action avec un nombre similaire à celui des exemples Google?
Si non, alors quel est le meilleur moyen de le faire?
Je suis nouveau sur Android, aidez-moi s'il vous plaît.
Je ne sais pas si c'est la meilleure solution ou non, mais c'est ce dont j'ai besoin.
S'il vous plaît dites-moi si vous savez ce qui doit être changé pour une meilleure performance ou qualité. Dans mon cas, j'ai un bouton.
Élément personnalisé dans mon menu - main.xml
<item
Android:id="@+id/badge"
Android:actionLayout="@layout/feed_update_count"
Android:icon="@drawable/shape_notification"
Android:showAsAction="always">
</item>
Forme personnalisée pouvant être dessinée (carré d’arrière-plan) - 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>
Mise en page pour ma vue - 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 - Définition et mise à jour de ma vue
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();
}
Éditer Depuis la version 26 de la bibliothèque de support (ou androidx), vous n'avez plus besoin d'implémenter un OnLongClickListener
personnalisé pour afficher l'info-bulle. Appelez simplement ceci:
TooltipCompat.setTooltipText(menu_hotlist, getString(R.string.hint_show_hot_message));
Je partagerai simplement mon code au cas où quelqu'un voudrait quelque chose comme ceci:
layout/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>
layout/action_bar_notifitcation_icon.xml
Remarque style et Android: propriétés cliquables . ceux-ci font la mise en page la taille d'un bouton et rendent l'arrière-plan gris lorsque vous le touchez.
<?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
Une image de 64 x 64 pixels avec des rembourrages de 10 pixels de large de tous les côtés. Vous êtes censé avoir un remplissage de 8 pixels de large, mais je trouve que la plupart des éléments par défaut sont légèrement plus petits que cela. Bien sûr, vous voudrez utiliser différentes tailles pour différentes densités.
drawable/rounded_square.xml
Ici, # ff222222 (couleur # 222222 avec alpha #ff (entièrement visible)) est la couleur d’arrière-plan de ma barre d’action.
<?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
Ici, nous le rendons cliquable et modifiable! J'ai créé un écouteur abstrait qui fournit la création de Toast sur onLongClick, le code provient de les sources 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;
}
}
Juste pour ajouter. Si quelqu'un veut implémenter une bulle de cercle rempli, voici le code (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.
EDIT: 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 article:
<item
Android:id="@+id/menu_messages"
Android:showAsAction="always"
Android:actionLayout="@layout/badge_layout"/>
Dans onCreateOptionsMenu
obtenez 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.+'
Je n'aime pas les solutions basées sur ActionView
, mon idée est la suivante:
TextView
, qui TextView
sera rempli par l'applicationlorsque vous devez dessiner un MenuItem
:
2.1. gonfler la mise en page
2.2. appelez measure()
& layout()
(sinon view
sera 0px x 0px, il est trop petit pour la plupart des cas d'utilisation)
2.3. définir le texte de TextView
2.4. faire "capture d'écran" de la vue
2.6 définir l'icône de MenuItem
en fonction du bitmap créé sous 2.4
profit!
alors, le résultat devrait être quelque chose comme
<?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_background
est-ce que l'arrière-plan vert de TextView
, @drawable/ic_menu_gallery
n'est pas vraiment requis ici, il s'agit simplement de prévisualiser le résultat de la mise en page dans IDE.
ajouter du code dans 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;
}
Implémentez la méthode 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);
}
Le code complet est ici: https://github.com/cvoronin/ActionBarMenuItemCounter
Ok, pour @ AndrewS la solution à utiliser avec bibliothèque v7 appCompat:
<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();
}
Le reste du code est le même.
Essayez de regarder les réponses à ces questions, en particulier la seconde qui contient un exemple de code:
Comment implémenter des valeurs dynamiques sur un élément de menu sous Android
Comment obtenir du texte sur une icône ActionBar?
D'après ce que je vois, vous devrez créer votre propre implémentation personnalisée ActionView
. Une alternative pourrait être une coutume Drawable
. Notez qu'il semble n'y avoir aucune implémentation native d'un nombre de notifications pour la barre d'action.
EDIT: La réponse que vous recherchiez, avec le code: affichage de la notification personnalisée avec exemple de mise en oeuvre
Lorsque vous utilisez la barre d'outils:
....
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);
}
et dans votre appel de données de chargement refreshMenu ():
private void refreshMenu() {
comment_count.setVisibility(View.VISIBLE);
comment_count.setText("" + post_data.getComment_count());
}
J'ai trouvé une très bonne solution ici , je l'utilise avec kotlin.
Tout d'abord, dans le dossier pouvant être dessiné, vous devez créer 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>
Dans votre Activity_Main
Layout, par exemple:
<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>
Et vous pouvez modifier comme:
btnBadge.setOnClickListener { view ->
Snackbar.make(view,"badge click", Snackbar.LENGTH_LONG) .setAction("Action", null).show()
txtBadge.text = "0"
}
J'ai trouvé un meilleur moyen de le faire. si vous voulez utiliser quelque chose comme ça
Utilisez cette dépendance
compile 'com.nex3z:notification-badge:0.1.0'
créer un fichier xml dans drawable et l'enregistrer en tant que 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>
Maintenant, partout où vous voulez utiliser ce badge, utilisez le code suivant en XML. avec l'aide de cela, vous pourrez voir ce badge dans le coin supérieur droit de votre image ou quoi que ce soit.
<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>
Maintenant, enfin sur yourFile.Java, utilisez ces 2 choses simples .. 1) Définir
NotificationBadge mBadge;
2) où votre boucle ou tout ce qui compte ce nombre utilise ceci:
mBadge.setNumber(your_LoopCount);
ici, mBadge.setNumber(0)
ne montrera rien.
J'espère que cette aide.