k_skin 0.0.1 copy "k_skin: ^0.0.1" to clipboard
k_skin: ^0.0.1 copied to clipboard

A Flutter package for skinning applications with custom themes and styles.This package allows developers to easily apply custom skins to their Flutter applications, enhancing the visual appeal and use [...]

example/lib/main.dart

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

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  // 注意:KThemeManager 不需要初始化,如果需要皮肤包功能,可以初始化 SkinManager
  // await SkinManager().initialize();

  runApp(MyApp());
}

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

  @override
  Widget build(BuildContext context) {
    return KThemeProvider(
      child: Builder(
        builder: (context) {
          return MaterialApp(
            title: 'K Skin Example',
            theme: KThemeProvider.of(context).toFlutterThemeData(),
            home: MyHomePage(),
          );
        },
      ),
    );
  }
}

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

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    final theme = KThemeProvider.of(context);

    return Scaffold(
      appBar: AppBar(
        title: Text('K Skin Example'),
        backgroundColor: theme.colorScheme.primary,
        foregroundColor: theme.colorScheme.onPrimary,
      ),
      body: SingleChildScrollView(
        padding: const EdgeInsets.all(16),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            // 主题信息卡片
            _buildThemeInfoCard(theme),

            const SizedBox(height: 20),

            // 主题切换器
            Text('主题切换器', style: theme.typography.headlineSmall),
            const SizedBox(height: 8),
            KThemeSwitcher(),

            const SizedBox(height: 20),

            // 颜色展示
            Text('颜色方案', style: theme.typography.headlineSmall),
            const SizedBox(height: 8),
            _buildColorDisplay(theme),

            const SizedBox(height: 20),

            // 快速创建主题
            Text('快速主题', style: theme.typography.headlineSmall),
            const SizedBox(height: 8),
            _buildQuickThemeButtons(),

            const SizedBox(height: 20),

            // 主题网格选择器
            Text('主题选择器', style: theme.typography.headlineSmall),
            const SizedBox(height: 8),
            SizedBox(
              height: 200,
              child: KThemeGridSelector(
                crossAxisCount: 2,
                onThemeChanged: (selectedTheme) {
                  ScaffoldMessenger.of(context).showSnackBar(
                    SnackBar(content: Text('选择了主题: ${selectedTheme.name}')),
                  );
                },
              ),
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _showCustomThemeDialog,
        tooltip: '创建自定义主题',
        child: const Icon(Icons.palette),
      ),
    );
  }

  Widget _buildThemeInfoCard(KThemeData theme) {
    return Card(
      child: Padding(
        padding: const EdgeInsets.all(16),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Text('当前主题信息', style: theme.typography.headlineSmall),
            const SizedBox(height: 8),
            _buildInfoRow('主题名称', theme.name, theme),
            _buildInfoRow('主题 ID', theme.id, theme),
            _buildInfoRow('版本', theme.version, theme),
            if (theme.author != null) _buildInfoRow('作者', theme.author!, theme),
            _buildInfoRow('类型', theme.isDark ? '暗色主题' : '亮色主题', theme),
          ],
        ),
      ),
    );
  }

  Widget _buildInfoRow(String label, String value, KThemeData theme) {
    return Padding(
      padding: const EdgeInsets.symmetric(vertical: 2),
      child: Row(
        children: [
          Text(
            '$label: ',
            style: theme.typography.bodyMedium.copyWith(
              fontWeight: FontWeight.bold,
            ),
          ),
          Expanded(child: Text(value, style: theme.typography.bodyMedium)),
        ],
      ),
    );
  }

  Widget _buildColorDisplay(KThemeData theme) {
    return Wrap(
      spacing: 8,
      runSpacing: 8,
      children: [
        _buildColorChip('Primary', theme.colorScheme.primary),
        _buildColorChip('Secondary', theme.colorScheme.secondary),
        _buildColorChip('Surface', theme.colorScheme.surface),
        _buildColorChip('Error', theme.colorScheme.error),
        ...theme.colorScheme.customColors.entries.map(
          (entry) => _buildColorChip(entry.key, entry.value),
        ),
      ],
    );
  }

  Widget _buildColorChip(String label, Color color) {
    return Chip(
      label: Text(
        label,
        style: TextStyle(
          color: color.computeLuminance() > 0.5 ? Colors.black : Colors.white,
          fontSize: 12,
        ),
      ),
      backgroundColor: color,
    );
  }

  Widget _buildQuickThemeButtons() {
    return Wrap(
      spacing: 8,
      runSpacing: 8,
      children: [
        ElevatedButton(
          onPressed: () => _applyQuickTheme('ocean'),
          child: Text('Ocean'),
        ),
        ElevatedButton(
          onPressed: () => _applyQuickTheme('forest'),
          child: Text('Forest'),
        ),
        ElevatedButton(
          onPressed: () => _applyQuickTheme('sunset'),
          child: Text('Sunset'),
        ),
        ElevatedButton(
          onPressed: () => _applyQuickTheme('night'),
          child: Text('Night'),
        ),
        ElevatedButton(
          onPressed: _applyMaterial3Theme,
          child: Text('Material 3'),
        ),
      ],
    );
  }

  void _applyQuickTheme(String template) async {
    final theme = KQuickThemeBuilder.preset(template).build();
    KThemeManager.instance.addTheme(theme, makeActive: true);
  }

  void _applyMaterial3Theme() async {
    final theme =
        KQuickThemeBuilder.light(
          name: 'Material 3 Theme',
          primaryColor: Colors.deepPurple,
          secondaryColor: Colors.deepPurpleAccent,
        ).build();
    KThemeManager.instance.addTheme(theme, makeActive: true);
  }

  void _showCustomThemeDialog() {
    showDialog(context: context, builder: (context) => CustomThemeDialog());
  }
}

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

  @override
  State<CustomThemeDialog> createState() => _CustomThemeDialogState();
}

