【问题标题】:NavigationView menu items with counter on the right右侧带有计数器的 NavigationView 菜单项
【发布时间】:2015-08-14 03:43:09
【问题描述】:

设计支持库 中的新 NavigationView 非常棒。

他们使用“menu-items”来显示选项。

但是如何在菜单项的右侧显示计数器

就像这张照片:

或喜欢在 GMail 应用中。

【问题讨论】:

  • 您可以尝试在您的菜单项中使用android:actionLayout。有一个将 TextView 边距设置为右侧的自定义布局。没试过。让我知道它是否有效。
  • actionLayout 如果设置会被忽略。
  • 被忽略是什么意思?
  • @Ewoks,您可以设置它,但没有任何反应。
  • @chrisonline 您期望发生什么,但没有?检查接受的答案,它可以正常工作,正如预期的那样

标签: android navigation-drawer material-design androiddesignsupport navigationview


【解决方案1】:

从 appcompat-v7 NavigationView 23 版本开始支持动作视图,因此很容易自己实现计数器。

  1. 创建柜台​​布局,即menu_counter.xml:

    <?xml version="1.0" encoding="utf-8"?>
    <TextView xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:gravity="center_vertical"
        android:textAppearance="@style/TextAppearance.AppCompat.Body2" />
    
  2. 在抽屉菜单 xml 中引用它,即menu/drawer.xml:

    <item
        ...
        app:actionLayout="@layout/menu_counter" />
    

注意你应该使用app命名空间,不要尝试使用android

您也可以使用MenuItem.setActionView() 方法手动设置操作视图。

  1. 查找菜单项并设置计数器:

    private void setMenuCounter(@IdRes int itemId, int count) {
        TextView view = (TextView) navigationView.getMenu().findItem(itemId).getActionView();
        view.setText(count > 0 ? String.valueOf(count) : null);
    }
    

请注意,如果您必须支持 Android 2.x 版本,则需要使用 MenuItemCompat

【讨论】:

  • 尽管有重力,但徽章内容(数字)总是与顶部对齐:“center_vertical”..我错过了什么吗?
  • @Ewoks,你可能错过了android:layout_height="match_parent"
  • 实际上是的.. 我希望如果我将重力和 layout_gravity 设置为 center_vertical 它将起作用,但是 TextView 会自动放置在某些 FrameLayout 中,如果高度未设置为 match_parent layout_gravity 没有效果。谢谢
  • 它工作得很好。但是上面的命令需要这么长时间才能获取代码。在导航代码之前添加方法 [setMenuCounter(menuitem ,notification_count);] 并传递参数以在导航屏幕中生成。现在它起作用了魅力
  • 确保添加&lt;menu ... xmlns:app="http://schemas.android.com/apk/res-auto" &gt;
【解决方案2】:

我的解决方法是传递一个具有不同背景的 SpannableString 作为 MenuItem 的新标题。

我知道这不是最好的解决方案,它也不是右对齐的,但它可以很好地用作计数器。像这样的:

NavigationView navigation = (NavigationView)findViewById(R.id.navigation);
Menu menuNav = navigation.getMenu();
MenuItem element = menuNav.findItem(R.id.item5);
String before = element.getTitle().toString();

String counter = Integer.toString(5);
String s = before + "   "+counter+" ";
SpannableString sColored = new SpannableString( s );

sColored.setSpan(new BackgroundColorSpan( Color.GRAY ), s.length()-(counter.length()+2), s.length(), 0);
sColored.setSpan(new ForegroundColorSpan( Color.WHITE ), s.length()-(counter.length()+2), s.length(), 0);


element.setTitle(sColored);

要改进计数器,here 你可以找到一个很好的答案来设置圆角

例子:

【讨论】:

  • 有截图吗?
【解决方案3】:

查看NavigationView 的源代码,它们目前不支持菜单项的任何自定义呈现(请参阅NavigationMenuPresenterNavigationMenuAdapter)。希望他们尽快公开更多功能,因为我想在菜单项上设置自定义字体,但如果不使用反射就无法做到。

【讨论】:

【解决方案4】:

我也想为柜台设计一个徽章图标。这个徽章是药丸形状的,可以用不同的颜色来区分重要的徽章和不重要的徽章。

为此,我创建了一个自定义视图徽章

