Skip to content

Commit 7d46d99

Browse files
author
liuchuancong
committed
fix(fullscreen)
1 parent ad6ae5f commit 7d46d99

7 files changed

Lines changed: 130 additions & 41 deletions

File tree

android/app/src/main/AndroidManifest.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
android:usesCleartextTraffic="true"
4141
android:networkSecurityConfig="@xml/network_security_config"
4242
android:requestLegacyExternalStorage="true"
43-
android:enableOnBackInvokedCallback="true"
43+
android:enableOnBackInvokedCallback="false"
4444
android:allowNativeHeapPointerTagging="false"
4545
android:icon="@mipmap/ic_launcher">
4646
<activity android:name=".MainActivity"
@@ -53,7 +53,7 @@
5353
android:hardwareAccelerated="true"
5454
android:resizeableActivity="true"
5555
android:supportsPictureInPicture="true"
56-
android:enableOnBackInvokedCallback="true"
56+
android:enableOnBackInvokedCallback="false"
5757
android:windowSoftInputMode="adjustResize">
5858
<meta-data android:name="io.flutter.embedding.android.NormalTheme"
5959
android:resource="@style/NormalTheme" />

lib/main.dart

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,14 @@ class _MyAppState extends State<MyApp> with DesktopWindowMixin {
9898
title: '纯粹直播',
9999
debugShowCheckedModeBanner: false,
100100
themeMode: AppConsts.themeModes[settings.themeModeName.value]!,
101-
theme: lightTheme.copyWith(appBarTheme: AppBarTheme(surfaceTintColor: Colors.transparent)),
101+
theme: lightTheme.copyWith(
102+
appBarTheme: AppBarTheme(surfaceTintColor: Colors.transparent),
103+
pageTransitionsTheme: const PageTransitionsTheme(
104+
builders: <TargetPlatform, PageTransitionsBuilder>{
105+
TargetPlatform.android: PredictiveBackPageTransitionsBuilder(),
106+
},
107+
),
108+
),
102109
darkTheme: darkTheme.copyWith(appBarTheme: AppBarTheme(surfaceTintColor: Colors.transparent)),
103110
locale: AppConsts.languages[settings.languageName.value]!,
104111
navigatorObservers: [FlutterSmartDialog.observer, BackButtonObserver()],
@@ -111,7 +118,7 @@ class _MyAppState extends State<MyApp> with DesktopWindowMixin {
111118
GlobalCupertinoLocalizations.delegate,
112119
],
113120
initialRoute: showSplashPage ? RoutePath.kSplash : RoutePath.kInitial,
114-
defaultTransition: Platform.isAndroid ? Transition.cupertino : Transition.native,
121+
defaultTransition: Transition.native,
115122
getPages: AppPages.routes,
116123
);
117124
});

lib/modules/live_play/live_play_controller.dart

Lines changed: 28 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import 'package:pure_live/core/danmaku/douyin_danmaku.dart';
1515
import 'package:pure_live/core/interface/live_danmaku.dart';
1616
import 'package:pure_live/modules/live_play/player_state.dart';
1717
import 'package:pure_live/player/switchable_global_player.dart';
18+
import 'package:back_button_interceptor/back_button_interceptor.dart';
1819

1920
enum VideoMode { normal, widescreen, fullscreen }
2021

@@ -69,26 +70,12 @@ class LivePlayController extends StateController with GetSingleTickerProviderSta
6970

7071
final refreshKey = DateTime.now().millisecondsSinceEpoch.obs;
7172

72-
Future<bool> onBackPressed() async {
73-
unawaited(
74-
Future.microtask(() {
75-
success.value = false;
76-
if (videoController.value!.showSettting.value) {
77-
videoController.value!.showSettting.toggle();
78-
}
79-
if (videoController.value!.isFullscreen.value) {
80-
videoController.value!.exitFullScreen();
81-
}
82-
}),
83-
);
84-
return await Future.value(true);
85-
}
86-
8773
@override
8874
void onClose() {
8975
success.value = false;
9076
SwitchableGlobalPlayer().stop();
9177
tabController.dispose();
78+
BackButtonInterceptor.removeByName("live_play_page");
9279
super.onClose();
9380
}
9481

@@ -97,12 +84,18 @@ class LivePlayController extends StateController with GetSingleTickerProviderSta
9784
success.value = false;
9885
SwitchableGlobalPlayer().stop();
9986
tabController.dispose();
87+
if (Platform.isAndroid) {
88+
BackButtonInterceptor.removeByName("live_play_page");
89+
}
10090
super.dispose();
10191
}
10292

