or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

asset-management.mdcomposition-loading.mdconfiguration-performance.mddynamic-properties.mdindex.mdview-components.md

asset-management.mddocs/

0

# Asset Management

1

2

Delegate interfaces for handling custom image assets, fonts, and dynamic text replacement. This system allows you to provide custom implementations for loading images, fonts, and replacing text content at runtime.

3

4

## Capabilities

5

6

### Image Asset Management

7

8

System for providing custom bitmap loading for image assets referenced in Lottie animations. Useful for loading images from network, custom storage, or applying transformations.

9

10

```java { .api }

11

/**

12

* Delegate for handling custom image asset loading

13

*/

14

public interface ImageAssetDelegate {

15

/**

16

* Fetch bitmap for the given image asset

17

* @param asset The image asset to load

18

* @return Bitmap to use, or null to use default loading

19

*/

20

Bitmap fetchBitmap(LottieImageAsset asset);

21

}

22

23

/**

24

* Image asset model containing metadata

25

*/

26

public class LottieImageAsset {

27

// Asset identification

28

public String getId();

29

public String getFileName();

30

public String getDirName();

31

32

// Dimensions

33

public int getWidth();

34

public int getHeight();

35

36

// Bitmap management

37

public Bitmap getBitmap();

38

public void setBitmap(Bitmap bitmap);

39

40

// Internal methods

41

@RestrictTo(RestrictTo.Scope.LIBRARY)

42

public boolean hasBitmap();

43

}

44

```

45

46

**Usage Examples:**

47

48

```java

49

// Basic image asset delegate

50

animationView.setImageAssetDelegate(new ImageAssetDelegate() {

51

@Override

52

public Bitmap fetchBitmap(LottieImageAsset asset) {

53

// Load from custom location

54

String imagePath = "custom/path/" + asset.getFileName();

55

return BitmapFactory.decodeFile(imagePath);

56

}

57

});

58

59

// Network image loading delegate

60

animationView.setImageAssetDelegate(new ImageAssetDelegate() {

61

@Override

62

public Bitmap fetchBitmap(LottieImageAsset asset) {

63

try {

64

String imageUrl = "https://cdn.example.com/images/" + asset.getFileName();

65

URL url = new URL(imageUrl);

66

InputStream inputStream = url.openConnection().getInputStream();

67

return BitmapFactory.decodeStream(inputStream);

68

} catch (IOException e) {

69

Log.e("Lottie", "Failed to load image: " + asset.getFileName(), e);

70

return null; // Use default loading

71

}

72

}

73

});

74

75

// Cached image loading with transformations

76

public class CachedImageDelegate implements ImageAssetDelegate {

77

private final LruCache<String, Bitmap> imageCache;

78

private final Context context;

79

80

public CachedImageDelegate(Context context) {

81

this.context = context;

82

int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);

83

int cacheSize = maxMemory / 8; // Use 1/8th of available memory

84

this.imageCache = new LruCache<String, Bitmap>(cacheSize) {

85

@Override

86

protected int sizeOf(String key, Bitmap bitmap) {

87

return bitmap.getByteCount() / 1024;

88

}

89

};

90

}

91

92

@Override

93

public Bitmap fetchBitmap(LottieImageAsset asset) {

94

String cacheKey = asset.getId();

95

Bitmap cached = imageCache.get(cacheKey);

96

if (cached != null) {

97

return cached;

98

}

99

100

// Load and process image

101

Bitmap original = loadImageFromAssets(asset.getFileName());

102

if (original != null) {

103

// Apply transformations

104

Bitmap processed = applyImageTransformations(original, asset);

105

imageCache.put(cacheKey, processed);

106

return processed;

107

}

108

109

return null;

110

}

111

112

private Bitmap loadImageFromAssets(String fileName) {

113

try (InputStream inputStream = context.getAssets().open("images/" + fileName)) {

114

return BitmapFactory.decodeStream(inputStream);

115

} catch (IOException e) {

116

return null;

117

}

118

}

119

120

private Bitmap applyImageTransformations(Bitmap original, LottieImageAsset asset) {

121

// Apply scaling, filters, etc.

122

if (original.getWidth() != asset.getWidth() || original.getHeight() != asset.getHeight()) {

123

return Bitmap.createScaledBitmap(original, asset.getWidth(), asset.getHeight(), true);

124

}

125

return original;

126

}

127

}

128

129

// Dynamic image replacement based on user data

130

animationView.setImageAssetDelegate(new ImageAssetDelegate() {

131

@Override

132

public Bitmap fetchBitmap(LottieImageAsset asset) {

133

switch (asset.getId()) {

134

case "user_avatar":

135

return getUserAvatarBitmap();

136

case "product_image":

137

return getProductImageBitmap();

138

default:

139

return null; // Use default loading

140

}

141

}

142

143

private Bitmap getUserAvatarBitmap() {

144

// Load user's profile picture

145

return ImageLoader.loadUserAvatar(getCurrentUserId());

146

}

147

148

private Bitmap getProductImageBitmap() {

149

// Load current product image

150

return ImageLoader.loadProductImage(getCurrentProductId());

151

}

152

});

153

```

