Có một huy hiệu hoặc phương pháp tiêu chuẩn Android để hiển thị biểu tượng thông báo trên thanh hành động với số đếm như trên các ví dụ của Google không?
Nếu không, cách tốt nhất để làm cho nó là gì?
Tôi mới dùng Android, xin hãy giúp đỡ.
Có một huy hiệu hoặc phương pháp tiêu chuẩn Android để hiển thị biểu tượng thông báo trên thanh hành động với số đếm như trên các ví dụ của Google không?
Nếu không, cách tốt nhất để làm cho nó là gì?
Tôi mới dùng Android, xin hãy giúp đỡ.
Câu trả lời:
Tôi không chắc đây có phải là giải pháp tốt nhất hay không, nhưng đó là thứ tôi cần.
Xin vui lòng cho tôi biết nếu bạn biết những gì cần phải thay đổi để có hiệu suất hoặc chất lượng tốt hơn. Trong trường hợp của tôi, tôi có một nút.
Mục tùy chỉnh trên menu của tôi - main.xml
<item
android:id="@+id/badge"
android:actionLayout="@layout/feed_update_count"
android:icon="@drawable/shape_notification"
android:showAsAction="always">
</item>
Hình dạng tùy chỉnh drawable (hình vuông nền) - 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>
Bố cục cho chế độ xem của tôi - 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 - cài đặt và cập nhật chế độ xem của tôi
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 trong mục menu. Thế android:actionLayout="..."
là đủ, ở đó. Đối với Button
XML trong bố cục, bạn có thể sử dụng thẻ tự đóng <Button ... />
vì thẻ không thể có nội dung. Bạn cần đóng <shape>
thẻ (một lần nữa: tự đóng). Và bạn không cần invalidateOptionsMenu()
. Đối với tôi, điều đó thậm chí không hoạt động, vì huy hiệu luôn bị thổi phồng từ XML một lần nữa. Vì vậy, toàn bộ setNotifCount(...)
là vô dụng. Chỉ cần gọi setText(...)
vào huy hiệu. Và bạn có thể đúc getActionView()
để Button
trực tiếp.
Chỉnh sửa Vì phiên bản 26 của thư viện hỗ trợ (hoặc androidx), bạn không còn cần phải thực hiện một tùy chỉnh OnLongClickListener
để hiển thị chú giải công cụ. Đơn giản chỉ cần gọi đây:
TooltipCompat.setTooltipText(menu_hotlist, getString(R.string.hint_show_hot_message));
Tôi sẽ chỉ chia sẻ mã của mình trong trường hợp ai đó muốn một cái gì đó như thế này:
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
Lưu ý phong cách và android: thuộc tính có thể nhấp . những cái này làm cho bố cục kích thước của một nút và làm cho nền màu xám khi chạm vào.
<?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
Một hình ảnh 64x64 pixel với các miếng đệm rộng 10 pixel từ mọi phía. Bạn được cho là có các miếng đệm rộng 8 pixel, nhưng tôi thấy hầu hết các mục mặc định nhỏ hơn một chút. Tất nhiên, bạn sẽ muốn sử dụng các kích cỡ khác nhau cho các mật độ khác nhau.
drawable / round_sapes.xml
Ở đây, # ff222222 (màu # 222222 với alpha #ff (hiển thị đầy đủ)) là màu nền của Action Bar của tôi.
<?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
Ở đây chúng tôi làm cho nó có thể nhấp và cập nhật! Tôi đã tạo một trình nghe trừu tượng cung cấp việc tạo Toast trên onLongClick, mã được lấy từ các nguồn của 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"
thay vì android:actionLayout="@layout/action_bar_notifitcation_icon"
nếu bạn sử dụng MenuItemCompat.getActionView
thay vì các menu.findItem(R.id.menu_hotlist).getActionView();
vấn đề tương thích. MenuItem.getActionView
không tương thích với cấp API <11.
android:actionLayout
; AppCompat: app:actionLayout
trong mục menu của bạn.
Chỉ cần thêm. Nếu ai đó muốn thực hiện một bong bóng vòng tròn đầy, hãy gọi mã này (đặt tên cho nó 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>
Bạn có thể phải điều chỉnh độ dày theo nhu cầu của bạn.
EDIT:
Đây là cách bố trí cho nút (đặt tên 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>
Trong Menu tạo mục:
<item
android:id="@+id/menu_messages"
android:showAsAction="always"
android:actionLayout="@layout/badge_layout"/>
Để onCreateOptionsMenu
tham khảo mục 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();
}
}
});
Sau khi nhận được thông báo cho tin nhắn, hãy đặt số đếm:
itemMessagesBadgeTextView.setText("" + count);
itemMessagesBadgeTextView.setVisibility(View.VISIBLE);
iconButtonMessages.setTextColor(getResources().getColor(R.color.white));
Mã này sử dụng Iconify-fontawgie .
compile 'com.joanzapata.iconify:android-iconify-fontawesome:2.1.+'
Tôi không thích ActionView
các giải pháp dựa trên, ý tưởng của tôi là:
TextView
, TextView
sẽ được điền bởi ứng dụngkhi bạn cần phải vẽ một MenuItem
:
2.1. bố trí thổi phồng
2.2. gọi measure()
& layout()
(nếu không view
sẽ là 0px x 0px, quá nhỏ cho hầu hết các trường hợp sử dụng)
2.3. đặt TextView
văn bản
2.4. tạo "ảnh chụp màn hình" của chế độ xem
2.6. đặt MenuItem
biểu tượng dựa trên bitmap được tạo trên 2.4
lợi nhuận!
vì vậy, kết quả nên giống như
<?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
nền của màu xanh lá cây đó,
@drawable/ic_menu_gallery
không thực sự cần thiết ở đây, nó chỉ để xem trước kết quả của bố cục trong IDE.
thêm mã vào 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;
}
Thực hiện phương thức xây dựng biểu tượng:
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);
}
Mã hoàn chỉnh có tại đây: https://github.com/cvoronin/ActionBarMothyItemCorer
Ok, để giải pháp @AndrewS hoạt động với thư viện 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();
}
Phần còn lại của mã là như nhau.
android:actionLayout
để app:actionLayout
nó workes như nét duyên dáng.
Hãy thử xem câu trả lời cho những câu hỏi này, đặc biệt là câu hỏi thứ hai có mã mẫu:
Cách triển khai các giá trị động trên mục menu trong Android
Làm cách nào để nhận văn bản trên Biểu tượng ActionBar?
Từ những gì tôi thấy, bạn sẽ cần tạo ActionView
triển khai tùy chỉnh của riêng bạn . Một thay thế có thể là một tùy chỉnh Drawable
. Lưu ý rằng dường như không có triển khai riêng về số lượng thông báo cho Action Bar.
EDIT: Câu trả lời bạn đang tìm kiếm, với mã: Chế độ xem thông báo tùy chỉnh với triển khai mẫu
Drawable
s như đã thấy trong hai liên kết sau: stackoverflow.com/questions/6691818/
Drawable
thông qua một cái gì đó như liên kết ở đây và sau đó tạo một thuộc tính cho tùy chỉnh của bạn Drawable
có văn bản trên đó để bạn có thể tạo toàn bộ trong XML và phù hợp với nó như bạn muốn. Ngoài ra, bạn có thể thêm Drawable trong Java nếu điều này quá khó.
Khi bạn sử dụng thanh công cụ:
....
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);
}
và trong cuộc gọi dữ liệu tải của bạn refreshMothy ():
private void refreshMenu() {
comment_count.setVisibility(View.VISIBLE);
comment_count.setText("" + post_data.getComment_count());
}
Tôi tìm thấy một giải pháp rất tốt ở đây , tôi đang sử dụng nó với kotlin.
Đầu tiên, trong thư mục drawable bạn phải tạo 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>
Trong Activity_Main
Bố cục của bạn, một số như:
<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>
Và bạn có thể sửa đổi như:
btnBadge.setOnClickListener { view ->
Snackbar.make(view,"badge click", Snackbar.LENGTH_LONG) .setAction("Action", null).show()
txtBadge.text = "0"
}
Tôi tìm thấy cách tốt hơn để làm điều đó. nếu bạn muốn sử dụng một cái gì đó như thế này
Sử dụng phụ thuộc này
compile 'com.nex3z:notification-badge:0.1.0'
tạo một tệp xml trong drawable và lưu nó dưới dạng 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>
Bây giờ bất cứ nơi nào bạn muốn sử dụng huy hiệu đó đều sử dụng mã sau trong xml. với sự giúp đỡ của điều này, bạn sẽ có thể thấy huy hiệu đó ở góc trên bên phải của hình ảnh của bạn hoặc bất cứ điều gì.
<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>
Bây giờ cuối cùng trên yourFile.java sử dụng 2 điều đơn giản này .. 1) Xác định
NotificationBadge mBadge;
2) trong đó vòng lặp của bạn hoặc bất cứ thứ gì đang đếm số này sử dụng:
mBadge.setNumber(your_LoopCount);
ở đây, mBadge.setNumber(0)
sẽ không hiển thị bất cứ điều gì.
Hy vọng điều này giúp đỡ.