【问题标题】:Notification Badge On Action Item AndroidAndroid 操作项上的通知徽章
【发布时间】:2017-08-28 21:17:27
【问题描述】:

我想在放置在操作栏中的购物车图像上添加一个通知徽章并以编程方式对其进行操作。有什么帮助吗?

【问题讨论】:

  • 为了“帮助”您,我们需要查看您已经编写了哪些代码,然后让您解释哪些确切部分无法正常运行,然后让您解释您为研究、调试和修复所做的工作问题,然后让你解释在所有这些完成后你到底有什么困惑。
  • 我已经在菜单下使用 menu.xml 添加了购物车图像,我是布局设计的新手,所以如果有人向购物车添加东西或删除项目,我无法确定添加通知计数。

标签: android android-layout android-actionbar badge


【解决方案1】:

您可以通过为MenuItem 创建一个custom layoutActionBar 上显示自定义MenuItem。要设置自定义布局,您必须使用菜单项属性app:actionLayout

按照以下步骤在Cart 操作项上创建Badge。结果见附件image

  1. 使用ImageView(用于购物车图标)和TextView(用于计数值)创建自定义布局

布局/custom_action_item_layout.xml:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
    style="?attr/actionButtonStyle"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:clipToPadding="false"
    android:focusable="true">

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:src="@drawable/ic_action_cart"/>

    <TextView
        android:id="@+id/cart_badge"
        android:layout_width="20dp"
        android:layout_height="20dp"
        android:layout_gravity="right|end|top"
        android:layout_marginEnd="-5dp"
        android:layout_marginRight="-5dp"
        android:layout_marginTop="3dp"
        android:background="@drawable/badge_background"
        android:gravity="center"
        android:padding="3dp"
        android:textColor="@android:color/white"
        android:text="0"
        android:textSize="10sp"/>

</FrameLayout>
  1. 使用Shape 创建可绘制圆形badge 背景。

drawable/badge_background.xml:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval">

    <solid android:color="@android:color/holo_red_dark"/>
    <stroke android:color="@android:color/white" android:width="1dp"/>

</shape>
  1. custom layout 添加到菜单item

menu/main_menu.xml

<menu 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto" >

    <item
        android:id="@+id/action_cart"
        android:icon="@drawable/ic_action_cart"
        android:title="Cart"
        app:actionLayout="@layout/custom_action_item_layout"
        app:showAsAction="always"/>

</menu>
  1. 在您的 MainActivity 中,添加以下代码:

MainActivity.java:

public class MainActivity extends AppCompatActivity {
    ................
    ......................
    TextView textCartItemCount;
    int mCartItemCount = 10;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        .....................
        ............................
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.main_menu, menu);

        final MenuItem menuItem = menu.findItem(R.id.action_cart);

        View actionView = menuItem.getActionView();
        textCartItemCount = (TextView) actionView.findViewById(R.id.cart_badge);

        setupBadge();

        actionView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                onOptionsItemSelected(menuItem);
            }
        });

        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {

        switch (item.getItemId()) {

            case R.id.action_cart: {
                // Do something
                return true;
            }
        }
        return super.onOptionsItemSelected(item);
    }

    private void setupBadge() {

        if (textCartItemCount != null) {
            if (mCartItemCount == 0) {
                if (textCartItemCount.getVisibility() != View.GONE) {
                    textCartItemCount.setVisibility(View.GONE);
                }
            } else {
                textCartItemCount.setText(String.valueOf(Math.min(mCartItemCount, 99)));
                if (textCartItemCount.getVisibility() != View.VISIBLE) {
                    textCartItemCount.setVisibility(View.VISIBLE);
                }
            }
        }
    }

    ..................
    ..............................

}

输出:

【讨论】:

  • 自定义布局不会覆盖购物车徽标@Ferdous Ahamed
  • 这很有帮助。在 Xamarin.Android 上尝试了同样的方法,效果很好。
  • 使用menuItem.getActionView(),因为MenuItemCompat.getActionView(menuItem)已被弃用
  • @MNFS 在 main_menu.xml 中使用 app:actionLayout 而不是 android:actionLayout
  • @Nipun 哦……这是个错误。它应该是 main_menu。谢谢~
【解决方案2】:

也许solution 会更快更简单。 例如 XML:

<ru.nikartm.support.ImageBadgeView
android:id="@+id/ibv_icon2"
android:layout_width="80dp"
android:layout_height="80dp"
android:layout_marginTop="30dp"
android:layout_gravity="center"
android:padding="10dp"
app:ibv_badgeValue="100"
app:ibv_badgeTextSize="12sp"
app:ibv_fixedBadgeRadius="15dp"
app:ibv_badgeTextStyle="bold"
app:ibv_badgeTextColor="#ffffff"
app:ibv_badgeColor="#00ACC1"
app:ibv_badgeLimitValue="false"
android:src="@drawable/ic_shopping_cart" />

