mirror of
https://github.com/bggRGjQaUbCoE/PiliPlus.git
synced 2026-05-12 21:17:41 +08:00
improve handling android window mode
Closes #1908 Signed-off-by: dom <githubaccount56556@proton.me>
This commit is contained in:
@@ -10,6 +10,7 @@ import android.content.pm.ShortcutInfo
|
|||||||
import android.content.pm.ShortcutManager
|
import android.content.pm.ShortcutManager
|
||||||
import android.content.res.Configuration
|
import android.content.res.Configuration
|
||||||
import android.graphics.BitmapFactory
|
import android.graphics.BitmapFactory
|
||||||
|
import android.graphics.Point
|
||||||
import android.graphics.drawable.Icon
|
import android.graphics.drawable.Icon
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
@@ -20,6 +21,7 @@ import androidx.core.net.toUri
|
|||||||
import com.ryanheise.audioservice.AudioServiceActivity
|
import com.ryanheise.audioservice.AudioServiceActivity
|
||||||
import io.flutter.embedding.engine.FlutterEngine
|
import io.flutter.embedding.engine.FlutterEngine
|
||||||
import io.flutter.plugin.common.MethodChannel
|
import io.flutter.plugin.common.MethodChannel
|
||||||
|
import kotlin.math.roundToInt
|
||||||
import kotlin.system.exitProcess
|
import kotlin.system.exitProcess
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
@@ -171,6 +173,31 @@ class MainActivity : AudioServiceActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
"maxScreenSize" -> {
|
||||||
|
try {
|
||||||
|
val density = resources.displayMetrics.density
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||||
|
val maxBounds = windowManager.maximumWindowMetrics.bounds
|
||||||
|
result.success(
|
||||||
|
mapOf(
|
||||||
|
"maxWidth" to (maxBounds.width() / density).roundToInt(),
|
||||||
|
"maxHeight" to (maxBounds.height() / density).roundToInt(),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
val realSizePoint = Point()
|
||||||
|
windowManager.defaultDisplay.getRealSize(realSizePoint)
|
||||||
|
result.success(
|
||||||
|
mapOf(
|
||||||
|
"maxWidth" to (realSizePoint.x / density).roundToInt(),
|
||||||
|
"maxHeight" to (realSizePoint.y / density).roundToInt(),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
else -> result.notImplemented()
|
else -> result.notImplemented()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import 'package:PiliPlus/utils/date_utils.dart';
|
|||||||
import 'package:PiliPlus/utils/extension/iterable_ext.dart';
|
import 'package:PiliPlus/utils/extension/iterable_ext.dart';
|
||||||
import 'package:PiliPlus/utils/extension/theme_ext.dart';
|
import 'package:PiliPlus/utils/extension/theme_ext.dart';
|
||||||
import 'package:PiliPlus/utils/json_file_handler.dart';
|
import 'package:PiliPlus/utils/json_file_handler.dart';
|
||||||
|
import 'package:PiliPlus/utils/max_screen_size.dart';
|
||||||
import 'package:PiliPlus/utils/path_utils.dart';
|
import 'package:PiliPlus/utils/path_utils.dart';
|
||||||
import 'package:PiliPlus/utils/platform_utils.dart';
|
import 'package:PiliPlus/utils/platform_utils.dart';
|
||||||
import 'package:PiliPlus/utils/request_utils.dart';
|
import 'package:PiliPlus/utils/request_utils.dart';
|
||||||
@@ -111,7 +112,7 @@ void main() async {
|
|||||||
|
|
||||||
if (PlatformUtils.isMobile) {
|
if (PlatformUtils.isMobile) {
|
||||||
await Future.wait([
|
await Future.wait([
|
||||||
if (Platform.isAndroid) _initSdkInt(),
|
if (Platform.isAndroid) ...[_initSdkInt(), MaxScreenSize.init()],
|
||||||
if (Pref.horizontalScreen) ?fullMode() else ?portraitUpMode(),
|
if (Pref.horizontalScreen) ?fullMode() else ?portraitUpMode(),
|
||||||
setupServiceLocator(),
|
setupServiceLocator(),
|
||||||
]);
|
]);
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ import 'package:PiliPlus/utils/extension/num_ext.dart';
|
|||||||
import 'package:PiliPlus/utils/extension/size_ext.dart';
|
import 'package:PiliPlus/utils/extension/size_ext.dart';
|
||||||
import 'package:PiliPlus/utils/extension/theme_ext.dart';
|
import 'package:PiliPlus/utils/extension/theme_ext.dart';
|
||||||
import 'package:PiliPlus/utils/image_utils.dart';
|
import 'package:PiliPlus/utils/image_utils.dart';
|
||||||
|
import 'package:PiliPlus/utils/max_screen_size.dart';
|
||||||
import 'package:PiliPlus/utils/mobile_observer.dart';
|
import 'package:PiliPlus/utils/mobile_observer.dart';
|
||||||
import 'package:PiliPlus/utils/page_utils.dart';
|
import 'package:PiliPlus/utils/page_utils.dart';
|
||||||
import 'package:PiliPlus/utils/platform_utils.dart';
|
import 'package:PiliPlus/utils/platform_utils.dart';
|
||||||
@@ -100,6 +101,10 @@ class _LiveRoomPageState extends State<LiveRoomPage>
|
|||||||
final size = MediaQuery.sizeOf(context);
|
final size = MediaQuery.sizeOf(context);
|
||||||
maxWidth = size.width;
|
maxWidth = size.width;
|
||||||
maxHeight = size.height;
|
maxHeight = size.height;
|
||||||
|
isWindowMode = MaxScreenSize.isWindowMode(
|
||||||
|
width: maxWidth,
|
||||||
|
height: maxHeight,
|
||||||
|
);
|
||||||
isPortrait = size.isPortrait;
|
isPortrait = size.isPortrait;
|
||||||
plPlayerController.screenRatio = maxHeight / maxWidth;
|
plPlayerController.screenRatio = maxHeight / maxWidth;
|
||||||
}
|
}
|
||||||
@@ -194,6 +199,7 @@ class _LiveRoomPageState extends State<LiveRoomPage>
|
|||||||
|
|
||||||
late double maxWidth;
|
late double maxWidth;
|
||||||
late double maxHeight;
|
late double maxHeight;
|
||||||
|
bool isWindowMode = false;
|
||||||
late EdgeInsets padding;
|
late EdgeInsets padding;
|
||||||
late bool isPortrait;
|
late bool isPortrait;
|
||||||
|
|
||||||
@@ -402,7 +408,7 @@ class _LiveRoomPageState extends State<LiveRoomPage>
|
|||||||
primary: !plPlayerController.removeSafeArea,
|
primary: !plPlayerController.removeSafeArea,
|
||||||
resizeToAvoidBottomInset: false,
|
resizeToAvoidBottomInset: false,
|
||||||
backgroundColor: Colors.transparent,
|
backgroundColor: Colors.transparent,
|
||||||
appBar: isFullScreen && !isPortrait
|
appBar: isWindowMode && isFullScreen && !isPortrait
|
||||||
? null
|
? null
|
||||||
: _buildAppBar(isFullScreen),
|
: _buildAppBar(isFullScreen),
|
||||||
body: isPortrait
|
body: isPortrait
|
||||||
@@ -424,7 +430,7 @@ class _LiveRoomPageState extends State<LiveRoomPage>
|
|||||||
Widget _buildPH(bool isFullScreen) {
|
Widget _buildPH(bool isFullScreen) {
|
||||||
final height = maxWidth / Style.aspectRatio16x9;
|
final height = maxWidth / Style.aspectRatio16x9;
|
||||||
final videoHeight = isFullScreen
|
final videoHeight = isFullScreen
|
||||||
? maxHeight - (isPortrait ? padding.top : 0)
|
? maxHeight - (isWindowMode && !isPortrait ? 0 : padding.top)
|
||||||
: height;
|
: height;
|
||||||
final bottomHeight = maxHeight - padding.top - height - kToolbarHeight;
|
final bottomHeight = maxHeight - padding.top - height - kToolbarHeight;
|
||||||
return Column(
|
return Column(
|
||||||
@@ -453,7 +459,7 @@ class _LiveRoomPageState extends State<LiveRoomPage>
|
|||||||
Widget _buildPP(bool isFullScreen) {
|
Widget _buildPP(bool isFullScreen) {
|
||||||
final bottomHeight = 70 + padding.bottom;
|
final bottomHeight = 70 + padding.bottom;
|
||||||
final videoHeight = isFullScreen
|
final videoHeight = isFullScreen
|
||||||
? maxHeight - (isPortrait ? padding.top : 0)
|
? maxHeight - (isWindowMode && !isPortrait ? 0 : padding.top)
|
||||||
: maxHeight - bottomHeight;
|
: maxHeight - bottomHeight;
|
||||||
return Stack(
|
return Stack(
|
||||||
clipBehavior: Clip.none,
|
clipBehavior: Clip.none,
|
||||||
@@ -707,7 +713,7 @@ class _LiveRoomPageState extends State<LiveRoomPage>
|
|||||||
final videoHeight = maxHeight - padding.top - kToolbarHeight;
|
final videoHeight = maxHeight - padding.top - kToolbarHeight;
|
||||||
final width = isFullScreen ? maxWidth : videoWidth;
|
final width = isFullScreen ? maxWidth : videoWidth;
|
||||||
final height = isFullScreen
|
final height = isFullScreen
|
||||||
? maxHeight - (isPortrait ? padding.top : 0)
|
? maxHeight - (isWindowMode && !isPortrait ? 0 : padding.top)
|
||||||
: videoHeight;
|
: videoHeight;
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: isFullScreen
|
padding: isFullScreen
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ import 'package:PiliPlus/utils/extension/num_ext.dart';
|
|||||||
import 'package:PiliPlus/utils/extension/scroll_controller_ext.dart';
|
import 'package:PiliPlus/utils/extension/scroll_controller_ext.dart';
|
||||||
import 'package:PiliPlus/utils/extension/theme_ext.dart';
|
import 'package:PiliPlus/utils/extension/theme_ext.dart';
|
||||||
import 'package:PiliPlus/utils/image_utils.dart';
|
import 'package:PiliPlus/utils/image_utils.dart';
|
||||||
|
import 'package:PiliPlus/utils/max_screen_size.dart';
|
||||||
import 'package:PiliPlus/utils/mobile_observer.dart';
|
import 'package:PiliPlus/utils/mobile_observer.dart';
|
||||||
import 'package:PiliPlus/utils/num_utils.dart';
|
import 'package:PiliPlus/utils/num_utils.dart';
|
||||||
import 'package:PiliPlus/utils/page_utils.dart';
|
import 'package:PiliPlus/utils/page_utils.dart';
|
||||||
@@ -453,6 +454,10 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
|
|||||||
final size = MediaQuery.sizeOf(context);
|
final size = MediaQuery.sizeOf(context);
|
||||||
maxWidth = size.width;
|
maxWidth = size.width;
|
||||||
maxHeight = size.height;
|
maxHeight = size.height;
|
||||||
|
isWindowMode = MaxScreenSize.isWindowMode(
|
||||||
|
width: maxWidth,
|
||||||
|
height: maxHeight,
|
||||||
|
);
|
||||||
videoDetailController.plPlayerController.screenRatio = maxHeight / maxWidth;
|
videoDetailController.plPlayerController.screenRatio = maxHeight / maxWidth;
|
||||||
|
|
||||||
final shortestSide = size.shortestSide;
|
final shortestSide = size.shortestSide;
|
||||||
@@ -471,8 +476,9 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
|
|||||||
: Theme.of(context);
|
: Theme.of(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool get removeAppBar =>
|
bool removeAppBar(bool isFullScreen) =>
|
||||||
videoDetailController.removeSafeArea || (isFullScreen && !isPortrait);
|
videoDetailController.removeSafeArea ||
|
||||||
|
(isWindowMode && isFullScreen && !isPortrait);
|
||||||
|
|
||||||
Widget get childWhenDisabled {
|
Widget get childWhenDisabled {
|
||||||
return Obx(
|
return Obx(
|
||||||
@@ -480,7 +486,7 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
|
|||||||
final isFullScreen = this.isFullScreen;
|
final isFullScreen = this.isFullScreen;
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
resizeToAvoidBottomInset: false,
|
resizeToAvoidBottomInset: false,
|
||||||
appBar: removeAppBar
|
appBar: removeAppBar(isFullScreen)
|
||||||
? null
|
? null
|
||||||
: PreferredSize(
|
: PreferredSize(
|
||||||
preferredSize: const Size.fromHeight(0),
|
preferredSize: const Size.fromHeight(0),
|
||||||
@@ -520,7 +526,7 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
|
|||||||
onlyOneScrollInBody: true,
|
onlyOneScrollInBody: true,
|
||||||
pinnedHeaderSliverHeightBuilder: () {
|
pinnedHeaderSliverHeightBuilder: () {
|
||||||
double pinnedHeight = this.isFullScreen || !isPortrait
|
double pinnedHeight = this.isFullScreen || !isPortrait
|
||||||
? maxHeight - (isPortrait ? padding.top : 0)
|
? maxHeight - (isWindowMode && !isPortrait ? 0 : padding.top)
|
||||||
: videoDetailController.isExpanding ||
|
: videoDetailController.isExpanding ||
|
||||||
videoDetailController.isCollapsing
|
videoDetailController.isCollapsing
|
||||||
? videoDetailController.animHeight
|
? videoDetailController.animHeight
|
||||||
@@ -546,7 +552,7 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
|
|||||||
},
|
},
|
||||||
headerSliverBuilder: (context, innerBoxIsScrolled) {
|
headerSliverBuilder: (context, innerBoxIsScrolled) {
|
||||||
final height = isFullScreen || !isPortrait
|
final height = isFullScreen || !isPortrait
|
||||||
? maxHeight - (isPortrait ? padding.top : 0)
|
? maxHeight - (isWindowMode && !isPortrait ? 0 : padding.top)
|
||||||
: videoDetailController.isExpanding ||
|
: videoDetailController.isExpanding ||
|
||||||
videoDetailController.isCollapsing
|
videoDetailController.isCollapsing
|
||||||
? videoDetailController.animHeight
|
? videoDetailController.animHeight
|
||||||
@@ -782,7 +788,7 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
|
|||||||
final isFullScreen = this.isFullScreen;
|
final isFullScreen = this.isFullScreen;
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
resizeToAvoidBottomInset: false,
|
resizeToAvoidBottomInset: false,
|
||||||
appBar: removeAppBar
|
appBar: removeAppBar(isFullScreen)
|
||||||
? null
|
? null
|
||||||
: AppBar(backgroundColor: Colors.black, toolbarHeight: 0),
|
: AppBar(backgroundColor: Colors.black, toolbarHeight: 0),
|
||||||
body: Padding(
|
body: Padding(
|
||||||
@@ -923,7 +929,7 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
|
|||||||
final videoWidth = isFullScreen ? maxWidth : width;
|
final videoWidth = isFullScreen ? maxWidth : width;
|
||||||
final double height = width / Style.aspectRatio16x9;
|
final double height = width / Style.aspectRatio16x9;
|
||||||
final videoHeight = isFullScreen
|
final videoHeight = isFullScreen
|
||||||
? maxHeight - (isPortrait ? padding.top : 0)
|
? maxHeight - (isWindowMode && !isPortrait ? 0 : padding.top)
|
||||||
: height;
|
: height;
|
||||||
if (height > maxHeight) {
|
if (height > maxHeight) {
|
||||||
return childSplit(Style.aspectRatio16x9);
|
return childSplit(Style.aspectRatio16x9);
|
||||||
@@ -1017,7 +1023,7 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
|
|||||||
final isFullScreen = this.isFullScreen;
|
final isFullScreen = this.isFullScreen;
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
resizeToAvoidBottomInset: false,
|
resizeToAvoidBottomInset: false,
|
||||||
appBar: removeAppBar
|
appBar: removeAppBar(isFullScreen)
|
||||||
? null
|
? null
|
||||||
: AppBar(backgroundColor: Colors.black, toolbarHeight: 0),
|
: AppBar(backgroundColor: Colors.black, toolbarHeight: 0),
|
||||||
body: Padding(
|
body: Padding(
|
||||||
@@ -1049,7 +1055,7 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
|
|||||||
final shouldShowSeasonPanel = _shouldShowSeasonPanel;
|
final shouldShowSeasonPanel = _shouldShowSeasonPanel;
|
||||||
final double height = maxHeight / 2.5;
|
final double height = maxHeight / 2.5;
|
||||||
final videoHeight = isFullScreen
|
final videoHeight = isFullScreen
|
||||||
? maxHeight - (isPortrait ? padding.top : 0)
|
? maxHeight - (isWindowMode && !isPortrait ? 0 : padding.top)
|
||||||
: height;
|
: height;
|
||||||
final bottomHeight = maxHeight - height - padding.top;
|
final bottomHeight = maxHeight - height - padding.top;
|
||||||
return Column(
|
return Column(
|
||||||
@@ -1298,6 +1304,7 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
|
|||||||
late bool isPortrait;
|
late bool isPortrait;
|
||||||
late double maxWidth;
|
late double maxWidth;
|
||||||
late double maxHeight;
|
late double maxHeight;
|
||||||
|
bool isWindowMode = false;
|
||||||
late EdgeInsets padding;
|
late EdgeInsets padding;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|||||||
25
lib/utils/max_screen_size.dart
Normal file
25
lib/utils/max_screen_size.dart
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
import 'dart:io' show Platform;
|
||||||
|
|
||||||
|
import 'package:PiliPlus/utils/utils.dart';
|
||||||
|
|
||||||
|
abstract final class MaxScreenSize {
|
||||||
|
static int? _maxWidth;
|
||||||
|
static int? _maxHeight;
|
||||||
|
|
||||||
|
static Future<void> init() async {
|
||||||
|
final res = await Utils.channel.invokeMethod('maxScreenSize');
|
||||||
|
if (res is Map) {
|
||||||
|
_maxWidth = res['maxWidth'];
|
||||||
|
_maxHeight = res['maxHeight'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool isWindowMode({required num width, required num height}) {
|
||||||
|
if (!Platform.isAndroid) return false;
|
||||||
|
width = width.round();
|
||||||
|
height = height.round();
|
||||||
|
final hasWidthMatch = width == _maxWidth || width == _maxHeight;
|
||||||
|
final hasHeightMatch = height == _maxWidth || height == _maxHeight;
|
||||||
|
return !(hasWidthMatch && hasHeightMatch);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user