class _CustomThemeDialogState extends State<CustomThemeDialog> {
  final _nameController = TextEditingController();
  Color _primaryColor = Colors.blue;
  Color _secondaryColor = Colors.cyan;
  bool _isDark = false;

  @override
  void dispose() {
    _nameController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return AlertDialog(
      title: const Text('创建自定义主题'),
      content: SingleChildScrollView(
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            TextField(
              controller: _nameController,
              decoration: const InputDecoration(
                labelText: '主题名称',
                hintText: '输入主题名称',
              ),
            ),
            const SizedBox(height: 16),

            ListTile(
              title: const Text('主要颜色'),
              trailing: Container(
                width: 40,
                height: 40,
                decoration: BoxDecoration(
                  color: _primaryColor,
                  shape: BoxShape.circle,
                  border: Border.all(color: Colors.grey),
                ),
              ),
              onTap: () => _pickColor('primary'),
            ),

            ListTile(
              title: const Text('次要颜色'),
              trailing: Container(
                width: 40,
                height: 40,
                decoration: BoxDecoration(
                  color: _secondaryColor,
                  shape: BoxShape.circle,
                  border: Border.all(color: Colors.grey),
                ),
              ),
              onTap: () => _pickColor('secondary'),
            ),

            SwitchListTile(
              title: const Text('暗色主题'),
              value: _isDark,
              onChanged: (value) {
                setState(() {
                  _isDark = value;
                });
              },
            ),
          ],
        ),
      ),
      actions: [
        TextButton(
          onPressed: () => Navigator.of(context).pop(),
          child: const Text('取消'),
        ),
        ElevatedButton(onPressed: _createTheme, child: const Text('创建')),
      ],
    );
  }

  void _pickColor(String type) {
    // 这里可以集成颜色选择器,简化起见使用预设颜色
    final colors = [
      Colors.red,
      Colors.pink,
      Colors.purple,
      Colors.deepPurple,
      Colors.indigo,
      Colors.blue,
      Colors.lightBlue,
      Colors.cyan,
      Colors.teal,
      Colors.green,
      Colors.lightGreen,
      Colors.lime,
      Colors.yellow,
      Colors.amber,
      Colors.orange,
      Colors.deepOrange,
    ];

    showDialog(
      context: context,
      builder:
          (context) => AlertDialog(
            title: const Text('选择颜色'),
            content: Wrap(
              children:
                  colors.map((color) {
                    return GestureDetector(
                      onTap: () {
                        setState(() {
                          if (type == 'primary') {
                            _primaryColor = color;
                          } else {
                            _secondaryColor = color;
                          }
                        });
                        Navigator.of(context).pop();
                      },
                      child: Container(
                        width: 40,
                        height: 40,
                        margin: const EdgeInsets.all(4),
                        decoration: BoxDecoration(
                          color: color,
                          shape: BoxShape.circle,
                          border: Border.all(color: Colors.grey),
                        ),
                      ),
                    );
                  }).toList(),
            ),
          ),
    );
  }

  void _createTheme() async {
    final name = _nameController.text.trim();
    if (name.isEmpty) {
      ScaffoldMessenger.of(
        context,
      ).showSnackBar(const SnackBar(content: Text('请输入主题名称')));
      return;
    }

    final theme =
        KThemeBuilder()
            .id('custom_${DateTime.now().millisecondsSinceEpoch}')
            .name(name)
            .version('1.0.0')
            .dark(_isDark)
            .primaryColor(_primaryColor)
            .secondaryColor(_secondaryColor)
            .extension('borderRadius', 12.0)
            .extension('cardElevation', 4.0)
            .build();

    KThemeManager.instance.addTheme(theme, makeActive: true);

    Navigator.of(context).pop();

    ScaffoldMessenger.of(
      context,
    ).showSnackBar(SnackBar(content: Text('主题 "$name" 创建成功!')));
  }
}
0
likes
125
points
19
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

A Flutter package for skinning applications with custom themes and styles.This package allows developers to easily apply custom skins to their Flutter applications, enhancing the visual appeal and user experience.

License

GPL-3.0 (license)

Dependencies

archive, flutter, http, path, path_provider

More

Packages that depend on k_skin