或以编程方式:

imageBadgeView.setBadgeValue(27)
            .setBadgeOvalAfterFirst(true)
            .setBadgeTextSize(16)
            .setMaxBadgeValue(999)
            .setBadgeTextFont(typeface)
            .setBadgeBackground(getResources().getDrawable(R.drawable.rectangle_rounded))
            .setBadgePosition(BadgePosition.BOTTOM_RIGHT)
            .setBadgeTextStyle(Typeface.NORMAL)
            .setShowCounter(true)
            .setBadgePadding(4);

我希望这会有所帮助。

【讨论】:

【解决方案3】:

使用Material Components for Android (1.3.0)。

val badge = BadgeDrawable.create(context)
BadgeUtils.attachBadgeDrawable(badge, toolbar, R.id.your_menu_item)

【讨论】:

  • 我收到错误 R.id.your_menu_item 需要框架布局,而不是 Id
  • 它不工作?
【解决方案4】:

通过赋予风格最简单的技巧。

        <TextView
                android:id="@+id/fabCounter"
                style="@style/Widget.Design.FloatingActionButton"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentEnd="true"
                android:layout_centerVertical="true"
                android:layout_marginEnd="10dp"
                android:padding="5dp"
                android:text="10"
                android:textColor="@android:color/black"
                android:textSize="14sp" />

【讨论】:

  • 请停止发送相同答案的垃圾邮件。相反,将问题标记为重复
  • 所有问题的含义不同,但解决方案相同。我对不同的问题给出了不同的答复,但我使用的是相同的图像。那有什么问题?
  • 如果所有问题都有相同的解决方案,则很可能它们是重复的问题,但措辞不同。将问题作为重复项关闭有助于未来的读者找到他们正在寻找的解决方案。现在,您的解决方案分布在 5 个以上的帖子中。如果你回来编辑它;或者人们发现错误,现在需要在所有 5 个位置进行更新。
【解决方案5】:

您可以使用Material Design徽章组件:

https://material.io/develop/android/components/badging

可在:implementation "com.google.android.material:material:1.3.0+"

【讨论】:

  • 我找不到任何教程
【解决方案6】:

创建自定义布局

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
    style="?attr/actionButtonStyle"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:clipToPadding="false"
    android:focusable="true">

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:src="@drawable/notifications_white"/>

    <TextView
        android:id="@+id/cart_badge"
        android:layout_width="20dp"
        android:layout_height="20dp"
        android:layout_marginLeft="55dp"
        android:layout_marginTop="3dp"
        android:background="@drawable/badge_background"
        android:gravity="center"
        android:padding="3dp"
        android:textColor="@android:color/white"
        android:text="0"
        android:textSize="10sp"
        android:visibility="gone"
        />

</FrameLayout>

创建徽章背景

<?xml version="1.0" encoding="utf-8"?>
    <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval">
        <solid android:color="@android:color/holo_red_dark"/>
        <stroke android:color="@android:color/white" android:width="1dp"/>
    </shape>

创建主菜单

<menu
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto" >

    <item
        android:id="@+id/action_cart"
        android:icon="@drawable/notifications_white"
        android:title="Cart"
        app:actionLayout="@layout/custom_layout"
        app:showAsAction="always"/>
</menu>

在 MainActivty.java 中

         int count = 0;
        TextView textCartItemCount;
    
/// build a method inside your MainActivity ////

     @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            getMenuInflater().inflate(R.menu.main_menu, menu);
    
            final MenuItem menuItem = menu.findItem(R.id.action_cart);
    
            View actionView = MenuItemCompat.getActionView(menuItem);
            textCartItemCount = (TextView) actionView.findViewById(R.id.cart_badge);
    
            setupBadge();
    
            actionView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    onOptionsItemSelected(menuItem);
                }
            });
    
            return true;
        }
    
        @Override
        public boolean onOptionsItemSelected(MenuItem item) {
    
            switch (item.getItemId()) {
    
                case R.id.action_cart: {
                    // Do something
                    return true;
                }
            }
            return super.onOptionsItemSelected(item);
        }
    
        private void setupBadge() {
    ///make a button in MainActivty layout
            button.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (count >= 0) {
                        textCartItemCount.setVisibility(View.VISIBLE);
                        textCartItemCount.setText(String.valueOf(++count));
                    } else {
                        textCartItemCount.setVisibility(View.GONE);`enter code here`
                    }
    
                }
            });

