feat(ui): 登录页重设计并统一弹框主题渐变外壳
This commit is contained in:
1 parent
c027acc91f
commit
de7da64886
25 files changed
+905
-317
No files matched your search
@@ -3,6 +3,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../../core/theme/app_colors.dart';
|
||||
import '../../../core/widgets/app_glow_panel.dart';
|
||||
import '../../../l10n/app_localizations.dart';
|
||||
|
||||
const double _sheetRadius = 20;
|
||||
@@ -52,6 +53,8 @@ class PlayerMoreActions {
|
||||
required this.onDownload,
|
||||
required this.onQualityChanged,
|
||||
this.onPip,
|
||||
this.autoPipEnabled = false,
|
||||
this.onAutoPipChanged,
|
||||
});
|
||||
|
||||
/// 倍速变化。
|
||||
@@ -68,6 +71,12 @@ class PlayerMoreActions {
|
||||
|
||||
/// 进入小窗播放;平台不支持时为 null。
|
||||
final VoidCallback? onPip;
|
||||
|
||||
/// 退出 App 自动小窗开关的当前状态(仅支持自动小窗的平台展示开关行)。
|
||||
final bool autoPipEnabled;
|
||||
|
||||
/// 切换退出 App 自动小窗;为 null 时隐藏开关行。
|
||||
final ValueChanged<bool>? onAutoPipChanged;
|
||||
}
|
||||
|
||||
/// K29.6 精简版播放页更多面板。
|
||||
@@ -96,16 +105,19 @@ class PlayerMoreSheet extends StatefulWidget {
|
||||
class _PlayerMoreSheetState extends State<PlayerMoreSheet> {
|
||||
late double _speed = widget.state.speed;
|
||||
late String _quality = widget.state.selectedQuality.toUpperCase();
|
||||
late bool _autoPip = widget.actions.autoPipEnabled;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final l10n = widget.l10n;
|
||||
return Material(
|
||||
key: const Key('player-more-sheet'),
|
||||
color: AppColors.ink,
|
||||
return AppGlowPanel(
|
||||
borderRadius: const BorderRadius.vertical(
|
||||
top: Radius.circular(_sheetRadius),
|
||||
),
|
||||
border: false,
|
||||
child: Material(
|
||||
key: const Key('player-more-sheet'),
|
||||
type: MaterialType.transparency,
|
||||
clipBehavior: Clip.antiAlias,
|
||||
child: SafeArea(
|
||||
top: false,
|
||||
@@ -142,6 +154,17 @@ class _PlayerMoreSheetState extends State<PlayerMoreSheet> {
|
||||
title: l10n.pictureInPicture,
|
||||
onTap: () => _closeThen(widget.actions.onPip!),
|
||||
),
|
||||
if (widget.actions.onAutoPipChanged != null)
|
||||
_switchRow(
|
||||
key: const Key('player-more-auto-pip'),
|
||||
icon: Icons.auto_awesome_motion_outlined,
|
||||
title: l10n.autoEnterPip,
|
||||
value: _autoPip,
|
||||
onChanged: (value) {
|
||||
setState(() => _autoPip = value);
|
||||
widget.actions.onAutoPipChanged!(value);
|
||||
},
|
||||
),
|
||||
_actionRow(
|
||||
key: const Key('player-more-offline'),
|
||||
icon: Icons.download_outlined,
|
||||
@@ -153,6 +176,7 @@ class _PlayerMoreSheetState extends State<PlayerMoreSheet> {
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -160,7 +184,7 @@ class _PlayerMoreSheetState extends State<PlayerMoreSheet> {
|
||||
width: double.infinity,
|
||||
padding: const EdgeInsets.symmetric(vertical: _groupVerticalPadding),
|
||||
decoration: BoxDecoration(
|
||||
color: AppColors.card,
|
||||
color: Colors.white.withValues(alpha: 0.06),
|
||||
borderRadius: BorderRadius.circular(_groupRadius),
|
||||
),
|
||||
child: Column(mainAxisSize: MainAxisSize.min, children: rows),
|
||||
@@ -241,7 +265,7 @@ class _PlayerMoreSheetState extends State<PlayerMoreSheet> {
|
||||
horizontal: _segmentTrackPadding,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: AppColors.raised,
|
||||
color: Colors.white.withValues(alpha: 0.08),
|
||||
borderRadius: BorderRadius.circular(_segmentTrackRadius),
|
||||
),
|
||||
child: Row(
|
||||
@@ -286,6 +310,54 @@ class _PlayerMoreSheetState extends State<PlayerMoreSheet> {
|
||||
);
|
||||
}
|
||||
|
||||
/// 开关行:左侧图标+标题,右侧主题色 Switch。
|
||||
Widget _switchRow({
|
||||
required Key key,
|
||||
required IconData icon,
|
||||
required String title,
|
||||
required bool value,
|
||||
required ValueChanged<bool> onChanged,
|
||||
}) {
|
||||
return SizedBox(
|
||||
key: key,
|
||||
height: _rowHeight,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: _rowHorizontalPadding),
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(icon, color: AppColors.onSurface, size: _rowIconSize),
|
||||
const SizedBox(width: _rowIconGap),
|
||||
Expanded(
|
||||
child: Text(
|
||||
title,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: const TextStyle(
|
||||
color: AppColors.onSurface,
|
||||
fontSize: _rowLabelSize,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
),
|
||||
Transform.scale(
|
||||
scale: 0.7,
|
||||
child: Switch(
|
||||
key: const Key('player-more-auto-pip-switch'),
|
||||
value: value,
|
||||
activeThumbColor: AppColors.onSurface,
|
||||
activeTrackColor: AppColors.brandRed,
|
||||
inactiveThumbColor: AppColors.textSecondary,
|
||||
inactiveTrackColor: AppColors.contentBorder,
|
||||
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
||||
onChanged: onChanged,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _actionRow({
|
||||
required Key key,
|
||||
required IconData icon,
|
||||
@@ -380,7 +452,9 @@ class _SegmentButton extends StatelessWidget {
|
||||
padding: const EdgeInsets.symmetric(horizontal: _segmentPadding),
|
||||
alignment: Alignment.center,
|
||||
decoration: BoxDecoration(
|
||||
color: selected ? AppColors.card : AppColors.transparent,
|
||||
color: selected
|
||||
? Colors.white.withValues(alpha: 0.16)
|
||||
: AppColors.transparent,
|
||||
borderRadius: BorderRadius.circular(_segmentRadius),
|
||||
boxShadow: selected
|
||||
? const [
|
||||
|
||||
Reference in new issue
Block a user