or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

animatedimage.mdindex.mdpreview.mdresources.mdsplitpane.md

animatedimage.mddocs/

0

# Animated Images

1

2

Cross-platform animated image support with automatic format detection and platform-optimized loading for GIFs and other animated formats, providing seamless animation playback in Compose applications.

3

4

## Capabilities

5

6

### AnimatedImage Type

7

8

Core animated image type with platform-specific implementations.

9

10

```kotlin { .api }

11

/**

12

* Platform-specific animated image representation

13

* Handles frame-based animations with proper timing and looping

14

*/

15

expect class AnimatedImage

16

```

17

18

**Platform Notes:**

19

- **Desktop**: Uses Skia `Codec` for efficient frame-based animation

20

- **Other platforms**: Platform-specific implementations for optimal performance

21

22

### Image Loading Functions

23

24

Load animated images from various sources with automatic format detection.

25

26

```kotlin { .api }

27

/**

28

* Load an animated image from a path (network URL or local file)

29

* Automatically detects if the path is a network URL or local file path

30

* @param path URL or file path to the animated image

31

* @return AnimatedImage instance ready for animation

32

*/

33

expect suspend fun loadAnimatedImage(path: String): AnimatedImage

34

35

/**

36

* Load an animated image from application resources

37

* @param path Resource path within the application bundle

38

* @return AnimatedImage instance ready for animation

39

*/

40

expect suspend fun loadResourceAnimatedImage(path: String): AnimatedImage

41

```

42

43

**Usage Examples:**

44

45

```kotlin

46

import org.jetbrains.compose.animatedimage.*

47

48

@Composable

49

fun AnimatedImageDemo() {

50

var animatedImage by remember { mutableStateOf<AnimatedImage?>(null) }

51

52

// Load from network

53

LaunchedEffect(Unit) {

54

animatedImage = loadAnimatedImage("https://example.com/animation.gif")

55

}

56

57

// Load from resources

58

LaunchedEffect(Unit) {

59

animatedImage = loadResourceAnimatedImage("animations/spinner.gif")

60

}

61

62

animatedImage?.let { image ->

63

Image(

64

bitmap = image.animate(),

65

contentDescription = "Animated GIF",

66

modifier = Modifier.size(200.dp)

67

)

68

}

69

}

70

```

71

72

### Animation Playback

73

74

Convert animated images to displayable bitmaps with automatic frame progression.

75

76

```kotlin { .api }

77

/**

78

* Animate the loaded image, returning the current frame as ImageBitmap

79

* Handles frame timing and looping automatically

80

* @return Current frame as ImageBitmap for display in Image composable

81

*/

82

@Composable

83

expect fun AnimatedImage.animate(): ImageBitmap

84

```

85

86

**Usage Examples:**

87

88

```kotlin

89

@Composable

90

fun LoadingSpinner() {

91

var spinner by remember { mutableStateOf<AnimatedImage?>(null) }

92

93

LaunchedEffect(Unit) {

94

spinner = loadResourceAnimatedImage("loading-spinner.gif")

95

}

96

97

Box(

98

modifier = Modifier.fillMaxSize(),

99

contentAlignment = Alignment.Center

100

) {

101

spinner?.let {

102

Image(

103

bitmap = it.animate(), // Automatically progresses through frames

104

contentDescription = "Loading...",

105

modifier = Modifier.size(48.dp)

106

)

107

} ?: CircularProgressIndicator() // Fallback while loading

108

}

109

}

110

```

111

112

### Utility Extensions

113

114

Additional utilities for working with animated images.

115

116

```kotlin { .api }

117

/**

118

* A blank 1x1 pixel ImageBitmap for placeholder usage

119

*/

120

val ImageBitmap.Companion.Blank: ImageBitmap

121

```

122

123

**Usage Examples:**

124

125

```kotlin

126

@Composable

127

fun AnimatedImageWithPlaceholder(imageUrl: String) {

128

var animatedImage by remember { mutableStateOf<AnimatedImage?>(null) }

129

var isLoading by remember { mutableStateOf(true) }

130

131

LaunchedEffect(imageUrl) {

132

isLoading = true

133

try {

134

animatedImage = loadAnimatedImage(imageUrl)

135

} catch (e: Exception) {

136

// Handle loading error

137

} finally {

138

isLoading = false

139

}

140

}

141

142

Image(

143

bitmap = when {

144

isLoading -> ImageBitmap.Blank

145

animatedImage != null -> animatedImage!!.animate()

146

else -> ImageBitmap.Blank // Error state

147

},

148

contentDescription = "Animated image",

149

modifier = Modifier.size(150.dp)

150

)

151

}

152

```

