Skip to content

Commit 79796e0

Browse files
committed
add examples, make loading async on Android
1 parent 24c2c00 commit 79796e0

16 files changed

+144
-92
lines changed

android/build.gradle

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,8 +123,6 @@ dependencies {
123123
kapt "com.github.bumptech.glide:compiler:${GLIDE_VERSION}"
124124

125125
api 'com.caverock:androidsvg-aar:1.4'
126-
// implementation 'com.github.bumptech.glide:glide:4.15.1'
127-
// implementation 'com.github.bumptech.glide:svg:4.15.1'
128126
}
129127

130128
if (isNewArchitectureEnabled()) {

android/src/main/java/com/rcttabview/RCTTabView.kt

Lines changed: 36 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.rcttabview
22

3+
import android.annotation.SuppressLint
34
import android.content.Context
45
import android.content.res.ColorStateList
56
import android.graphics.Typeface
@@ -16,9 +17,7 @@ import android.view.View
1617
import android.view.ViewGroup
1718
import android.widget.TextView
1819
import androidx.appcompat.content.res.AppCompatResources
19-
import androidx.core.graphics.drawable.DrawableCompat
2020
import com.bumptech.glide.load.DataSource
21-
import com.bumptech.glide.load.DecodeFormat
2221
import com.bumptech.glide.load.engine.GlideException
2322
import com.bumptech.glide.request.RequestListener
2423
import com.bumptech.glide.request.target.Target
@@ -30,8 +29,6 @@ import com.facebook.react.modules.core.ReactChoreographer
3029
import com.facebook.react.views.imagehelper.ImageSource
3130
import com.facebook.react.views.text.ReactTypefaceUtils
3231
import com.google.android.material.bottomnavigation.BottomNavigationView
33-
import kotlinx.coroutines.Dispatchers
34-
import kotlinx.coroutines.runBlocking
3532

3633

3734
class ReactBottomNavigationView(context: Context) : BottomNavigationView(context) {
@@ -73,6 +70,7 @@ class ReactBottomNavigationView(context: Context) : BottomNavigationView(context
7370
override fun requestLayout() {
7471
super.requestLayout()
7572
@Suppress("SENSELESS_COMPARISON") // layoutCallback can be null here since this method can be called in init
73+
7674
if (!isLayoutEnqueued && layoutCallback != null) {
7775
isLayoutEnqueued = true
7876
// we use NATIVE_ANIMATED_MODULE choreographer queue because it allows us to catch the current
@@ -106,7 +104,9 @@ class ReactBottomNavigationView(context: Context) : BottomNavigationView(context
106104
val menuItem = getOrCreateItem(index, item.title)
107105
menuItem.isVisible = !item.hidden
108106
if (icons.containsKey(index)) {
109-
menuItem.icon = getDrawable(icons[index]!!)
107+
getDrawable(icons[index]!!) {
108+
menuItem.icon = it
109+
}
110110
}
111111

112112
if (item.badge.isNotEmpty()) {
@@ -154,7 +154,9 @@ class ReactBottomNavigationView(context: Context) : BottomNavigationView(context
154154

155155
// Update existing item if exists.
156156
menu.findItem(idx)?.let { menuItem ->
157-
menuItem.icon = getDrawable(imageSource)
157+
getDrawable(imageSource) {
158+
menuItem.icon = it
159+
}
158160
}
159161
}
160162
}
@@ -173,38 +175,35 @@ class ReactBottomNavigationView(context: Context) : BottomNavigationView(context
173175
itemRippleColor = color
174176
}
175177

176-
private fun getDrawable(imageSource: ImageSource): Drawable? {
177-
val uri = imageSource.uri.toString()
178-
val isSvg = uri.contains(".svg", ignoreCase = true)
179-
Log.d("ReactBottomNav", "Loading image: $uri, isSvg: $isSvg")
180-
181-
return try {
182-
runBlocking(Dispatchers.IO) {
183-
val drawable = GlideApp.with(context)
184-
.`as`(Drawable::class.java)
185-
.load(imageSource.uri)
186-
.apply {
187-
if (isSvg) {
188-
override(200, 200)
189-
}
190-
}
191-
.submit()
192-
.get()
193-
194-
// Make the drawable tintable
195-
if (isSvg && drawable != null) {
196-
DrawableCompat.wrap(drawable.mutate()).apply {
197-
DrawableCompat.setTintList(this, null) // Clear any existing tint
198-
alpha = 255
199-
}
200-
} else {
201-
drawable
178+
@SuppressLint("CheckResult")
179+
private fun getDrawable(imageSource: ImageSource, onDrawableReady: (Drawable?) -> Unit) {
180+
GlideApp.with(context)
181+
.`as`(Drawable::class.java)
182+
.load(imageSource.uri)
183+
.listener(object : RequestListener<Drawable> {
184+
override fun onLoadFailed(
185+
e: GlideException?,
186+
model: Any?,
187+
target: Target<Drawable>,
188+
isFirstResource: Boolean
189+
): Boolean {
190+
Log.e("RCTTabView", "Error loading image: ${imageSource.uri}", e)
191+
return false
202192
}
203-
}
204-
} catch (e: Exception) {
205-
Log.e("ReactBottomNav", "Error loading image: $uri", e)
206-
null
207-
}
193+
194+
override fun onResourceReady(
195+
resource: Drawable,
196+
model: Any,
197+
target: Target<Drawable>?,
198+
dataSource: DataSource,
199+
isFirstResource: Boolean
200+
): Boolean {
201+
// Update images on the main queue.
202+
post { onDrawableReady(resource) }
203+
return true
204+
}
205+
})
206+
.submit()
208207
}
209208

210209
override fun onDetachedFromWindow() {

android/src/main/java/com/rcttabview/SVGDrawableTranscoder.kt

Lines changed: 0 additions & 44 deletions
This file was deleted.

android/src/main/java/com/rcttabview/SVGDecoder.kt renamed to android/src/main/java/com/rcttabview/svg/SVGDecoder.kt

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package com.rcttabview
1+
package com.rcttabview.svg
22

33
import com.bumptech.glide.load.Options
44
import com.bumptech.glide.load.ResourceDecoder
@@ -9,24 +9,29 @@ import com.caverock.androidsvg.SVGParseException
99
import java.io.IOException
1010
import java.io.InputStream
1111

12+
1213
class SVGDecoder : ResourceDecoder<InputStream, SVG> {
1314
override fun handles(source: InputStream, options: Options) = true
1415

16+
companion object {
17+
const val DEFAULT_SIZE = 40f
18+
}
19+
1520
@Throws(IOException::class)
1621
override fun decode(source: InputStream, width: Int, height: Int, options: Options): Resource<SVG>? {
1722
return try {
1823
val svg: SVG = SVG.getFromInputStream(source)
19-
// Use document width and height if view box is not set.
20-
// Later, we will override the document width and height with the dimensions of the native view.
24+
// Taken from https://github.com/expo/expo/blob/215d8a13a7ef3f0b36b14eead41291e2d2d6cd0c/packages/expo-image/android/src/main/java/expo/modules/image/svg/SVGDecoder.kt#L28
2125
if (svg.documentViewBox == null) {
2226
val documentWidth = svg.documentWidth
2327
val documentHeight = svg.documentHeight
2428
if (documentWidth != -1f && documentHeight != -1f) {
2529
svg.setDocumentViewBox(0f, 0f, documentWidth, documentHeight)
2630
}
2731
}
28-
svg.documentWidth = width.toFloat()
29-
svg.documentHeight = height.toFloat()
32+
33+
svg.documentWidth = DEFAULT_SIZE
34+
svg.documentHeight = DEFAULT_SIZE
3035
SimpleResource(svg)
3136
} catch (ex: SVGParseException) {
3237
throw IOException("Cannot load SVG from stream", ex)
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package com.rcttabview.svg
2+
3+
import android.content.Context
4+
import android.graphics.Bitmap
5+
import android.graphics.Canvas
6+
import android.graphics.drawable.BitmapDrawable
7+
import android.graphics.drawable.Drawable
8+
import android.graphics.drawable.PictureDrawable
9+
import com.bumptech.glide.load.Options
10+
import com.bumptech.glide.load.engine.Resource
11+
import com.bumptech.glide.load.resource.SimpleResource
12+
import com.bumptech.glide.load.resource.transcode.ResourceTranscoder
13+
import com.caverock.androidsvg.SVG
14+
15+
class SVGDrawableTranscoder(val context: Context) : ResourceTranscoder<SVG?, Drawable> {
16+
override fun transcode(toTranscode: Resource<SVG?>, options: Options): Resource<Drawable> {
17+
val svg = toTranscode.get()
18+
val picture = svg.renderToPicture()
19+
val drawable = PictureDrawable(picture)
20+
21+
val returnedBitmap = Bitmap.createBitmap(
22+
drawable.intrinsicWidth,
23+
drawable.intrinsicHeight,
24+
Bitmap.Config.ARGB_8888
25+
)
26+
27+
val canvas = Canvas(returnedBitmap)
28+
canvas.drawPicture(drawable.picture)
29+
val bitMapDrawable = BitmapDrawable(context.resources, returnedBitmap)
30+
return SimpleResource(bitMapDrawable)
31+
}
32+
}

android/src/main/java/com/rcttabview/TabViewGlideModule.kt renamed to android/src/main/java/com/rcttabview/svg/TabViewGlideModule.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package com.rcttabview
1+
package com.rcttabview.svg
22

33
import android.content.Context
44
import android.graphics.drawable.Drawable
Lines changed: 1 addition & 0 deletions
Loading
Lines changed: 1 addition & 0 deletions
Loading

example/assets/icons/newspaper.svg

Lines changed: 1 addition & 0 deletions
Loading
Lines changed: 1 addition & 0 deletions
Loading

0 commit comments

Comments
 (0)