154

155

### Font Asset Management

156

157

System for providing custom font loading for text layers in Lottie animations. Allows loading fonts from custom locations or applying font substitutions.

158

159

```java { .api }

160

/**

161

* Delegate for handling custom font asset loading

162

*/

163

public interface FontAssetDelegate {

164

/**

165

* Fetch typeface for the given font family

166

* @param fontFamily Font family name from animation

167

* @return Typeface to use, or null to use default loading

168

*/

169

Typeface fetchFont(String fontFamily);

170

171

/**

172

* Get file path for font family (optional)

173

* @param fontFamily Font family name

174

* @return Font file path, or null

175

*/

176

String getFontPath(String fontFamily);

177

}

178

179

/**

180

* Font asset model

181

*/

182

public class Font {

183

// Font identification

184

public String getName();

185

public String getFontFamily();

186

public String getStyle();

187

public String getFontPath();

188

189

// Font metrics

190

public float getAscent();

191

192

// Internal methods

193

@RestrictTo(RestrictTo.Scope.LIBRARY)

194

public Font(String fontFamily, String name, String style, float ascent);

195

}

196

```

197

198

**Usage Examples:**

199

200

```java

201

// Basic font asset delegate

202

animationView.setFontAssetDelegate(new FontAssetDelegate() {

203

@Override

204

public Typeface fetchFont(String fontFamily) {

205

try {

206

return Typeface.createFromAsset(getAssets(), "fonts/" + fontFamily + ".ttf");

207

} catch (Exception e) {

208

Log.w("Lottie", "Failed to load font: " + fontFamily, e);

209

return null; // Use default font

210

}

211

}

212

213

@Override

214

public String getFontPath(String fontFamily) {

215

return "fonts/" + fontFamily + ".ttf";

216

}

217

});

218

219

// Font mapping delegate

220

animationView.setFontAssetDelegate(new FontAssetDelegate() {

221

private final Map<String, String> fontMappings = new HashMap<String, String>() {{

222

put("CustomFont-Regular", "Roboto-Regular");

223

put("CustomFont-Bold", "Roboto-Bold");

224

put("DisplayFont", "Oswald-Regular");

225

}};

226

227

@Override

228

public Typeface fetchFont(String fontFamily) {

229

String mappedFont = fontMappings.get(fontFamily);

230

if (mappedFont != null) {

231

try {

232

return Typeface.createFromAsset(getAssets(), "fonts/" + mappedFont + ".ttf");

233

} catch (Exception e) {

234

Log.w("Lottie", "Failed to load mapped font: " + mappedFont, e);

235

}

236

}

237

238

// Try original font name

239

try {

240

return Typeface.createFromAsset(getAssets(), "fonts/" + fontFamily + ".ttf");

241

} catch (Exception e) {

242

return Typeface.DEFAULT;

243

}

244

}

245

246

@Override

247

public String getFontPath(String fontFamily) {

248

String mappedFont = fontMappings.get(fontFamily);

249

return "fonts/" + (mappedFont != null ? mappedFont : fontFamily) + ".ttf";

250

}

251

});

252

253

// System font delegate

254

animationView.setFontAssetDelegate(new FontAssetDelegate() {

255

@Override

256

public Typeface fetchFont(String fontFamily) {

257

switch (fontFamily.toLowerCase()) {

258

case "roboto":

259

case "roboto-regular":

260

return Typeface.DEFAULT;

261

case "roboto-bold":

262

return Typeface.DEFAULT_BOLD;

263

case "monospace":

264

return Typeface.MONOSPACE;

265

case "serif":

266

return Typeface.SERIF;

267

case "sans-serif":

268

return Typeface.SANS_SERIF;

269

default:

270

// Try to create from system

271

return Typeface.create(fontFamily, Typeface.NORMAL);

272

}

273

}

274

275

@Override

276

public String getFontPath(String fontFamily) {

277

return null; // System fonts don't have file paths

278

}

279

});

280

281

// Font caching delegate

282

public class CachedFontDelegate implements FontAssetDelegate {

283

private final Map<String, Typeface> fontCache = new HashMap<>();

284

private final Context context;

285

286

public CachedFontDelegate(Context context) {

287

this.context = context;

288

}

289

290

@Override

291

public Typeface fetchFont(String fontFamily) {

292

Typeface cached = fontCache.get(fontFamily);

293

if (cached != null) {

294

return cached;

295

}

296

297

try {

298

Typeface typeface = Typeface.createFromAsset(

299

context.getAssets(),

300

"fonts/" + fontFamily + ".ttf"

301

);

302

fontCache.put(fontFamily, typeface);

303

return typeface;

304

} catch (Exception e) {

305

Log.w("Lottie", "Failed to load font: " + fontFamily, e);

306

return Typeface.DEFAULT;

307

}

308

}

309

310

@Override

311

public String getFontPath(String fontFamily) {

312

return "fonts/" + fontFamily + ".ttf";

313

}

314

}

315

```

