lib/utils/screen_util.dart (83 lines of code) (raw):
// Copyright © 2025 Alibaba Cloud. All rights reserved.
//
// Author: keria
// Date: 2025/2/18
// Brief: 屏幕工具类
// import 'package:aliplayer_widget/utils/log_util.dart';
import 'package:flutter/material.dart';
/// 屏幕工具类
class ScreenUtil {
// 私有构造函数,防止实例化
ScreenUtil._();
/// 计算视频的实际渲染尺寸和宽高比
///
/// Calculate the actual rendering size and aspect ratio of the video.
static Size calculateRenderSize(
BuildContext context, {
required Size videoSize,
required bool isFullScreenMode,
}) {
// 获取当前方向和屏幕尺寸
final screenSize = MediaQuery.of(context).size;
// logi("calculateRenderSize: screenSize: $screenSize, videoSize: $videoSize");
// 如果视频尺寸为空或非法,则根据屏幕方向分配默认尺寸
if (videoSize == Size.zero ||
videoSize.width <= 0 ||
videoSize.height <= 0 ||
videoSize.aspectRatio <= 0) {
return screenSize;
}
// 处理竖屏视频的情况下,调整逻辑
if (videoSize.height > videoSize.width) {
return isFullScreenMode
? _calculateVerticalFullScreenDimensions(screenSize, videoSize)
: _calculateVerticalNonFullScreenDimensions(screenSize, videoSize);
}
// 计算视频的宽高比
final aspectRatio = videoSize.aspectRatio;
// 根据模式选择全屏或非全屏计算逻辑
return isFullScreenMode
? _calculateFullScreenDimensions(screenSize, aspectRatio)
: _calculateNonFullScreenDimensions(screenSize, aspectRatio);
}
/// 默认尺寸计算
///
/// Calculate the default dimensions.
static Size calculateDefaultDimensions(BuildContext context) {
final size = MediaQuery.of(context).size;
final shortestSide = size.shortestSide;
double width, height;
// 计算宽和高,确保短边占满屏幕
if (MediaQuery.of(context).orientation == Orientation.portrait) {
width = shortestSide;
height = shortestSide * size.aspectRatio;
} else {
height = shortestSide;
width = shortestSide * size.aspectRatio;
}
return Size(width, height);
}
/// 竖屏模式下全屏显示
static Size _calculateVerticalFullScreenDimensions(
Size screenSize,
Size videoSize,
) {
final videoAspectRatio = videoSize.aspectRatio; // 竖屏的宽高比应该是 < 1
final screenAspectRatio = screenSize.width / screenSize.height;
// 如果屏幕宽高比大于视频宽高比,则优先利用屏幕宽度
if (screenAspectRatio > videoAspectRatio) {
return Size(screenSize.width, screenSize.width / videoAspectRatio);
}
// 否则优先利用屏幕高度
return Size(screenSize.height * videoAspectRatio, screenSize.height);
}
/// 竖屏模式下非全屏显示
static Size _calculateVerticalNonFullScreenDimensions(
Size screenSize,
Size videoSize,
) {
final videoAspectRatio = videoSize.aspectRatio; // 竖屏的宽高比应该是 < 1
final screenAspectRatio = screenSize.width / screenSize.height;
// 如果屏幕宽高比大于视频宽高比,则优先利用屏幕宽度
if (screenAspectRatio > videoAspectRatio) {
return Size(screenSize.width, screenSize.width / videoAspectRatio);
}
// 否则优先利用屏幕高度
return Size(screenSize.height * videoAspectRatio, screenSize.height);
}
/// 全屏模式下的宽高计算
static Size _calculateFullScreenDimensions(
Size screenSize,
double aspectRatio,
) {
final screenAspectRatio = screenSize.width / screenSize.height;
// 根据宽高比判断是否需要留黑边
if (aspectRatio > screenAspectRatio) {
// 视频宽高比大于屏幕宽高比,优先利用屏幕高度
return Size(screenSize.height * aspectRatio, screenSize.height);
} else {
// 视频宽高比小于屏幕宽高比,优先利用屏幕宽度
return Size(screenSize.width, screenSize.width / aspectRatio);
}
}
/// 非全屏模式下的宽高计算
static Size _calculateNonFullScreenDimensions(
Size screenSize,
double aspectRatio,
) {
final screenAspectRatio = screenSize.width / screenSize.height;
// 根据宽高比判断是否需要留黑边
if (aspectRatio > screenAspectRatio) {
// 视频宽高比大于屏幕宽高比,优先利用屏幕宽度
return Size(screenSize.width, screenSize.width / aspectRatio);
} else {
// 视频宽高比小于屏幕宽高比,优先利用屏幕高度
return Size(screenSize.height * aspectRatio, screenSize.height);
}
}
}