【讨论】:

    【解决方案7】:

    此答案是对 Ferdous Ahmed 给出的答案的修改,因为我无法对答案发表评论,这就是我发布新答案的原因。

    我只是转发MainActivity

    您可以通过为 MenuItem 创建自定义布局在 ActionBar 上显示自定义 MenuItem。要设置自定义布局,您必须使用菜单项属性 app:actionLayout。

    使用 ImageView(用于购物车图标)和 TextView(用于计数值)创建自定义布局

    MainActivity:

    public class MainActivity extends AppCompatActivity {
    ................
    ......................
    TextView textCartItemCount;
    int mCartItemCount = 10;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    
        .....................
        ............................
    }
    
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.main_menu, menu);
    
        **FrameLayout actionView = 
                      (FrameLayout)menu.findItem(R.id.action_cart).getActionView();
        textCartItemCount = (TextView) actionView.findViewById(R.id.cart_badge);**
    
        setupBadge();
    
        actionView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                onOptionsItemSelected(menuItem);
            }
        });
    
        return true;
    }
    
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
    
        switch (item.getItemId()) {
    
            case R.id.action_cart: {
                // Do something
                return true;
            }
        }
        return super.onOptionsItemSelected(item);
    }
    
    private void setupBadge() {
    
        if (textCartItemCount != null) {
            if (mCartItemCount == 0) {
                if (textCartItemCount.getVisibility() != View.GONE) {
                    textCartItemCount.setVisibility(View.GONE);
                }
            } else {
                textCartItemCount.setText(String.valueOf(Math.min(mCartItemCount, 99)));
                if (textCartItemCount.getVisibility() != View.VISIBLE) {
                    textCartItemCount.setVisibility(View.VISIBLE);
                }
            }
        }
    }
    
    ..................
    ..............................
    

    }

    【讨论】:

      【解决方案8】:

      使用https://github.com/nikartm/Image-Support 将负责创建具有更多选项(例如最大计数限制等)的徽章。

      layout_menu_cart.xml

      <?xml version="1.0" encoding="utf-8"?>
      <FrameLayout style="?attr/actionButtonStyle"
          xmlns:app="http://schemas.android.com/apk/res-auto"
          xmlns:android="http://schemas.android.com/apk/res/android"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:clipToPadding="false"
          android:focusable="true"
          android:clickable="true"
          xmlns:tools="http://schemas.android.com/tools">
      
          <ru.nikartm.support.ImageBadgeView
              android:id="@+id/cart_menu_icon"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:layout_gravity="center"
              android:src="@drawable/ic_shopping_cart_black"
              tools:ibv_badgeValue="101"
              app:ibv_maxBadgeValue="99"
              app:ibv_badgeTextSize="7sp"
              app:ibv_fixedBadgeRadius="7dp"
              app:ibv_badgeTextStyle="bold"
              app:ibv_badgeTextColor="#ffffff"
              app:ibv_badgeColor="@color/colorAccent"
              app:ibv_badgeLimitValue="true" />
      
      </FrameLayout>
      

      main_menu.xml

      <?xml version="1.0" encoding="utf-8"?>
      <menu xmlns:android="http://schemas.android.com/apk/res/android"
          xmlns:app="http://schemas.android.com/apk/res-auto">
          <item
              android:id="@+id/menu_cart"
              android:title="Cart"
              android:icon="@drawable/ic_shopping_cart_black"
              app:actionLayout="@layout/layout_menu_cart"
              app:showAsAction="always"/>
      </menu>
      

      YourActivity.kt

      val menuItem = menu.findItem(R.id.menu_cart) as MenuItem
      val actionView = menuItem.actionView
      
      actionView.findViewById<ImageBadgeView>(R.id.cart_menu_icon).badgeValue = count
      

      【讨论】:

        【解决方案9】:

        按照以下步骤进行

        1. 实现 'com.nex3z:notification-badge:1.0.4' 在您的 build.gradle (app) 中实现上述工件

        2. 创建菜单文件和一个名为visitdetails.xml 的资源文件。请注意,您可以为您的任何首选名称命名。

        <?xml version="1.0" encoding="utf-8"?>
        <menu xmlns:android="http://schemas.android.com/apk/res/android"
            xmlns:app="http://schemas.android.com/apk/res-auto"
            app:menu="@menu/attendant_menu">
        
            <item
                android:id="@+id/action_notifications"
                android:title="Search"
                android:icon="@drawable/ic_baseline_accessible_24"
                app:showAsAction="always"
                app:actionLayout="@layout/action_bar_notification" />
        
        </menu>
        
        1. 在布局文件中创建 action_bar_notification.xml。
        <?xml version="1.0" encoding="utf-8"?>
        <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
            xmlns:app="http://schemas.android.com/apk/res-auto"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            style="@android:style/Widget.ActionButton">
        
            <ImageView
                android:id="@+id/icon_images"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:src="@drawable/ic_baseline_accessible_24"/>
        
            <com.nex3z.notificationbadge.NotificationBadge
                android:id="@+id/badge"
                android:layout_width="28dp"
                android:layout_height="28dp"
                app:nbMaxTextLength="2"
                android:layout_toRightOf="@+id/icon_images"
                android:textColor="@color/white"
                android:layout_alignTop="@+id/icon_images"
                android:layout_marginTop="-12dp"
                android:layout_marginLeft="-10dp"
                />
        
        </RelativeLayout>
        
        1. 请注意,我正在使用视图绑定。将工具栏添加到您的活动或片段 xml。
         <?xml version="1.0" encoding="utf-8"?>
        <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
            xmlns:app="http://schemas.android.com/apk/res-auto"
            xmlns:tools="http://schemas.android.com/tools"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="@color/white"
            android:orientation="vertical"
            tools:context="">
        
            <androidx.appcompat.widget.Toolbar
                android:id="@+id/_customers_toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                android:background="@color/white"
                android:elevation="4dp"
                android:theme="@style/AppTheme.Toolbar"
                app:titleTextColor="@color/white"
                app:subtitleTextAppearance="@font/roboto_mediumitalic"
                app:subtitleTextColor="@color/white"
                app:navigationIcon="@drawable/ic_baseline_arrow_back_24"
                />
        </RelativeLayout>
        

        请注意,工具栏 ID 是 @+id/_customers_toolbar,我使用 setSupportActionBar(binding.CustomersToolbar) 进行绑定

        1. 编码期望。将此 setSupportActionBar(binding.CustomersToolbar) 添加到您的 onCreate
        override fun onCreate(savedInstanceState: Bundle?) {
        setSupportActionBar(binding.CustomersToolbar)
        }
        
        class UrAvtivityName : AppCompatActivity() {
        
          var item_Notification: MenuItem? = null
          var notificationBadgeView: View? = null
          var notificationBadge: NotificationBadge? = null
        
          override fun onCreate(savedInstanceState: Bundle?) {
                super.onCreate(savedInstanceState)
                setSupportActionBar(binding.CustomersToolbar)
          }
        
          override fun onCreateOptionsMenu(menu: Menu?): Boolean {
                menuInflater.inflate(R.menu.visitdetails, menu)
                item_Notification = menu!!.findItem(R.id.action_notifications)
                notificationBadgeView = item_Notification!!.actionView
                notificationBadge = notificationBadgeView!!.findViewById(R.id.badge) as NotificationBadge
        
               notificationBadgeView!!.setOnClickListener {
        
                }
        
                setupBadge()
                return true
            }
        
            private fun setupBadge() {
                
                 if (it == 0) {
                    notificationBadge!!.isVisible = false
                    return
                 }
                 notificationBadge!!.isVisible = true
                 notificationBadge!!.setText("2")
            }
        }
        

        【讨论】:

          【解决方案10】:
          val cartCount = Utility.getPreference(MainApplication.instance.getContext(), Constants.PREF_CART_COUNT)
                  Log.e("cart_count", cartCount)
                  if (cartCount.isNotEmpty()) {
                      val rl = RelativeLayout(this)
                      val paramsRR = LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)
                      paramsRR.gravity = Gravity.CENTER
                      rl.layoutParams = paramsRR
          
                      val iv = ImageView(this)
                      iv.loadFromUrl(iconUrl[i])
                      val params = LinearLayout.LayoutParams(getPixel(24f).toInt(), getPixel(23f).toInt())
                      params.setMargins(getPixel(10f).toInt(), 0, getPixel(10f).toInt(), 0)
                      params.gravity = Gravity.CENTER
                      iv.setPadding(4, 4, 4, 4)
                      iv.layoutParams = params
          
                      val tv = TextView(this)
                      val paramsRl = LinearLayout.LayoutParams(getPixel(12f).toInt(), getPixel(12f).toInt())
                      paramsRl.setMargins(getPixel(25f).toInt(), 0, getPixel(10f).toInt(), 0)
                      params.gravity = Gravity.RIGHT
                      tv.setPadding(8, 0, 4, 8)
                      tv.text = cartCount
                      tv.setTextSize(8f)
                      tv.setTextColor(Color.parseColor("#E31119"))
                      tv.setBackgroundResource(R.drawable.badge_background)
                      tv.layoutParams = paramsRl
          
                      rl.addView(iv)
                      rl.addView(tv)
          
                      ll_options_items ?.addView(rl)
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2022-12-14
            • 1970-01-01
            • 2020-12-27
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多