153

154

### Advanced Usage Patterns

155

156

#### Conditional Animation

157

158

```kotlin

159

@Composable

160

fun ConditionalAnimation(shouldAnimate: Boolean) {

161

var animatedImage by remember { mutableStateOf<AnimatedImage?>(null) }

162

var staticImage by remember { mutableStateOf<ImageBitmap?>(null) }

163

164

LaunchedEffect(Unit) {

165

animatedImage = loadAnimatedImage("animation.gif")

166

staticImage = loadAnimatedImage("static-frame.png").animate()

167

}

168

169

Image(

170

bitmap = if (shouldAnimate) {

171

animatedImage?.animate() ?: ImageBitmap.Blank

172

} else {

173

staticImage ?: ImageBitmap.Blank

174

},

175

contentDescription = "Conditional animation",

176

modifier = Modifier.size(100.dp)

177

)

178

}

179

```

180

181

#### Animation Gallery

182

183

```kotlin

184

@Composable

185

fun AnimationGallery() {

186

val animationUrls = listOf(

187

"https://example.com/cat.gif",

188

"https://example.com/dog.gif",

189

"https://example.com/bird.gif"

190

)

191

192

LazyRow {

193

items(animationUrls) { url ->

194

AnimatedImageCard(url)

195

}

196

}

197

}

198

199

@Composable

200

fun AnimatedImageCard(url: String) {

201

var animatedImage by remember { mutableStateOf<AnimatedImage?>(null) }

202

203

Card(

204

modifier = Modifier

205

.size(120.dp)

206

.padding(8.dp)

207

) {

208

LaunchedEffect(url) {

209

animatedImage = loadAnimatedImage(url)

210

}

211

212

Box(

213

modifier = Modifier.fillMaxSize(),

214

contentAlignment = Alignment.Center

215

) {

216

animatedImage?.let { image ->

217

Image(

218

bitmap = image.animate(),

219

contentDescription = null,

220

modifier = Modifier.fillMaxSize(),

221

contentScale = ContentScale.Crop

222

)

223

} ?: CircularProgressIndicator(modifier = Modifier.size(24.dp))

224

}

225

}

226

}

227

```

228

229

### Error Handling

230

231

```kotlin

232

@Composable

233

fun RobustAnimatedImage(imagePath: String) {

234

var animatedImage by remember { mutableStateOf<AnimatedImage?>(null) }

235

var error by remember { mutableStateOf<String?>(null) }

236

var isLoading by remember { mutableStateOf(true) }

237

238

LaunchedEffect(imagePath) {

239

isLoading = true

240

error = null

241

try {

242

animatedImage = loadAnimatedImage(imagePath)

243

} catch (e: Exception) {

244

error = "Failed to load animation: ${e.message}"

245

animatedImage = null

246

} finally {

247

isLoading = false

248

}

249

}

250

251

Box(

252

modifier = Modifier.size(200.dp),

253

contentAlignment = Alignment.Center

254

) {

255

when {

256

isLoading -> CircularProgressIndicator()

257

error != null -> Text(

258

error!!,

259

color = MaterialTheme.colors.error,

260

textAlign = TextAlign.Center

261

)

262

animatedImage != null -> Image(

263

bitmap = animatedImage!!.animate(),

264

contentDescription = "Animation",

265

modifier = Modifier.fillMaxSize()

266

)

267

else -> Text("No image")

268

}

269

}

270

}

271

```

272

273

### Performance Considerations

274

275

- **Automatic Format Detection**: The system automatically detects image formats and optimizes loading

276

- **Frame Timing**: Animation respects original frame timing for smooth playback

277

- **Memory Management**: Platform-specific implementations optimize memory usage

278

- **Network Loading**: Supports both local and network image sources seamlessly

279

- **Infinite Looping**: Animations loop continuously without manual intervention

280

281

### Platform Implementation Details

282

283

#### Desktop Implementation

284

- Uses Skia `Codec` for efficient frame decoding

285

- Supports GIF, WebP, and other animated formats

286

- Automatic network URL detection

287

- Loaders: `NetworkAnimatedImageLoader`, `LocalAnimatedImageLoader`, `ResourceAnimatedImageLoader`

288

289

#### Multiplatform Support

290

- Each platform provides optimized implementations

291

- Consistent API across all supported platforms

292

- Platform-specific performance optimizations