Files
ReelShort/lib/pages/player/widgets/episode_picker_cell.dart
T

130 lines
3.2 KiB
Dart

// 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.55;
/// 选集格子。需要解锁时铺一层透明底,锁在上,集数在锁下面。
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,
color: selected ? AppColors.onPrimary : AppColors.cream,
),
),
if (episode.locked)
_LockCover(
episodeId: episode.id,
number: episode.number,
label: lockLabel,
selected: selected,
),
],
),
),
);
}
}
class _EpisodeNumber extends StatelessWidget {
const _EpisodeNumber(this.number, {required this.color});
final int number;
final Color color;
@override
Widget build(BuildContext context) {
return Text(
'$number',
style: TextStyle(
color: color,
fontSize: _numberSize,
fontWeight: FontWeight.w600,
height: 1,
),
);
}
}
/// 透明底铺满格子,锁在上,集数在锁下面。
class _LockCover extends StatelessWidget {
const _LockCover({
required this.episodeId,
required this.number,
required this.label,
required this.selected,
});
final String episodeId;
final int number;
final String label;
final bool selected;
@override
Widget build(BuildContext context) {
return Stack(
fit: StackFit.expand,
children: [
ColoredBox(
key: ValueKey('episode-lock-cover-$episodeId'),
color: AppColors.card.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.secondary,
semanticLabel: label,
),
const SizedBox(height: _lockGap),
_EpisodeNumber(
number,
color: selected ? AppColors.onPrimary : AppColors.cream,
),
],
),
),
],
);
}
}