feat(ui): 更新品牌启动页与选集交互
This commit is contained in:
1 parent
4778ce2c75
commit
c1cb7d1c11
87 files changed
+919
-552
No files matched your search
@@ -0,0 +1,116 @@
|
||||
// Author: fruit.com.cn
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../../core/data/models/drama.dart';
|
||||
import '../../../core/theme/app_colors.dart';
|
||||
|
||||
const double _cellRadius = 8;
|
||||
const double _numberSize = 15;
|
||||
const double _lockSize = 16;
|
||||
const double _lockGap = 4;
|
||||
const double _lockWeight = 300;
|
||||
const double _coverAlpha = 0.45;
|
||||
|
||||
/// 选集格子。需要解锁时铺一层透明底,锁在上,集数在锁下面。
|
||||
class EpisodePickerCell extends StatelessWidget {
|
||||
const EpisodePickerCell({
|
||||
required this.episode,
|
||||
required this.selected,
|
||||
required this.lockLabel,
|
||||
required this.onTap,
|
||||
super.key,
|
||||
});
|
||||
|
||||
final Episode episode;
|
||||
final bool selected;
|
||||
final String lockLabel;
|
||||
final VoidCallback onTap;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Material(
|
||||
clipBehavior: Clip.antiAlias,
|
||||
color: selected ? AppColors.bluePressed : AppColors.raised,
|
||||
borderRadius: BorderRadius.circular(_cellRadius),
|
||||
child: InkWell(
|
||||
onTap: onTap,
|
||||
child: Stack(
|
||||
fit: StackFit.expand,
|
||||
children: [
|
||||
if (!episode.locked) Center(child: _EpisodeNumber(episode.number)),
|
||||
if (episode.locked)
|
||||
_LockCover(
|
||||
episodeId: episode.id,
|
||||
number: episode.number,
|
||||
label: lockLabel,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _EpisodeNumber extends StatelessWidget {
|
||||
const _EpisodeNumber(this.number);
|
||||
|
||||
final int number;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Text(
|
||||
'$number',
|
||||
style: const TextStyle(
|
||||
color: AppColors.cream,
|
||||
fontSize: _numberSize,
|
||||
fontWeight: FontWeight.w600,
|
||||
height: 1,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// 透明底铺满格子,锁在上,集数在锁下面。
|
||||
class _LockCover extends StatelessWidget {
|
||||
const _LockCover({
|
||||
required this.episodeId,
|
||||
required this.number,
|
||||
required this.label,
|
||||
});
|
||||
|
||||
final String episodeId;
|
||||
final int number;
|
||||
final String label;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Stack(
|
||||
fit: StackFit.expand,
|
||||
children: [
|
||||
ColoredBox(
|
||||
key: ValueKey('episode-lock-cover-$episodeId'),
|
||||
color: AppColors.ink.withValues(alpha: _coverAlpha),
|
||||
),
|
||||
Center(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Icon(
|
||||
Icons.lock_outline,
|
||||
key: ValueKey('episode-lock-$episodeId'),
|
||||
size: _lockSize,
|
||||
weight: _lockWeight,
|
||||
fill: 0,
|
||||
color: AppColors.gold,
|
||||
semanticLabel: label,
|
||||
),
|
||||
const SizedBox(height: _lockGap),
|
||||
_EpisodeNumber(number),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user