J'essaie d'ajouter un badge à l'élément BottomNavigationView
sans utiliser de bibliothèque, mais d'une manière ou d'une autre, la BottomNavigationView
ne montre pas le badge (custom_view)
main_view.xml:
<RelativeLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
xmlns:tools="http://schemas.Android.com/tools"
xmlns:app="http://schemas.Android.com/apk/res-auto"
Android:id="@+id/activity_main"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:paddingBottom="@dimen/activity_vertical_margin"
Android:paddingLeft="@dimen/activity_horizontal_margin"
Android:paddingRight="@dimen/activity_horizontal_margin"
Android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.hrskrs.test.MainActivity">
<FrameLayout
Android:id="@+id/container"
Android:layout_width="match_parent"
Android:layout_height="match_parent" />
<Android.support.design.widget.BottomNavigationView
Android:id="@+id/bottom_navigation"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:layout_alignParentBottom="true"
app:itemBackground="@color/colorPrimary"
app:itemIconTint="@color/colorAccent"
app:itemTextColor="@color/colorPrimaryDark"
app:menu="@menu/bottom_navigation_main" />
</RelativeLayout>
bottom_navigation_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/item_test"
Android:icon="@mipmap/ic_launcher"
Android:title="action1"
app:showAsAction="always" />
<item
Android:enabled="true"
Android:icon="@mipmap/ic_launcher"
Android:title="action2"
app:showAsAction="ifRoom" />
<item
Android:enabled="true"
Android:icon="@mipmap/ic_launcher"
Android:title="action3"
app:showAsAction="ifRoom" />
</menu>
Activité prolongée à partir de AppCompatActivity
:
@Override
public boolean onCreateOptionsMenu(Menu menu) {
menu = bottomNavigationView.getMenu();
menu.clear();
getMenuInflater().inflate(R.menu.bottom_navigation_main, menu);
MenuItem item = menu.findItem(R.id.item_test);
item = MenuItemCompat.setActionView(item, R.layout.custom_view);
RelativeLayout badgeWrapper = (RelativeLayout) MenuItemCompat.getActionView(item);
TextView textView = (TextView) badgeWrapper.findViewById(R.id.txtCount);
textView.setText("99+");
return super.onCreateOptionsMenu(menu);
}
custom_view.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
style="@Android:style/Widget.ActionButton"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:background="@Android:color/transparent"
Android:clickable="true"
Android:gravity="center"
Android:orientation="vertical">
<ImageView
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:contentDescription="Notification Icon"
Android:gravity="center"
Android:src="@mipmap/ic_launcher" />
<TextView xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:id="@+id/txtCount"
Android:gravity="right"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:background="@drawable/ic_badge"
Android:text="55"
Android:textColor="#ffffffff"
Android:textSize="12sp" />
</RelativeLayout>
Au lieu d'afficher (badge) custom_view
, l'élément en question est affiché uniquement:
Ci-dessous, vous pouvez voir en mode débogage que la view
à laquelle vous avez accédé est la bonne et qu'elle est définie correctement. Cependant, d'une manière ou d'une autre, la BottomNavigationView
n'est pas invalidée:
J'ai réussi à faire BottomNavigationView avec le badge. Voici mon code (Kotlin).
Ceci est le panneau (hérité de BottomNavigationView)
/** Bottom menu with badge */
class AdvancedBottomNavigationView(context: Context, attrs: AttributeSet) : BottomNavigationView(context, attrs) {
private companion object {
const val BADGE_MIN_WIDTH = 16 // [dp]
const val BADGE_MARGIN_TOP = 5 // [dp]
const val BADGE_MARGIN_LEFT = 15 // [dp]
}
@Inject internal lateinit var uiCalculator: UICalculatorInterface
private val bottomMenuView: BottomNavigationMenuView
init {
// Get access to internal menu
val field = BottomNavigationView::class.Java.getDeclaredField("mMenuView")
field.isAccessible = true
bottomMenuView = field.get(this) as BottomNavigationMenuView
App.injections.presentationLayerComponent!!.inject(this)
@SuppressLint("CustomViewStyleable")
val a = context.obtainStyledAttributes(attrs, R.styleable.advanced_bottom_navigation_bar)
val badgeLayoutId = a.getResourceId(R.styleable.advanced_bottom_navigation_bar_badge_layout, -1)
a.recycle()
initBadges(badgeLayoutId)
}
/**
* [position] index of menu item */
fun setBadgeValue(position: Int, count: Int) {
val menuView = bottomMenuView
val menuItem = menuView.getChildAt(position) as BottomNavigationItemView
val badge = menuItem.findViewById(R.id.bottom_bar_badge)
val badgeText = menuItem.findViewById(R.id.bottom_bar_badge_text) as TextView
if (count > 0) {
badgeText.text = count.toString()
badge.visibility = View.VISIBLE
} else {
badge.visibility = View.GONE
}
}
/**
* Select menu item
* [position] index of menu item to select
*/
fun setSelected(position: Int) = bottomMenuView.getChildAt(position).performClick()
private fun initBadges(badgeLayoutId: Int) {
// Adding badges to each Item
val menuView = bottomMenuView
val totalItems = menuView.childCount
val oneItemAreaWidth = uiCalculator.getScreenSize(context).first / totalItems
val marginTop = uiCalculator.dpToPixels(context, BADGE_MARGIN_TOP)
val marginLeft = uiCalculator.dpToPixels(context, BADGE_MARGIN_LEFT)
for (i in 0 until totalItems) {
val menuItem = menuView.getChildAt(i) as BottomNavigationItemView
// Add badge to every item
val badge = View.inflate(context, badgeLayoutId, null) as FrameLayout
badge.visibility = View.GONE
badge.minimumWidth = uiCalculator.dpToPixels(context, BADGE_MIN_WIDTH)
val layoutParam = FrameLayout.LayoutParams(
FrameLayout.LayoutParams.WRAP_CONTENT,
FrameLayout.LayoutParams.WRAP_CONTENT)
layoutParam.gravity = Gravity.START
layoutParam.setMargins(oneItemAreaWidth / 2 + marginLeft, marginTop, 0, 0)
menuItem.addView(badge, layoutParam)
}
}
}
C'est un fichier attr.xml avec des options pour ce composant:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="advanced_bottom_navigation_bar">
<attr name="badge_layout" format="reference|integer" />
</declare-styleable>
</resources>
Fond pour le badge du dossier pouvant être tiré:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:Android="http://schemas.Android.com/apk/res/Android">
<item>
<shape>
<solid Android:color="#ff0000" />
<corners Android:radius="10dp" />
</shape>
</item>
</selector>
Insigne lui-même:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
Android:id="@+id/bottom_bar_badge"
Android:layout_height="20dp"
Android:layout_width="20dp"
xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:background="@drawable/bcg_badge"
>
<TextView
Android:id="@+id/bottom_bar_badge_text"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:text="1"
Android:textSize="10sp"
Android:textColor="@Android:color/white"
xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:textAlignment="center"
Android:layout_gravity="center"/>
</FrameLayout>
Et voici un exemple d'utilisation dans votre code:
<?xml version="1.0" encoding="utf-8"?>
<Android.support.constraint.ConstraintLayout
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"
tools:context="su.ivcs.ucim.presentationLayer.userStories.mainScreen.view.MainActivity">
<su.ivcs.ucim.presentationLayer.common.advancedBottomNavigationView.AdvancedBottomNavigationView
Android:id="@+id/bottom_navigation"
Android:layout_width="0dp"
Android:layout_height="wrap_content"
Android:layout_alignParentBottom="true"
app:itemBackground="@Android:color/white"
app:itemIconTint="@color/main_screen_tabs_menu_items"
app:itemTextColor="@color/main_screen_tabs_menu_items"
app:menu="@menu/main_screen_tabs_menu"
app:badge_layout = "@layout/common_badge"
app:layout_constraintTop_toBottomOf="@+id/fragmentsContainer"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
/>
</Android.support.constraint.ConstraintLayout>
J'espère que ceci vous aide.
@hrskrs Essayez d’ajouter une altitude plus élevée à votre txtCount ou à votre badgeWrapper lui-même. BottomNavigationView
semble avoir une altitude plus élevée que les vues à l’écran.
J'ai eu du mal à montrer des badges sur les articles BottomNavigationView
. Mon badge (sans aucune valeur de texte) faisant partie du dessinable lui-même est devenu gris lorsque l'utilisateur a cliqué sur un autre élément ou est devenu la même couleur définie dans la teinte (si non défini est colorPrimary). Je pense que vous rencontrerez le même problème que je rencontrais avec la coloration du badge/compteur en haut de l'élément de menu de BottomNavigationView
car la couleur de teinte sera appliquée à l'article lui-même et votre badge faisant partie de MenuItem
prendra la teinte (devient gris lorsque vous appuyez sur un autre élément que vous ne voudrez plus, je suppose).
Découvrez ma réponse ici: Existe-t-il un moyen d’afficher un badge de notification dans les éléments de menu officiels de Google BottomNavigationView introduits dans l’API 25?
J'ai utilisé un ImageView
pour un badge mais vous pouvez avoir votre badgeWrapper RelativeView
à la place de ImageView.