10393
@override
10494
void onInit() {
10595
super.onInit();
96+
if (Platform.isAndroid) {
97+
BackButtonInterceptor.add(myInterceptor, zIndex: 1, name: "live_play_page");
98+
}
10699
detail.value = room;
107100
currentSite = Sites.of(site);
108101
liveDanmaku = Sites.of(site).liveSite.getDanmaku();
@@ -145,6 +138,26 @@ class LivePlayController extends StateController with GetSingleTickerProviderSta
145138
});
146139
}
147140

141+
bool myInterceptor(bool stopDefaultButtonEvent, RouteInfo info) {
142+
// 1. 如果是全屏,退出全屏
143+
if (videoController.value!.isFullscreen.value) {
144+
setNormalScreen();
145+
videoController.value!.exitFullScreen();
146+
return true; // 拦截,不让页面关闭
147+
}
148+
149+
// 2. 如果显示设置面板,隐藏它
150+
if (videoController.value!.showSettting.value) {
151+
videoController.value!.showSettting.toggle();
152+
return true; // 拦截,不让页面关闭
153+
}
154+
155+
// 3. 所有特殊状态都处理完了,现在决定是否允许退出页面
156+
// 如果你想直接退出页面:
157+
success.value = false;
158+
return false; // 不拦截,让系统执行默认的返回(关闭页面)
159+
}
160+
148161
Future<LiveRoom> onInitPlayerState({
149162
ReloadDataType reloadDataType = ReloadDataType.refreash,
150163
int line = 0,

lib/modules/live_play/live_play_page.dart

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -15,29 +15,18 @@ class LivePlayPage extends GetView<LivePlayController> {
1515
LivePlayPage({super.key});
1616

1717
final SettingsService settings = Get.find<SettingsService>();
18-
Future<void> onWillPop(bool didPop, Object? result) async {
19-
if (didPop) return;
20-
var shouldPop = await controller.onBackPressed();
21-
if (shouldPop) {
22-
Navigator.of(Get.context!).pop();
23-
}
24-
}
2518

2619
@override
2720
Widget build(BuildContext context) {
2821
if (settings.enableScreenKeepOn.value) {
2922
WakelockPlus.toggle(enable: settings.enableScreenKeepOn.value);
3023
}
31-
return PopScope(
32-
canPop: false,
33-
onPopInvokedWithResult: onWillPop,
34-
child: Obx(() {
35-
if (controller.screenMode.value == VideoMode.normal) {
36-
return buildNormalPlayerView(context);
37-
}
38-
return buildVideoPlayer();
39-
}),
40-
);
24+
return Obx(() {
25+
if (controller.screenMode.value == VideoMode.normal) {
26+
return buildNormalPlayerView(context);
27+
}
28+
return buildVideoPlayer();
29+
});
4130
}
4231

4332
Scaffold buildNormalPlayerView(BuildContext context) {

lib/player/fullscreen.dart

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import 'dart:io';
22
import 'package:flutter/services.dart';
33
import 'package:flutter/foundation.dart';
44
import 'package:window_manager/window_manager.dart';
5+
import 'package:screen_retriever/screen_retriever.dart';
56
import 'package:device_info_plus/device_info_plus.dart';
67
import 'package:auto_orientation_v2/auto_orientation_v2.dart';
78

@@ -17,6 +18,36 @@ Future<void> landScape() async {
1718
await windowManager.setHasShadow(false); // 去掉阴影
1819
await windowManager.setAsFrameless(); // 设置为无边框模式
1920
await windowManager.setFullScreen(true);
21+
// 1. 獲取目前視窗的中心點
22+
Rect windowRect = await windowManager.getBounds();
23+
Offset center = windowRect.center;
24+
25+
// 2. 獲取所有顯示器
26+
List<Display> displays = await screenRetriever.getAllDisplays();
27+
28+
// 3. 尋找視窗中心點在哪個顯示器範圍內
29+
Display currentDisplay = displays.firstWhere((display) {
30+
// 注意:這裡使用 visiblePosition 或 bounds.topLeft
31+
final Offset origin = display.visiblePosition ?? Offset.zero;
32+
final Size size = display.size;
33+
34+
return center.dx >= origin.dx &&
35+
center.dx <= origin.dx + size.width &&
36+
center.dy >= origin.dy &&
37+
center.dy <= origin.dy + size.height;
38+
}, orElse: () => displays.first);
39+
40+
// 4. 根據找到的螢幕設定全螢幕範圍
41+
await windowManager.setBounds(
42+
Rect.fromLTWH(
43+
currentDisplay.visiblePosition!.dx,
44+
currentDisplay.visiblePosition!.dy,
45+
currentDisplay.size.width,
46+
currentDisplay.size.height,
47+
),
48+
);
49+
50+
await windowManager.setAlwaysOnTop(true);
2051
}
2152
} catch (exception, stacktrace) {
2253
debugPrint(exception.toString());
@@ -36,6 +67,35 @@ Future<void> doEnterFullScreen() async {
3667
await windowManager.setHasShadow(false); // 去掉阴影
3768
await windowManager.setAsFrameless(); // 设置为无边框模式
3869
await windowManager.setFullScreen(true);
70+
// 1. 獲取目前視窗的中心點
71+
Rect windowRect = await windowManager.getBounds();
72+
Offset center = windowRect.center;
73+
74+
// 2. 獲取所有顯示器
75+
List<Display> displays = await screenRetriever.getAllDisplays();
76+
77+
// 3. 尋找視窗中心點在哪個顯示器範圍內
78+
Display currentDisplay = displays.firstWhere((display) {
79+
// 注意:這裡使用 visiblePosition 或 bounds.topLeft
80+
final Offset origin = display.visiblePosition ?? Offset.zero;
81+
final Size size = display.size;
82+
83+
return center.dx >= origin.dx &&
84+
center.dx <= origin.dx + size.width &&
85+
center.dy >= origin.dy &&
86+
center.dy <= origin.dy + size.height;
87+
}, orElse: () => displays.first);
88+
89+
// 4. 根據找到的螢幕設定全螢幕範圍
90+
await windowManager.setBounds(
91+
Rect.fromLTWH(
92+
currentDisplay.visiblePosition!.dx,
93+
currentDisplay.visiblePosition!.dy,
94+
currentDisplay.size.width,
95+
currentDisplay.size.height,
96+
),
97+
);
98+
await windowManager.setAlwaysOnTop(true);
3999
}
40100
}
41101

pubspec.lock

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,14 @@ packages:
8989
url: "https://pub.flutter-io.cn"
9090
source: hosted
9191
version: "2.3.7"
92+
back_button_interceptor:
93+
dependency: "direct main"
94+
description:
95+
name: back_button_interceptor
96+
sha256: b85977faabf4aeb95164b3b8bf81784bed4c54ea1aef90a036ab6927ecf80c5a
97+
url: "https://pub.flutter-io.cn"
98+
source: hosted
99+
version: "8.0.4"
92100
battery_plus:
93101
dependency: "direct main"
94102
description:
@@ -1586,12 +1594,13 @@ packages:
15861594
source: hosted
15871595
version: "2.1.0"
15881596
screen_retriever:
1589-
dependency: transitive
1597+
dependency: "direct main"
15901598
description:
1591-
name: screen_retriever
1592-
sha256: "570dbc8e4f70bac451e0efc9c9bb19fa2d6799a11e6ef04f946d7886d2e23d0c"
1593-
url: "https://pub.flutter-io.cn"
1594-
source: hosted
1599+
path: "packages/screen_retriever"
1600+
ref: main
1601+
resolved-ref: b246b3963738d6cc159c921764c194c73dbdf2ad
1602+
url: "https://github.com/MSOB7YY/screen_retriever.git"
1603+
source: git
15951604
version: "0.2.0"
15961605
screen_retriever_linux:
15971606
dependency: transitive

pubspec.yaml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,12 @@ dependencies:
118118
hive_ce_flutter: ^2.3.3
119119
markdown_widget: ^2.3.2+8
120120
google_fonts: ^6.3.3
121+
back_button_interceptor: ^8.0.4
122+
screen_retriever:
123+
git:
124+
url: https://github.com/MSOB7YY/screen_retriever.git
125+
path: ./packages/screen_retriever
126+
ref: main
121127
dependency_overrides:
122128
media_kit:
123129
git:
@@ -159,6 +165,11 @@ dependency_overrides:
159165
url: https://github.com/Predidit/media-kit.git
160166
ref: main
161167
path: ./libs/macos/media_kit_libs_macos_video
168+
screen_retriever:
169+
git:
170+
url: https://github.com/MSOB7YY/screen_retriever.git
171+
path: ./packages/screen_retriever
172+
ref: main
162173
dev_dependencies:
163174
flutter_test:
164175
sdk: flutter

0 commit comments

Comments
 (0)