1
1
package com.rcttabview
2
2
3
+ import android.annotation.SuppressLint
3
4
import android.content.Context
5
+ import android.graphics.drawable.BitmapDrawable
6
+ import android.graphics.drawable.Drawable
7
+ import android.net.Uri
4
8
import android.view.Choreographer
5
9
import android.view.MenuItem
6
- import androidx.appcompat.content.res.AppCompatResources
10
+ import com.facebook.common.references.CloseableReference
11
+ import com.facebook.datasource.DataSources
12
+ import com.facebook.drawee.backends.pipeline.Fresco
13
+ import com.facebook.imagepipeline.image.CloseableBitmap
14
+ import com.facebook.imagepipeline.request.ImageRequestBuilder
7
15
import com.facebook.react.bridge.Arguments
16
+ import com.facebook.react.bridge.ReadableArray
8
17
import com.facebook.react.bridge.WritableMap
18
+ import com.facebook.react.views.imagehelper.ImageSource
19
+ import com.facebook.react.views.imagehelper.ImageSource.Companion.getTransparentBitmapImageSource
9
20
import com.google.android.material.bottomnavigation.BottomNavigationView
10
21
22
+
11
23
class ReactBottomNavigationView (context : Context ) : BottomNavigationView(context) {
12
24
private val ANIMATION_DURATION : Long = 300
25
+ private val icons: MutableMap <Int , ImageSource > = mutableMapOf ()
13
26
14
27
var items: MutableList <TabInfo >? = null
15
28
var onTabSelectedListener: ((WritableMap ) -> Unit )? = null
@@ -62,17 +75,10 @@ class ReactBottomNavigationView(context: Context) : BottomNavigationView(context
62
75
63
76
fun updateItems (items : MutableList <TabInfo >) {
64
77
this .items = items
65
- // TODO: This doesn't work with hot reload. It clears all menu items
66
- menu.clear()
67
78
items.forEachIndexed {index, item ->
68
- val menuItem = menu.add(0 , index, 0 , item.title)
69
- val iconResourceId = resources.getIdentifier(
70
- item.icon, " drawable" , context.packageName
71
- )
72
- if (iconResourceId != 0 ) {
73
- menuItem.icon = AppCompatResources .getDrawable(context, iconResourceId)
74
- } else {
75
- menuItem.setIcon(android.R .drawable.btn_star) // fallback icon
79
+ val menuItem = getOrCreateItem(index, item.title)
80
+ if (icons.containsKey(index)) {
81
+ menuItem.icon = getDrawable(icons[index]!! )
76
82
}
77
83
if (item.badge.isNotEmpty()) {
78
84
val badge = this .getOrCreateBadge(index)
@@ -84,6 +90,48 @@ class ReactBottomNavigationView(context: Context) : BottomNavigationView(context
84
90
}
85
91
}
86
92
93
+ private fun getOrCreateItem (index : Int , title : String ): MenuItem {
94
+ return menu.findItem(index) ? : menu.add(0 , index, 0 , title)
95
+ }
96
+
97
+ fun setIcons (icons : ReadableArray ? ) {
98
+ if (icons == null || icons.size() == 0 ) {
99
+ return
100
+ }
101
+
102
+ for (idx in 0 until icons.size()) {
103
+ val source = icons.getMap(idx)
104
+ var imageSource =
105
+ ImageSource (
106
+ context,
107
+ source.getString(" uri" ),
108
+ source.getDouble(" width" ),
109
+ source.getDouble(" height" ))
110
+ if (Uri .EMPTY == imageSource.uri) {
111
+ imageSource = getTransparentBitmapImageSource(context)
112
+ }
113
+ this .icons[idx] = imageSource
114
+
115
+ // Update existing item if exists.
116
+ menu.findItem(idx)?.let { menuItem ->
117
+ menuItem.icon = getDrawable(imageSource)
118
+ }
119
+ }
120
+ }
121
+
122
+ @SuppressLint(" UseCompatLoadingForDrawables" )
123
+ private fun getDrawable (imageSource : ImageSource ): Drawable {
124
+ val imageRequest = ImageRequestBuilder .newBuilderWithSource(imageSource.uri).build()
125
+ val dataSource = Fresco .getImagePipeline().fetchDecodedImage(imageRequest, context)
126
+ val result = DataSources .waitForFinalResult(dataSource) as CloseableReference <CloseableBitmap >
127
+ val bitmap = result.get().underlyingBitmap
128
+
129
+ CloseableReference .closeSafely(result)
130
+ dataSource.close()
131
+
132
+ return BitmapDrawable (resources, bitmap)
133
+ }
134
+
87
135
// Fixes issues with BottomNavigationView children layouting.
88
136
private fun measureAndLayout () {
89
137
measure(
0 commit comments