feat(launch_overlay): 使用品牌 Logo 和 AppName 替换通用图标
- ShellEnvironment 新增 splashImage 字段支持品牌启动图标 - LaunchOverlay 使用 splash.png 替换 Icons.language_rounded - 标题改为品牌名称(appName),移除副标题 - 加载指示器改为 CircularProgressIndicator 不定态转圈 - 使用 accentColor 主题色 - generate_app.dart 自动注册 assets/branding/ 并生成 splashImage 配置 - quanxue pubspec.yaml 注册 assets/branding/ 目录
This commit is contained in:
parent
8ac3a222c1
commit
dad37faecb
|
|
@ -10,6 +10,7 @@ void main() {
|
|||
backgroundColor: const Color(0xFFFFFFFF),
|
||||
textColor: const Color(0xFF1F2937),
|
||||
mutedTextColor: const Color(0xFF6B7280),
|
||||
splashImage: const AssetImage('assets/branding/splash.png'),
|
||||
initialUrl: "http://192.168.2.57:8080/test_bridge.html",
|
||||
),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -61,10 +61,8 @@ flutter:
|
|||
# the material Icons class.
|
||||
uses-material-design: true
|
||||
|
||||
# To add assets to your application, add an assets section, like this:
|
||||
# assets:
|
||||
# - images/a_dot_burr.jpeg
|
||||
# - images/a_dot_ham.jpeg
|
||||
assets:
|
||||
- assets/branding/
|
||||
|
||||
# An image asset can refer to one or more resolution-specific "variants", see
|
||||
# https://flutter.dev/to/resolution-aware-images
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ class ShellEnvironment {
|
|||
required this.backgroundColor,
|
||||
required this.textColor,
|
||||
required this.mutedTextColor,
|
||||
this.splashImage,
|
||||
this.initialUrl,
|
||||
});
|
||||
|
||||
|
|
@ -32,6 +33,9 @@ class ShellEnvironment {
|
|||
/// 品牌次要文字色
|
||||
final Color mutedTextColor;
|
||||
|
||||
/// 可选的品牌启动页图标;为空时使用默认图标。
|
||||
final ImageProvider? splashImage;
|
||||
|
||||
/// 可选的初始地址;为空时使用默认地址。
|
||||
final String? initialUrl;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,64 +17,86 @@ class LaunchOverlay extends StatelessWidget {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final splashImage = _env.splashImage;
|
||||
|
||||
return ColoredBox(
|
||||
color: _shellBackgroundColor,
|
||||
child: Center(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: <Widget>[
|
||||
Container(
|
||||
width: 88,
|
||||
height: 88,
|
||||
decoration: BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
colors: <Color>[const Color(0xFF66E59A), _shellAccentColor],
|
||||
begin: Alignment.topLeft,
|
||||
end: Alignment.bottomRight,
|
||||
// ── 品牌 Logo ──
|
||||
if (splashImage != null)
|
||||
Container(
|
||||
width: 88,
|
||||
height: 88,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(24),
|
||||
boxShadow: <BoxShadow>[
|
||||
BoxShadow(
|
||||
color: _shellAccentColor.withValues(alpha: 0.2),
|
||||
blurRadius: 20,
|
||||
offset: const Offset(0, 6),
|
||||
),
|
||||
],
|
||||
),
|
||||
borderRadius: BorderRadius.circular(24),
|
||||
boxShadow: <BoxShadow>[
|
||||
BoxShadow(
|
||||
color: _shellAccentColor.withValues(alpha: 0.3),
|
||||
blurRadius: 20,
|
||||
offset: const Offset(0, 6),
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(24),
|
||||
child: Image(
|
||||
image: splashImage,
|
||||
width: 88,
|
||||
height: 88,
|
||||
fit: BoxFit.contain,
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
else
|
||||
Container(
|
||||
width: 88,
|
||||
height: 88,
|
||||
decoration: BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
colors: <Color>[
|
||||
const Color(0xFF66E59A),
|
||||
_shellAccentColor,
|
||||
],
|
||||
begin: Alignment.topLeft,
|
||||
end: Alignment.bottomRight,
|
||||
),
|
||||
borderRadius: BorderRadius.circular(24),
|
||||
boxShadow: <BoxShadow>[
|
||||
BoxShadow(
|
||||
color: _shellAccentColor.withValues(alpha: 0.3),
|
||||
blurRadius: 20,
|
||||
offset: const Offset(0, 6),
|
||||
),
|
||||
],
|
||||
),
|
||||
alignment: Alignment.center,
|
||||
child: const Icon(
|
||||
Icons.language_rounded,
|
||||
size: 42,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
alignment: Alignment.center,
|
||||
child: const Icon(
|
||||
Icons.language_rounded,
|
||||
size: 42,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
// ── 品牌名称 ──
|
||||
Text(
|
||||
'页面加载中',
|
||||
_env.appName,
|
||||
style: TextStyle(
|
||||
fontSize: 24,
|
||||
fontWeight: FontWeight.w800,
|
||||
color: _shellTextColor,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
'正在为你启动 H5 页面',
|
||||
style: TextStyle(color: _shellMutedTextColor, fontSize: 14),
|
||||
),
|
||||
const SizedBox(height: 36),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 64),
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(6),
|
||||
child: LinearProgressIndicator(
|
||||
minHeight: 6,
|
||||
value: hasMeasuredProgress ? progress / 100 : null,
|
||||
backgroundColor: const Color(0xFFE7F3EB),
|
||||
valueColor: AlwaysStoppedAnimation<Color>(
|
||||
_shellAccentColor,
|
||||
),
|
||||
),
|
||||
// ── 不定态转圈 ──
|
||||
SizedBox(
|
||||
width: 32,
|
||||
height: 32,
|
||||
child: CircularProgressIndicator(
|
||||
strokeWidth: 3,
|
||||
valueColor: AlwaysStoppedAnimation<Color>(_shellAccentColor),
|
||||
),
|
||||
),
|
||||
],
|
||||
|
|
@ -83,3 +105,4 @@ class LaunchOverlay extends StatelessWidget {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -78,6 +78,9 @@ Future<void> main(List<String> args) async {
|
|||
// 7. 生成图标与启动页配置
|
||||
await _generateBrandingAssets(brand, appDir, config);
|
||||
|
||||
// 8. 在 pubspec.yaml 中注册 Flutter assets
|
||||
await _registerFlutterAssets(appDir);
|
||||
|
||||
print('\x1B[32m✔ 应用 $brand 已生成到 $appDir!\x1B[0m');
|
||||
print('\x1B[34m构建应用请执行:\x1B[0m');
|
||||
print(' cd $appDir && flutter build apk');
|
||||
|
|
@ -201,6 +204,7 @@ void main() {
|
|||
backgroundColor: const Color($bgColor),
|
||||
textColor: const Color($textColor),
|
||||
mutedTextColor: const Color($mutedTextColor),
|
||||
splashImage: const AssetImage('assets/branding/splash.png'),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
@ -337,3 +341,19 @@ flutter_native_splash:
|
|||
}
|
||||
print('\x1B[32m✔ 启动页已生成。\x1B[0m');
|
||||
}
|
||||
|
||||
Future<void> _registerFlutterAssets(String appDir) async {
|
||||
print('\x1B[34m[信息] 正在注册 Flutter assets...\x1B[0m');
|
||||
final File pubspecFile = File('$appDir/pubspec.yaml');
|
||||
String content = await pubspecFile.readAsString();
|
||||
|
||||
// 查找 flutter: 段并添加 assets 声明
|
||||
if (!content.contains('assets:')) {
|
||||
content = content.replaceFirst(
|
||||
'flutter:\n',
|
||||
'flutter:\n assets:\n - assets/branding/\n',
|
||||
);
|
||||
await pubspecFile.writeAsString(content);
|
||||
}
|
||||
print('\x1B[32m✔ Flutter assets 已注册。\x1B[0m');
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue