Чи є стандартний значок або метод Android для показу піктограми сповіщень на панелі дій із кількістю, як на прикладах Google?
Якщо ні, то який найкращий спосіб зробити це?
Я новачок в android, будь ласка, допоможіть.
Чи є стандартний значок або метод Android для показу піктограми сповіщень на панелі дій із кількістю, як на прикладах Google?
Якщо ні, то який найкращий спосіб зробити це?
Я новачок в android, будь ласка, допоможіть.
Відповіді:
Я не впевнений, це найкраще рішення чи ні, але це те, що мені потрібно.
Скажіть, будь ласка, чи знаєте ви, що потрібно змінити для кращої продуктивності чи якості. У моєму випадку у мене є кнопка.
Спеціальний елемент у моєму меню - main.xml
<item
android:id="@+id/badge"
android:actionLayout="@layout/feed_update_count"
android:icon="@drawable/shape_notification"
android:showAsAction="always">
</item>
Спеціальна форма для малювання (квадратний фон) - 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>
Макет для мого перегляду - 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 - налаштування та оновлення мого перегляду
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 вам не потрібен . Тут android:actionLayout="..."
достатньо. Для Button
XML у макеті ви можете використовувати тег, <Button ... />
що закривається, оскільки тег не може мати вміст. Вам потрібно закрити <shape>
тег (знову: самозакриваючись). І вам це не потрібно invalidateOptionsMenu()
. Для мене це навіть не працює, оскільки значок завжди знову надувається від XML. Отже, ціле setNotifCount(...)
марне. Просто зателефонуйте setText(...)
до значка. І ви можете привести getActionView()
до Button
прямо.
Редагувати З версії 26 бібліотеки підтримки (або androidx) вам більше не потрібно впроваджувати спеціальний OnLongClickListener
спосіб відображення підказки. Просто зателефонуйте до цього:
TooltipCompat.setTooltipText(menu_hotlist, getString(R.string.hint_show_hot_message));
Я просто поділюсь своїм кодом у випадку, якщо хтось захоче щось подібне:
макет / меню / меню washingbar.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
Стиль ноти та андроїд: властивості, які можна натискати . вони роблять макет розміром кнопки та роблять фон сірим при дотику.
<?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>
dravable-xhdpi / ic_bell.png
Зображення розміром 64x64 пікселів із широкими прокладками з 10 пікселів з усіх боків. У вас має бути 8 пікселів, але я вважаю, що більшість елементів за замовчуванням трохи менше. Звичайно, ви хочете використовувати різні розміри для різної щільності.
dravable / rounded_square.xml
Тут # ff222222 (колір # 222222 з альфа #ff (повністю видно)) - колір фону моєї панелі дій.
<?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
Тут ми робимо його легко натискати та оновлювати! Я створив абстрактного слухача, який забезпечує створення Toast на onLongClick, код взятий з джерел 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"
замість, android:actionLayout="@layout/action_bar_notifitcation_icon"
якщо вам потрібно використовувати MenuItemCompat.getActionView
замість проблем menu.findItem(R.id.menu_hotlist).getActionView();
із сумісністю. MenuItem.getActionView
не сумісний з рівнем API <11.
android:actionLayout
; AppCompat: app:actionLayout
у пункті вашого меню.
Просто додати. Якщо хтось хоче реалізувати міхур із заповненим колом, ось код (назвіть його 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>
Можливо, вам доведеться регулювати товщину відповідно до ваших потреб.
EDIT:
Ось макет кнопки (назвіть її 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.+'
Мені не подобаються ActionView
базовані рішення, моя ідея:
TextView
, який TextView
буде заповнений додаткомколи вам потрібно намалювати MenuItem
:
2.1. надути макет
2.2. call measure()
& layout()
(інакше view
буде 0px x 0px, це занадто мало для більшості випадків використання)
2.3. встановити TextView
текст 's
2.4. зробити "скріншот" подання
2.6. набір MenuItem
іконок на основі растрової карти, створеної на 2.4
прибуток!
тому результат повинен бути чимось на кшталт
<?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
полягає в тому, що зелений TextView
фон
@drawable/ic_menu_gallery
тут насправді не потрібно, це лише попередній перегляд результату макета в IDE.
додати код у 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;
}
Реалізуйте метод збірки значків:
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);
}
Повний код тут: https://github.com/cvoronin/ActionBarMenuItemCounter
Гаразд, для рішення @AndrewS для роботи з 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();
}
Решта коду однакова.
android:actionLayout
щоб app:actionLayout
він workes як шарм.
Спробуйте переглянути відповіді на ці запитання, особливо на друге, що має зразок коду:
Як реалізувати динамічні значення в пункті меню в Android
Як отримати текст на IconBar Icon?
З того, що я бачу, вам потрібно буде створити власну власну ActionView
реалізацію. Альтернативою може бути звичай Drawable
. Зауважте, що, здається, не існує власного впровадження кількості сповіщень для панелі дій.
EDIT: Відповідь, яку ви шукали, з кодом: Спеціальний перегляд сповіщень із реалізацією зразка
Drawable
з , як видно в двох наступних посилань: stackoverflow.com/questions/6691818 / ... і stackoverflow.com/questions/3972445 / ...
Drawable
наскрізного на зразок посилання тут, а потім зробити атрибут для вашого користувачу, Drawable
який має текст над ним, щоб ви могли створити всю справу в XML і підходити так, як ти захотів. Крім того, ви можете додати Dravable в Java, якщо це занадто важко.
Під час використання панелі інструментів:
....
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);
}
і у вашому завантаженні даних виклику refreshMenu ():
private void refreshMenu() {
comment_count.setVisibility(View.VISIBLE);
comment_count.setText("" + post_data.getComment_count());
}
Я знайшов дуже гарне рішення тут , я використовую його з Котлін.
По-перше, у папці, що витягується, ви повинні створити 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>
У вашій Activity_Main
макеті такі:
<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>
І ви можете змінювати, як:
btnBadge.setOnClickListener { view ->
Snackbar.make(view,"badge click", Snackbar.LENGTH_LONG) .setAction("Action", null).show()
txtBadge.text = "0"
}
Я знайшов кращий спосіб це зробити. якщо ви хочете використовувати щось подібне
Використовуйте цю залежність
compile 'com.nex3z:notification-badge:0.1.0'
створіть один XML-файл у малюванні та збережіть його як 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>
Тепер, де ви хочете використовувати цей знак, використовуйте наступний код у xml. за допомогою цього ви зможете побачити цей знак у правому верхньому куті зображення чи будь-що інше.
<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>
Тепер нарешті на yourFile.java використовуйте цю просту річ .. 1) Визначте
NotificationBadge mBadge;
2) де ваш цикл або все, що рахує це число, використовують це:
mBadge.setNumber(your_LoopCount);
тут, mBadge.setNumber(0)
нічого не покаже
Сподіваюся, що це допоможе.