flutter_avatar_kit 1.0.1 copy "flutter_avatar_kit: ^1.0.1" to clipboard
flutter_avatar_kit: ^1.0.1 copied to clipboard

SVG avatar UI kit with eight categories, grid picker, animated ring, theme-aware card, and path helpers for bundled assets.

example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:flutter_avatar_kit/flutter_avatar_kit.dart';

void main() => runApp(const AvatarKitDemoApp());

class AvatarKitDemoApp extends StatelessWidget {
  const AvatarKitDemoApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Avatar Kit',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.indigo),
        useMaterial3: true,
      ),
      darkTheme: ThemeData(
        colorScheme: ColorScheme.fromSeed(
          seedColor: Colors.indigo,
          brightness: Brightness.dark,
        ),
        useMaterial3: true,
      ),
      home: const DemoHomePage(),
    );
  }
}

class DemoHomePage extends StatefulWidget {
  const DemoHomePage({super.key});

  @override
  State<DemoHomePage> createState() => _DemoHomePageState();
}

class _DemoHomePageState extends State<DemoHomePage> {
  AvatarType _type = AvatarType.vibrant;
  int? _gridIndex;
  String? _gridAsset;
  int _heroIndex = 0;
  AvatarShape _heroShape = AvatarShape.rounded;
  bool _showRing = false;
  bool _randomHero = false;

  @override
  Widget build(BuildContext context) {
    final total = AvatarAssets.count(_type);

    return Scaffold(
      appBar: AppBar(
        title: const Text('Flutter Avatar Kit'),
        actions: [
          IconButton(
            tooltip: 'Toggle animated ring on hero',
            onPressed: () => setState(() => _showRing = !_showRing),
            icon: Icon(_showRing ? Icons.toll : Icons.toll_outlined),
          ),
          IconButton(
            tooltip: 'Random hero avatar',
            onPressed: () => setState(() {
              _randomHero = !_randomHero;
              if (!_randomHero) _heroIndex = 0;
            }),
            icon: Icon(_randomHero ? Icons.shuffle : Icons.shuffle_outlined),
          ),
        ],
      ),
      body: ListView(
        padding: const EdgeInsets.fromLTRB(16, 8, 16, 24),
        children: [
          Text(
            'Category',
            style: Theme.of(context).textTheme.titleMedium,
          ),
          const SizedBox(height: 8),
          Wrap(
            spacing: 8,
            runSpacing: 8,
            children: AvatarType.values.map((t) {
              final selected = t == _type;
              return FilterChip(
                label: Text(_label(t)),
                selected: selected,
                onSelected: (_) {
                  setState(() {
                    _type = t;
                    _gridIndex = null;
                    _gridAsset = null;
                    _heroIndex = _heroIndex.clamp(0, AvatarAssets.count(t) - 1);
                  });
                },
              );
            }).toList(),
          ),
          const SizedBox(height: 20),
          Text(
            'Hero preview',
            style: Theme.of(context).textTheme.titleMedium,
          ),
          const SizedBox(height: 8),
          Row(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              AvatarCard(
                onTap: () {
                  setState(() {
                    _randomHero = false;
                    _heroIndex = (_heroIndex + 1) % total;
                  });
                },
                child: AvatarWidget(
                  type: _type,
                  index: _heroIndex,
                  size: 96,
                  shape: _heroShape,
                  showRing: _showRing,
                  isRandom: _randomHero,
                ),
              ),
              const SizedBox(width: 16),
              Expanded(
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Text(
                      _randomHero
                          ? 'Random asset each rebuild (tap card to cycle index when off).'
                          : 'Index $_heroIndex of $total — tap card to cycle.',
                      style: Theme.of(context).textTheme.bodyMedium,
                    ),
                    const SizedBox(height: 8),
                    Text(
                      _randomHero
                          ? AvatarAssets.getRandomAsset(_type)
                          : AvatarAssets.getAsset(_type, _heroIndex),
                      style: Theme.of(context).textTheme.bodySmall?.copyWith(
                            fontFamily: 'monospace',
                          ),
                    ),
                    const SizedBox(height: 12),
                    Text(
                      'Shape',
                      style: Theme.of(context).textTheme.labelLarge,
                    ),
                    const SizedBox(height: 4),
                    SegmentedButton<AvatarShape>(
                      segments: AvatarShape.values
                          .map(
                            (s) => ButtonSegment<AvatarShape>(
                              value: s,
                              label: Text(s.name),
                            ),
                          )
                          .toList(),
                      selected: {_heroShape},
                      onSelectionChanged: (s) =>
                          setState(() => _heroShape = s.first),
                    ),
                  ],
                ),
              ),
            ],
          ),
          const SizedBox(height: 24),
          Text(
            'Grid (${AvatarAssets.count(_type)} items)',
            style: Theme.of(context).textTheme.titleMedium,
          ),
          const SizedBox(height: 8),
          SizedBox(
            height: 320,
            child: AvatarGrid(
              type: _type,
              crossAxisCount: 5,
              padding: const EdgeInsets.only(bottom: 8),
              onSelect: (index, asset) {
                setState(() {
                  _gridIndex = index;
                  _gridAsset = asset;
                });
              },
              onLongPress: (index, asset) {
                ScaffoldMessenger.of(context).showSnackBar(
                  SnackBar(
                    content: Text('Long press #$index → $asset'),
                    behavior: SnackBarBehavior.floating,
                  ),
                );
              },
            ),
          ),
          if (_gridIndex != null && _gridAsset != null) ...[
            const SizedBox(height: 8),
            Text(
              'Selected: #$_gridIndex — $_gridAsset',
              style: Theme.of(context).textTheme.bodyMedium?.copyWith(
                    fontFamily: 'monospace',
                  ),
            ),
          ],
        ],
      ),
    );
  }

  static String _label(AvatarType t) {
    switch (t) {
      case AvatarType.d3:
        return '3D';
      case AvatarType.vibrant:
        return 'Vibrant';
      case AvatarType.bluey:
        return 'Bluey';
      case AvatarType.memo:
        return 'Memo';
      case AvatarType.notion:
        return 'Notion';
      case AvatarType.teams:
        return 'Teams';
      case AvatarType.toon:
        return 'Toon';
      case AvatarType.upstream:
        return 'Upstream';
    }
  }
}
0
likes
160
points
30
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

SVG avatar UI kit with eight categories, grid picker, animated ring, theme-aware card, and path helpers for bundled assets.

Repository (GitHub)
View/report issues

Topics

#avatar #svg #widget #ui

License

MIT (license)

Dependencies

flutter, flutter_svg

More

Packages that depend on flutter_avatar_kit