1+ import 'dart:async' ;
12import 'dart:io' ;
23import 'package:flutter/material.dart' ;
34import 'package:nipaplay/themes/nipaplay/widgets/video_player_widget.dart' ;
@@ -14,6 +15,7 @@ import 'package:nipaplay/themes/nipaplay/widgets/anime_info_widget.dart';
1415import 'package:nipaplay/utils/tab_change_notifier.dart' ;
1516import 'package:flutter/gestures.dart' ;
1617import 'package:nipaplay/themes/nipaplay/widgets/send_danmaku_button.dart' ;
18+ import 'package:nipaplay/themes/nipaplay/widgets/lock_controls_button.dart' ;
1719import 'package:nipaplay/themes/nipaplay/widgets/skip_button.dart' ;
1820import 'package:nipaplay/themes/nipaplay/widgets/send_danmaku_dialog.dart' ;
1921import '../player_abstraction/player_abstraction.dart' ;
@@ -35,11 +37,20 @@ class _PlayVideoPageState extends State<PlayVideoPage> {
3537 bool _isHoveringBackButton = false ;
3638 double _horizontalDragDistance = 0.0 ;
3739 final GlobalKey <SendDanmakuDialogContentState > _danmakuDialogKey = GlobalKey ();
40+ bool _isUiLocked = false ;
41+ bool _showUiLockButton = false ;
42+ Timer ? _uiLockButtonTimer;
3843
3944 @override
4045 void initState () {
4146 super .initState ();
4247 }
48+
49+ @override
50+ void dispose () {
51+ _uiLockButtonTimer? .cancel ();
52+ super .dispose ();
53+ }
4354
4455 // 处理系统返回键事件
4556 Future <bool > _handleWillPop () async {
@@ -125,6 +136,39 @@ class _PlayVideoPageState extends State<PlayVideoPage> {
125136 }
126137 }
127138
139+ void _toggleUiLock (VideoPlayerState videoState) {
140+ if (! globals.isPhone) return ;
141+ final nextLocked = ! _isUiLocked;
142+ _uiLockButtonTimer? .cancel ();
143+ setState (() {
144+ _isUiLocked = nextLocked;
145+ _showUiLockButton = nextLocked;
146+ });
147+ videoState.setShowControls (! nextLocked);
148+
149+ if (nextLocked) {
150+ _showUiLockButtonTemporarily ();
151+ }
152+ }
153+
154+ void _showUiLockButtonTemporarily ([Duration duration = const Duration (seconds: 3 )]) {
155+ if (! mounted) return ;
156+ if (! globals.isPhone) return ;
157+ if (! _isUiLocked) return ;
158+
159+ _uiLockButtonTimer? .cancel ();
160+ setState (() {
161+ _showUiLockButton = true ;
162+ });
163+ _uiLockButtonTimer = Timer (duration, () {
164+ if (! mounted) return ;
165+ if (! _isUiLocked) return ;
166+ setState (() {
167+ _showUiLockButton = false ;
168+ });
169+ });
170+ }
171+
128172 @override
129173 Widget build (BuildContext context) {
130174 final uiThemeProvider = Provider .of <UIThemeProvider >(context);
@@ -159,6 +203,10 @@ class _PlayVideoPageState extends State<PlayVideoPage> {
159203 }
160204
161205 Widget _buildMaterialControls (VideoPlayerState videoState) {
206+ final bool uiLocked = globals.isPhone ? _isUiLocked : false ;
207+ final bool showLockButton = globals.isPhone &&
208+ (videoState.showControls || (uiLocked && _showUiLockButton));
209+
162210 return Stack (
163211 children: [
164212 Consumer <VideoPlayerState >(
@@ -243,6 +291,40 @@ class _PlayVideoPageState extends State<PlayVideoPage> {
243291 ),
244292 ),
245293 const VideoControlsOverlay (),
294+ if (uiLocked)
295+ Positioned .fill (
296+ child: GestureDetector (
297+ behavior: HitTestBehavior .opaque,
298+ onTap: _showUiLockButtonTemporarily,
299+ child: const SizedBox .expand (),
300+ ),
301+ ),
302+ if (globals.isPhone)
303+ Positioned (
304+ left: 16.0 + (globals.isPhone ? 24.0 : 0.0 ),
305+ top: 0 ,
306+ bottom: 0 ,
307+ child: Center (
308+ child: Transform .translate (
309+ offset: const Offset (0 , - 90 ),
310+ child: AnimatedSlide (
311+ duration: const Duration (milliseconds: 150 ),
312+ offset: Offset (showLockButton ? 0 : - 0.1 , 0 ),
313+ child: AnimatedOpacity (
314+ opacity: showLockButton ? 1.0 : 0.0 ,
315+ duration: const Duration (milliseconds: 150 ),
316+ child: IgnorePointer (
317+ ignoring: ! showLockButton,
318+ child: LockControlsButton (
319+ locked: uiLocked,
320+ onPressed: () => _toggleUiLock (videoState),
321+ ),
322+ ),
323+ ),
324+ ),
325+ ),
326+ ),
327+ ),
246328 ],
247329 );
248330 }
@@ -305,4 +387,4 @@ class _PlayVideoPageState extends State<PlayVideoPage> {
305387 await videoState.player.playDirectly ();
306388 }
307389 }
308- }
390+ }
0 commit comments