class Badge @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyle: Int = 0,
    defStyleRes: Int = 0
) : LinearLayout(context, attrs, defStyle, defStyleRes) {
    private val badgeText: TextView
    private var important: Boolean

    init {
        inflate(context, R.layout.badge, this)
        badgeText = findViewById(R.id.badge)
        important = false
        isImportant(important)
        adjustVisibility()
    }

    fun setText(text: String) {
        badgeText.text = text
        adjustVisibility()
    }

    fun isImportant(isImportant: Boolean) {
        if (isImportant) {
            badgeText.backgroundTintList = ColorStateList.valueOf(
                ContextCompat.getColor(
                    context,
                    R.color.nav_badge_important
                )
            )
        } else {
            badgeText.backgroundTintList = ColorStateList.valueOf(
                ContextCompat.getColor(
                    context,
                    R.color.nav_badge_unimportant
                )
            )
        }
    }

    private fun adjustVisibility() {
        if (badgeText.text.isNullOrBlank() && this.visibility == VISIBLE) {
            this.visibility = INVISIBLE
        } else {
            this.visibility = VISIBLE
        }
    }
}

徽章的布局

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:orientation="vertical">

    <TextView
        android:id="@+id/badge"
        style="@style/BadgeStyle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</LinearLayout>

徽章的样式

<resources>
    <style name="BadgeStyle" parent="Widget.AppCompat.TextView">
        <item name="android:textSize">10sp</item>
        <item name="android:background">@drawable/badge_curved</item>
        <item name="android:textColor">@color/white</item>
    </style>
</resources>

徽章的可绘制对象

<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <corners android:radius="300dp" />
    <padding
        android:bottom="2dp"
        android:left="8dp"
        android:right="8dp"
        android:top="2dp" />
</shape>

对于每个能够显示徽章的菜单项,您需要将app:actionViewClass="com.example.ui.Badge" 添加到您的导航菜单。

Badge 类使您能够以编程方式设置徽章的文本和重要性。

private fun setupBadges(navView: NavigationView) {
    val badgesItemOne = navView.menu.findItem(R.id.nav_one).actionView as Badge
    val badgesItemTwo = navView.menu.findItem(R.id.nav_two).actionView as Badge
    val badgesItemThree = navView.menu.findItem(R.id.nav_three).actionView as Badge

    badgesItemOne.setText("6+")
    badgesItemOne.isImportant(true)
    badgesItemTwo.setText("2")
    badgesItemThree.setText("99+")
}

【讨论】:

    【解决方案5】:

    第 1 步:识别组项并添加“app:actionViewClass=android.widget.TextView”,如下所示:

    <menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    
    <group android:checkableBehavior="single">
    
        <item
            android:id="@+id/nav_recorder"
            app:actionViewClass="android.widget.TextView"
            android:icon="@drawable/ic_menu_gallery"
            android:title="Gallery" />
        <item
            android:id="@+id/nav_night_section"
            app:actionViewClass="android.widget.TextView"
            android:icon="@drawable/ic_menu_slideshow"
            android:title="Slideshow" />
    </group>
    

    第 2 步:声明 Navigation Drawer 菜单项并使用徽章值初始化该项

    //Create these objects above OnCreate()of your main activity
    TextView recorder,nightSection;
    
    //These lines should be added in the OnCreate() of your main activity
    recorder =(TextView) MenuItemCompat.getActionView(navigationView.getMenu().
            findItem(R.id.nav_recorder));
    
    recordSection=(TextView) MenuItemCompat.getActionView(navigationView.getMenu().
            findItem(R.id.nav_night_section));
    
    //This method will initialize the count value
    initializeCountDrawer();
    

    第 3 步:initializeCountDrawer() 可以在任何需要的地方调用。它还可以用于更新导航抽屉菜单项中的计数或徽章值。

    private void initializeCountDrawer(){
    
        //Gravity property aligns the text
        recorder.setGravity(Gravity.CENTER_VERTICAL);
        recorder.setTypeface(null, Typeface.BOLD);
        recorder.setTextColor(getResources().getColor(R.color.colorAccent));                
        recorder.setText("99+");
    
        slideshow.setGravity(Gravity.CENTER_VERTICAL);
        slideshow.setTypeface(null,Typeface.BOLD);
        slideshow.setTextColor(getResources().getColor(R.color.colorAccent));              
        //count is added     
       slideshow.setText("7");
    }
    

    【讨论】:

      猜你喜欢
      • 2015-12-13
      • 1970-01-01
      • 2017-10-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-02-24
      • 1970-01-01
      相关资源
      最近更新 更多