316

317

### Text Replacement

318

319

System for dynamically replacing text content in text layers. Allows localization, personalization, and real-time text updates.

320

321

```java { .api }

322

/**

323

* Delegate for dynamic text replacement

324

*/

325

public class TextDelegate {

326

// Text replacement methods

327

public String getText(String layerName, String sourceText);

328

public void setText(String layerName, String text);

329

330

// Internal text storage

331

private final Map<String, String> textMap = new HashMap<>();

332

333

// Internal callback handling

334

@RestrictTo(RestrictTo.Scope.LIBRARY)

335

public final LottieValueCallback<String> getTextCallback(String layerName, String sourceText);

336

}

337

```

338

339

**Usage Examples:**

340

341

```java

342

// Basic text replacement

343

TextDelegate textDelegate = new TextDelegate() {

344

@Override

345

public String getText(String layerName, String sourceText) {

346

switch (layerName) {

347

case "WelcomeText":

348

return "Welcome, " + getCurrentUserName() + "!";

349

case "StatusText":

350

return getApplicationStatus();

351

case "CounterText":

352

return String.valueOf(getCurrentCount());

353

default:

354

return sourceText; // Use original text

355

}

356

}

357

};

358

animationView.setTextDelegate(textDelegate);

359

360

// Localized text replacement

361

TextDelegate localizedDelegate = new TextDelegate() {

362

private final Map<String, String> localizedTexts = loadLocalizedTexts();

363

364

@Override

365

public String getText(String layerName, String sourceText) {

366

String localized = localizedTexts.get(layerName);

367

return localized != null ? localized : sourceText;

368

}

369

370

private Map<String, String> loadLocalizedTexts() {

371

Map<String, String> texts = new HashMap<>();

372

// Load from resources based on current locale

373

String locale = Locale.getDefault().getLanguage();

374

switch (locale) {

375

case "es":

376

texts.put("HelloText", "¡Hola!");

377

texts.put("GoodbyeText", "¡Adiós!");

378

break;

379

case "fr":

380

texts.put("HelloText", "Bonjour!");

381

texts.put("GoodbyeText", "Au revoir!");

382

break;

383

default:

384

texts.put("HelloText", "Hello!");

385

texts.put("GoodbyeText", "Goodbye!");

386

break;

387

}

388

return texts;

389

}

390

};

391

392

// Dynamic text updates

393

TextDelegate dynamicDelegate = new TextDelegate();

394

animationView.setTextDelegate(dynamicDelegate);

395

396

// Update text dynamically

397

dynamicDelegate.setText("ScoreText", "Score: " + currentScore);

398

dynamicDelegate.setText("TimeText", "Time: " + formatTime(remainingTime));

399

dynamicDelegate.setText("MessageText", "Level " + currentLevel + " Complete!");

400

401

// Template-based text replacement

402

TextDelegate templateDelegate = new TextDelegate() {

403

@Override

404

public String getText(String layerName, String sourceText) {

405

// Support template variables in source text

406

return replaceTemplateVariables(sourceText);

407

}

408

409

private String replaceTemplateVariables(String template) {

410

return template

411

.replace("${username}", getCurrentUserName())

412

.replace("${score}", String.valueOf(getCurrentScore()))

413

.replace("${level}", String.valueOf(getCurrentLevel()))

414

.replace("${date}", getCurrentDate());

415

}

416

};

417

418

// Real-time updating text delegate

419

public class LiveTextDelegate extends TextDelegate {

420

private Timer updateTimer;

421

private LottieAnimationView animationView;

422

423

public LiveTextDelegate(LottieAnimationView animationView) {

424

this.animationView = animationView;

425

startUpdates();

426

}

427

428

@Override

429

public String getText(String layerName, String sourceText) {

430

switch (layerName) {

431

case "ClockText":

432

return getCurrentTime();

433

case "CountdownText":

434

return String.valueOf(getRemainingSeconds());

435

case "LiveDataText":

436

return getLiveDataValue();

437

default:

438

return sourceText;

439

}

440

}

441

442

private void startUpdates() {

443

updateTimer = new Timer();

444

updateTimer.scheduleAtFixedRate(new TimerTask() {

445

@Override

446

public void run() {

447

// Trigger redraw to update text

448

if (animationView != null) {

449

animationView.post(() -> animationView.invalidate());

450

}

451

}

452

}, 0, 1000); // Update every second

453

}

454

455

public void stopUpdates() {

456

if (updateTimer != null) {

457

updateTimer.cancel();

458

updateTimer = null;

459

}

460

}

461

462

private String getCurrentTime() {

463

SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss", Locale.getDefault());

464

return sdf.format(new Date());

465

}

466

467

private int getRemainingSeconds() {

468

// Calculate remaining time

469

return Math.max(0, (int) ((endTime - System.currentTimeMillis()) / 1000));

470

}

471

472

private String getLiveDataValue() {

473

// Fetch live data from server, database, etc.

474

return String.valueOf(DataProvider.getCurrentValue());

475

}

476

}

477

478

// Conditional text replacement

479

TextDelegate conditionalDelegate = new TextDelegate() {

480

@Override

481

public String getText(String layerName, String sourceText) {

482

switch (layerName) {

483

case "StatusIndicator":

484

return isConnected() ? "ONLINE" : "OFFLINE";

485

case "ProgressText":

486

int progress = getCurrentProgress();

487

if (progress < 25) return "Starting...";

488

else if (progress < 75) return "In Progress...";

489

else if (progress < 100) return "Almost Done...";

490

else return "Complete!";

491

case "UserGreeting":

492

return isUserLoggedIn() ?

493

"Welcome back!" :

494

"Please sign in";

495

default:

496

return sourceText;

497

}

498

}

499

};

500

```

501

502

## Font Character Model

503

504

```java { .api }

505

public class FontCharacter {

506

// Character properties

507

public String getCharacter();

508

public double getSize();

509

public double getWidth();

510

public String getStyle();

511

public String getFontFamily();

512

513

// Shape data

514

public List<ShapeGroup> getShapes();

515

516

// Internal construction

517

@RestrictTo(RestrictTo.Scope.LIBRARY)

518

public FontCharacter(List<ShapeGroup> shapes, String character, double size,

519

double width, String style, String fontFamily);

520

}

521

```