feat(player): 未就绪改由进度条展示加载态
This commit is contained in:
1 parent
76cc52ad66
commit
cf4b07aa69
12 files changed
+359
-167
No files matched your search
@@ -7,6 +7,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:video_player/video_player.dart';
|
||||
|
||||
import '../../../core/theme/app_colors.dart';
|
||||
import 'loading_progress_track.dart';
|
||||
|
||||
/// Keeps seeks within the playable range so dragging to the edge does not
|
||||
/// trigger the player's completion callback before playback resumes.
|
||||
@@ -92,6 +93,7 @@ class _SeekProgressBarState extends State<SeekProgressBar> {
|
||||
|
||||
Widget _buildTrack(BuildContext context, VideoPlayerValue video) {
|
||||
final total = video.duration.inMilliseconds;
|
||||
final loading = !video.isInitialized || video.isBuffering;
|
||||
final enabled = video.isInitialized && total > 0 && widget.onSeek != null;
|
||||
final played = total > 0
|
||||
? (video.position.inMilliseconds / total).clamp(0.0, 1.0)
|
||||
@@ -100,7 +102,15 @@ class _SeekProgressBarState extends State<SeekProgressBar> {
|
||||
final previewPosition = _previewFraction.value == null
|
||||
? video.position
|
||||
: seekPositionForFraction(fraction, video.duration);
|
||||
final scrubbing = _previewFraction.value != null;
|
||||
final scrubbing = !loading && _previewFraction.value != null;
|
||||
final trackHeight = widget.compact
|
||||
? (scrubbing ? 3.0 : 1.5)
|
||||
: (scrubbing ? 4.0 : 3.0);
|
||||
final trackAreaHeight = loading
|
||||
? (widget.compact ? 20.0 : 44.0)
|
||||
: widget.compact
|
||||
? (scrubbing ? 32.0 : 20.0)
|
||||
: (scrubbing ? 48.0 : 44.0);
|
||||
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
@@ -120,47 +130,50 @@ class _SeekProgressBarState extends State<SeekProgressBar> {
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
height: widget.compact
|
||||
? (scrubbing ? 32 : 20)
|
||||
: (scrubbing ? 48 : 44),
|
||||
child: SliderTheme(
|
||||
data: SliderTheme.of(context).copyWith(
|
||||
trackHeight: widget.compact
|
||||
? (scrubbing ? 3 : 1.5)
|
||||
: (scrubbing ? 4 : 3),
|
||||
activeTrackColor: AppColors.blue,
|
||||
inactiveTrackColor: widget.inactiveTrackColor,
|
||||
thumbColor: AppColors.onPrimary,
|
||||
thumbShape: RoundSliderThumbShape(
|
||||
enabledThumbRadius: widget.compact
|
||||
? (scrubbing ? 6 : 4)
|
||||
: (scrubbing ? 8 : 6),
|
||||
),
|
||||
overlayShape: RoundSliderOverlayShape(
|
||||
overlayRadius: widget.compact ? 12 : 18,
|
||||
),
|
||||
),
|
||||
child: Semantics(
|
||||
label: widget.semanticsLabel,
|
||||
child: Slider(
|
||||
value: fraction,
|
||||
// 轨道与上方文案共用同一层水平内边距,避免 Slider 默认内缩。
|
||||
padding: EdgeInsets.zero,
|
||||
onChangeStart: enabled
|
||||
? (value) {
|
||||
_previewFraction.value = value;
|
||||
widget.onScrubStart?.call();
|
||||
}
|
||||
: null,
|
||||
onChanged: enabled
|
||||
? (value) => _previewFraction.value = value
|
||||
: null,
|
||||
onChangeEnd: enabled
|
||||
? (value) => unawaited(_finish(value, video.duration))
|
||||
: null,
|
||||
),
|
||||
),
|
||||
),
|
||||
height: trackAreaHeight,
|
||||
child: loading
|
||||
? Center(
|
||||
child: LoadingProgressTrack(
|
||||
height: trackHeight,
|
||||
trackColor: widget.inactiveTrackColor,
|
||||
),
|
||||
)
|
||||
: SliderTheme(
|
||||
data: SliderTheme.of(context).copyWith(
|
||||
trackHeight: trackHeight,
|
||||
activeTrackColor: AppColors.blue,
|
||||
inactiveTrackColor: widget.inactiveTrackColor,
|
||||
thumbColor: AppColors.onPrimary,
|
||||
thumbShape: RoundSliderThumbShape(
|
||||
enabledThumbRadius: widget.compact
|
||||
? (scrubbing ? 6 : 4)
|
||||
: (scrubbing ? 8 : 6),
|
||||
),
|
||||
overlayShape: RoundSliderOverlayShape(
|
||||
overlayRadius: widget.compact ? 12 : 18,
|
||||
),
|
||||
),
|
||||
child: Semantics(
|
||||
label: widget.semanticsLabel,
|
||||
child: Slider(
|
||||
value: fraction,
|
||||
// 轨道与上方文案共用同一层水平内边距,避免 Slider 默认内缩。
|
||||
padding: EdgeInsets.zero,
|
||||
onChangeStart: enabled
|
||||
? (value) {
|
||||
_previewFraction.value = value;
|
||||
widget.onScrubStart?.call();
|
||||
}
|
||||
: null,
|
||||
onChanged: enabled
|
||||
? (value) => _previewFraction.value = value
|
||||
: null,
|
||||
onChangeEnd: enabled
|
||||
? (value) => unawaited(_finish(value, video.duration))
|
||||
: null,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
Reference in new issue
Block a user