Разве BadgeDrawable не работает для представлений в FrameLayout, таких как кнопки, изображения, текстовые представления и т. Д. c.? - PullRequest
1 голос
/ 31 января 2020

У меня есть эта функция в моей основной деятельности, которая не отображает значок:

private fun setFindShiftBadge(state: HomeState) {
        val findShiftsBadge = BadgeDrawable.create(this)
        home_framelayout.foreground = findShiftsBadge
        findShiftsBadge.badgeGravity = BadgeDrawable.TOP_END
        findShiftsBadge.backgroundColor = resources.getColor(R.color.colorWhite)
        findShiftsBadge.badgeTextColor = resources.getColor(R.color.colorPrimary)
        findShiftsBadge.number = state.availableShifts.size
 }

В той же деятельности у меня есть эта функция, которая отображает значок:

private fun setMyPostedShiftBadge(state: HomeState) {
    val userShiftsBadge: BadgeDrawable =
        bottom_navigation_view.getOrCreateBadge(R.id.bottom_navigation_my_posted_shifts_text)
    userShiftsBadge.number = state.userShifts.size
    userShiftsBadge.backgroundColor = resources.getColor(R.color.colorPrimary)
} 

Теперь я понимаю, что вторая функция работает, потому что значок установлен в пределах BottomNavigationView. По иронии судьбы, BottomNavigationView расширяется FrameLayout. В документации Android: Добавьте BadgeDrawable в качестве ViewOverlay к желаемому представлению привязки, используя attachBadgeDrawable (BadgeDrawable, View, FrameLayout). Обновите координаты BadgeDrawable BadgeDrawable (центр и границы) на основе его привязки, используя updateBadgeCoordinates (View, ViewGroup).

Говорят, что использовать этот код, For API 18+ (APIs supported by ViewOverlay), который я использую в первой функции, которая не работает:

 BadgeDrawable badgeDrawable = BadgeDrawable.create(context);
 BadgeUtils.attachBadgeDrawable(badgeDrawable, anchor, null);

Я также пробовал это решение , но оно тоже не сработало. Я знаю, что есть обходные пути, такие как:

  1. Создание рисованного объекта и установка его на желаемом виде
  2. Размещение TextView внутри этого чертежа, который затем обновляется с номером Вы хотите
  3. Переключить видимость рисования, когда есть какие-либо числа.

Я на implementation 'com.google.android.material:material:1.2.0-alpha04'

Это кажется мне грязным, так как я знаю, что есть лучший способ сделать это. Я просто не могу понять это. Что мне не хватает? Это вообще возможно? Как вы смогли сделать это без необходимости писать обходной путь? Спасибо за ваше время! Будем рады учиться на ваших вопросах и ответах! Имейте фантазию c день!

Ответы [ 2 ]

1 голос
/ 31 января 2020

BottomNavigationView.getOrCreateBadge() не только назначает BadgeDrawable в качестве переднего плана Drawable, но также устанавливает границы для рисования. Без этого шага они остаются в (0,0,0,0), поэтому рисовать нечего.

Чтобы установить границы, давайте введем функцию расширения для BadgeDrawable

/**
 * Inspired by BadgeUtils in com.google.android.material library
 *
 * Sets the bounds of a BadgeDrawable 
 */
private fun BadgeDrawable.setBoundsFor(@NonNull anchor: View, @NonNull parent: FrameLayout){
    val rect = Rect()
    parent.getDrawingRect(rect)
    this.setBounds(rect)
    this.updateBadgeCoordinates(anchor, parent)
}

Используйте эту функцию вместе с BadgeDrawable для FrameLayout:

private fun setFindShiftBadge(state: HomeState) {
    val findShiftsBadge = BadgeDrawable.create(this)
    // configure the badge drawable
    findShiftsBadge.badgeGravity = BadgeDrawable.TOP_END
    findShiftsBadge.backgroundColor = resources.getColor(R.color.colorWhite)
    findShiftsBadge.badgeTextColor = resources.getColor(R.color.colorPrimary)
    findShiftsBadge.number = state.availableShifts.size
    // set bounds inside which it will be drawn
    findShiftsBadge.setBoundsFor(btn_badge, home_framelayout)
    // assign as foreground drawable
    home_framelayout.foreground = findShiftsBadge
}

screenshot

0 голосов
/ 19 марта 2020
  BadgeDrawable badgeDrawable = BadgeDrawable.create(this);
badgeDrawable.setNumber(15);

FrameLayout frameLayout = findViewById(R.id.framelayout);

ImageView imageView = findViewById(R.id.iv_center);

//core code
frameLayout.setForeground(badgeDrawable);
frameLayout.addOnLayoutChangeListener((v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {


    //either of the following two lines of code  work
    //badgeDrawable.updateBadgeCoordinates(imageView, frameLayout);
    BadgeUtils.attachBadgeDrawable(badgeDrawable, imageView, frameLayout);
});





<FrameLayout
    android:id="@+id/framelayout"
    android:layout_width="150dp"
    android:layout_height="150dp">

    <ImageView
        android:layout_gravity="center"
        android:id="@+id/iv_center"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:scaleType="fitXY"
        android:src="@drawable/ic_beard" />
</FrameLayout>
...