Commit code. Update time: 2023-06-25

This commit is contained in:
TK
2023-06-25 11:50:55 +08:00
parent 2d74227878
commit 39a5f2fa92
244 changed files with 26147 additions and 0 deletions
+9
View File
@@ -0,0 +1,9 @@
import 'dart:core' as core;
import 'package:flutter/foundation.dart';
void print (core.Object object) {
if (kDebugMode) {
core.print(object);
}
}
+54
View File
@@ -0,0 +1,54 @@
import 'dart:convert';
import 'package:crypto/crypto.dart';
import 'package:convert/convert.dart';
/// Encrypt Util.
class EncryptUtil {
/// md5 加密
static String encodeMd5(String data) {
var content = Utf8Encoder().convert(data);
var digest = md5.convert(content);
return hex.encode(digest.bytes);
}
/// 异或对称加密
static String xorCode(String res, String key) {
List<String> keyList = key.split(',');
List<int> codeUnits = res.codeUnits;
List<int> codes = [];
for (int i = 0, length = codeUnits.length; i < length; i++) {
int code = codeUnits[i] ^ int.parse(keyList[i % keyList.length]);
codes.add(code);
}
return String.fromCharCodes(codes);
}
/// 异或对称 Base64 加密
static String xorBase64Encode(String res, String key) {
String encode = xorCode(res, key);
encode = encodeBase64(encode);
return encode;
}
/// 异或对称 Base64 解密
static String xorBase64Decode(String res, String key) {
String encode = decodeBase64(res);
encode = xorCode(encode, key);
return encode;
}
/// Base64加密
static String encodeBase64(String data) {
var content = utf8.encode(data);
var digest = base64Encode(content);
return digest;
}
/// Base64解密
static String decodeBase64(String data) {
List<int> bytes = base64Decode(data);
String result = utf8.decode(bytes);
return result;
}
}
+136
View File
@@ -0,0 +1,136 @@
import 'package:dio/dio.dart';
import 'package:sail/constant/app_strings.dart';
import 'package:sail/router/application.dart';
import 'package:sail/router/routers.dart';
import 'package:sail/utils/common_util.dart';
import 'package:sail/utils/shared_preferences_util.dart';
class HttpUtil {
static HttpUtil get instance => _httpUtil;
static final HttpUtil _httpUtil = HttpUtil();
late Dio dio;
HttpUtil() {
BaseOptions options = BaseOptions(
connectTimeout: 10000,
receiveTimeout: 10000,
);
dio = Dio(options);
dio.interceptors
.add(InterceptorsWrapper(onRequest: (options, handler) async {
//print("========================请求数据===================");
//print("url=${options.uri.toString()}");
//print("headers=${options.headers}");
//print("params=${options.data}");
//如果token存在在请求参数加上token
await SharedPreferencesUtil.getInstance()
?.getString(AppStrings.token)
.then((token) {
if (token != null) {
options.queryParameters[AppStrings.token] = token;
//print("token=$token");
}
});
//如果auth_data存在在请求参数加上auth_data
await SharedPreferencesUtil.getInstance()
?.getString(AppStrings.authData)
.then((authData) {
if (authData != null) {
options.queryParameters[AppStrings.authData] = authData;
//print("authData=$authData");
}
});
return handler.next(options);
}, onResponse: (response, handler) {
//print("========================请求数据===================");
//print("code=${response.statusCode}");
if (response.statusCode! < 200 || response.statusCode! >= 300) {
if (response.statusCode == 403) {
Application.navigatorKey.currentState?.pushNamed(Routers.login);
}
return handler.reject(DioError(
requestOptions: response.requestOptions,
response: response,
type: DioErrorType.response));
}
return handler.next(response);
}, onError: (error, handler) {
//print("========================请求错误===================");
//print("message =${error.message}");
//print("code=${error.response?.statusCode}");
return handler.next(error);
}));
}
//get请求
Future get(String url,
{Map<String, dynamic>? parameters, Options? options}) async {
Response response;
if (parameters != null && options != null) {
response =
await dio.get(url, queryParameters: parameters, options: options);
} else if (parameters != null && options == null) {
response = await dio.get(url, queryParameters: parameters);
} else if (parameters == null && options != null) {
response = await dio.get(url, options: options);
} else {
response = await dio.get(url);
}
return response.data;
}
//post请求
Future post(String url,
{Map<String, dynamic>? parameters, Options? options}) async {
Response response;
if (parameters != null && options != null) {
response = await dio.post(url, data: parameters, options: options);
} else if (parameters != null && options == null) {
response = await dio.post(url, data: parameters);
} else if (parameters == null && options != null) {
response = await dio.post(url, options: options);
} else {
response = await dio.post(url);
}
return response.data;
}
//put请求
Future put(String url,
{Map<String, dynamic>? parameters, Options? options}) async {
Response response;
if (parameters != null && options != null) {
response = await dio.put(url, data: parameters, options: options);
} else if (parameters != null && options == null) {
response = await dio.put(url, data: parameters);
} else if (parameters == null && options != null) {
response = await dio.put(url, options: options);
} else {
response = await dio.put(url);
}
return response.data;
}
//delete请求
Future delete(String url,
{Map<String, dynamic>? parameters, Options? options}) async {
Response response;
if (parameters != null && options != null) {
response = await dio.delete(url, data: parameters, options: options);
} else if (parameters != null && options == null) {
response = await dio.delete(url, data: parameters);
} else if (parameters == null && options != null) {
response = await dio.delete(url, options: options);
} else {
response = await dio.delete(url);
}
return response.data;
}
}
+8
View File
@@ -0,0 +1,8 @@
import 'package:flutter/widgets.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
export 'package:flutter_gen/gen_l10n/app_localizations.dart';
extension AppLocalizationsX on BuildContext {
AppLocalizations get l10n => AppLocalizations.of(this)!;
}
+49
View File
@@ -0,0 +1,49 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
class MessageUtil {
static toast(String msg) {
Fluttertoast.showToast(
msg: msg,
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.CENTER,
timeInSecForIosWeb: 1,
backgroundColor: Colors.black,
textColor: Colors.white,
fontSize: 16.0);
}
static alert(String msg, BuildContext context, {Function? callback}) {
showCupertinoDialog(
context: context,
builder: (context) {
return Material(
color: Colors.transparent,
child: CupertinoAlertDialog(
title: Text("提示"),
content: Text(msg),
actions: <Widget>[
CupertinoButton(
child: Text("确定"),
onPressed: () {
Navigator.pop(context);
callback!();
}),
]),
);
},
);
}
static snack(String msg, BuildContext context) {
ScaffoldMessenger.of(context).hideCurrentSnackBar();
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text(msg),
action: SnackBarAction(
label: "关闭",
onPressed: () => ScaffoldMessenger.of(context).hideCurrentSnackBar(),
),
));
}
}
+80
View File
@@ -0,0 +1,80 @@
import 'dart:convert';
import 'package:fluro/fluro.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:modal_bottom_sheet/modal_bottom_sheet.dart';
import 'package:sail/pages/accountPage.dart';
import 'package:sail/pages/crisp_page.dart';
import 'package:sail/pages/plan/plan_page.dart';
import 'package:sail/pages/server_list.dart';
import 'package:sail/router/application.dart';
import 'package:sail/router/routers.dart';
class NavigatorUtil {
static goHomePage(BuildContext context) {
Application.router?.navigateTo(context, Routers.home,
transition: TransitionType.inFromRight, replace: true);
}
static goLogin(BuildContext context) {
Application.router?.navigateTo(context, Routers.login,
transition: TransitionType.inFromRight, replace: true);
}
static goPlan(BuildContext context) {
showCupertinoModalBottomSheet(
context: context, builder: (context) => const PlanPage());
// Application.router.navigateTo(context, Routers.plan,
// transition: TransitionType.inFromRight);
}
static goSettings(BuildContext context) {
// showCupertinoModalBottomSheet(
// context: context, builder: (context) => const AccountPage());
// Application.router.navigateTo(context, Routers.plan,
// transition: TransitionType.inFromRight);
// Application.router?.navigateTo(context, Routers.account,
// transition: TransitionType.inFromRight, replace: true);
Navigator.of(context)
.push(MaterialPageRoute(builder: (builder) => const AccountPage()));
}
static goServerList(BuildContext context) {
// showCupertinoModalBottomSheet(
// context: context, builder: (context) => const ServerListPage());
showCupertinoModalBottomSheet(
context: context,
builder: (BuildContext context) {
return Container(
height: MediaQuery.of(context).size.height /
1.3, // set height to half of the screen
child: Center(
child: const ServerListPage(),
),
);
},
);
// Application.router.navigateTo(context, Routers.serverList,
// transition: TransitionType.inFromRight);
}
static goToCrisp(BuildContext context) {
showCupertinoModalBottomSheet(
context: context, builder: (context) => const CrispPage());
}
static goWebView(BuildContext context, String titleName, String url) {
String encodeUrl = Uri.encodeComponent(jsonEncode(url));
String encodeTitleName = Uri.encodeComponent(jsonEncode(titleName));
return Application.router?.navigateTo(
context, "${Routers.webView}?titleName=$encodeTitleName&url=$encodeUrl",
transition: TransitionType.inFromRight);
}
static goBack(BuildContext context) {
Application.router?.pop(context);
}
}
@@ -0,0 +1,101 @@
import 'dart:convert';
import 'package:shared_preferences/shared_preferences.dart';
class SharedPreferencesUtil {
SharedPreferencesUtil._();
static SharedPreferencesUtil? _instance;
late SharedPreferences sharedPreferences;
static SharedPreferencesUtil? getInstance() {
_instance ??= SharedPreferencesUtil._();
return _instance;
}
static saveData<T>(String key, T value) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
switch (T) {
case String:
prefs.setString(key, value as String);
break;
case int:
prefs.setInt(key, value as int);
break;
case bool:
prefs.setBool(key, value as bool);
break;
case double:
prefs.setDouble(key, value as double);
break;
}
}
static Future<T?> getData<T>(String key) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
T? res;
switch (T) {
case String:
res = prefs.getString(key) as T;
break;
case int:
res = prefs.getInt(key) as T;
break;
case bool:
res = prefs.getBool(key) as T;
break;
case double:
res = prefs.getDouble(key) as T;
break;
}
return res;
}
Future<bool> setBool(String tag, bool isFirst) async {
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
return sharedPreferences.setBool(tag, isFirst);
}
Future<bool> setString(String tag, String data) async {
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
return sharedPreferences.setString(tag, data);
}
Future<bool> setMap(String tag, Map<String, dynamic>? data) async {
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
return sharedPreferences.setString(tag, jsonEncode(data));
}
Future<bool> setList(String tag, List<dynamic>? data) async {
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
return sharedPreferences.setString(tag, jsonEncode(data));
}
Future<bool?> getBool(String tag) async {
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
return sharedPreferences.getBool(tag);
}
Future<String?> getString(String tag) async {
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
return sharedPreferences.getString(tag);
}
Future<Map<String, dynamic>> getMap(String tag) async {
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
return jsonDecode(sharedPreferences.getString(tag) ?? '{}');
}
Future<List<dynamic>> getList(String tag) async {
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
return jsonDecode(sharedPreferences.getString(tag) ?? '[]');
}
Future<bool> clear() async {
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
return sharedPreferences.clear();
}
}
@@ -0,0 +1,10 @@
import 'package:flutter/material.dart';
SliverGridDelegate gridDelegate(BuildContext context) {
return SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: MediaQuery.of(context).size.width > 500.0 ? 4 : 2,
mainAxisSpacing: 10,
crossAxisSpacing: 10,
childAspectRatio: 100 / 150,
);
}
+167
View File
@@ -0,0 +1,167 @@
import 'dart:async';
import 'dart:convert';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:synchronized/synchronized.dart';
/// SharedPreferences Util.
class SpUtil {
static SpUtil? _singleton;
static SharedPreferences? _prefs;
static Lock _lock = Lock();
static Future<SpUtil?> getInstance() async {
if (_singleton == null) {
await _lock.synchronized(() async {
if (_singleton == null) {
// 保持本地实例直到完全初始化。
var singleton = SpUtil._();
await singleton._init();
_singleton = singleton;
}
});
}
return _singleton;
}
SpUtil._();
Future _init() async {
_prefs = await SharedPreferences.getInstance();
}
/// put object.
static Future<bool>? putObject(String key, Object value) {
if (_prefs == null) return null;
return _prefs!.setString(key, value == null ? "" : json.encode(value));
}
/// get object.
static Map? getObject(String key) {
if (_prefs == null) return null;
String? _data = _prefs!.getString(key);
return (_data == null || _data.isEmpty) ? null : json.decode(_data);
}
/// get object.
static Object? getObject2(String key) {
if (_prefs == null) return null;
String? _data = _prefs!.getString(key);
return (_data == null || _data.isEmpty) ? null : json.decode(_data);
}
/// put object list.
static Future<bool>? putObjectList(String key, List<Object>? list) {
if (_prefs == null) return null;
List<String>? _dataList = list?.map((value) {
return json.encode(value);
}).toList();
return _prefs!.setStringList(key, _dataList ?? []);
}
/// get object list.
static List<Map?>? getObjectList(String key) {
if (_prefs == null) return null;
List<String>? dataLis = _prefs!.getStringList(key);
return dataLis?.map((value) {
Map? _dataMap = json.decode(value);
return _dataMap;
}).toList();
}
/// get string.
static String? getString(String key, {String? defValue = ''}) {
if (_prefs == null) return defValue;
return _prefs!.getString(key) ?? defValue;
}
/// put string.
static Future<bool>? putString(String? key, String value) {
if (_prefs == null) return null;
return _prefs!.setString(key!, value);
}
/// get bool.
static bool getBool(String key, {bool defValue = false}) {
if (_prefs == null) return defValue;
return _prefs!.getBool(key) ?? defValue;
}
/// put bool.
static Future<bool>? putBool(String key, bool value) {
if (_prefs == null) return null;
return _prefs!.setBool(key, value);
}
/// get int.
static int getInt(String key, {int defValue = 0}) {
if (_prefs == null) return defValue;
return _prefs!.getInt(key) ?? defValue;
}
/// put int.
static Future<bool>? putInt(String key, int value) {
if (_prefs == null) return null;
return _prefs!.setInt(key, value);
}
/// get double.
static double getDouble(String key, double defValue) {
if (_prefs == null) return defValue;
return _prefs!.getDouble(key) ?? defValue;
}
/// put double.
static Future<bool>? putDouble(String key, double value) {
if (_prefs == null) return null;
return _prefs!.setDouble(key, value);
}
/// get string list.
static List<String> getStringList(String key,
{List<String> defValue = const []}) {
if (_prefs == null) return defValue;
return _prefs!.getStringList(key) ?? defValue;
}
/// put string list.
static Future<bool>? putStringList(String key, List<String> value) {
if (_prefs == null) return null;
return _prefs!.setStringList(key, value);
}
/// get dynamic.
static dynamic getDynamic(String key, {Object? defValue}) {
if (_prefs == null) return defValue;
return _prefs!.get(key) ?? defValue;
}
/// have key.
static bool? haveKey(String key) {
if (_prefs == null) return null;
return _prefs!.getKeys().contains(key);
}
/// get keys.
static Set<String>? getKeys() {
if (_prefs == null) return null;
return _prefs!.getKeys();
}
/// remove.
static Future<bool>? remove(String key) {
if (_prefs == null) return null;
return _prefs!.remove(key);
}
/// clear.
static Future<bool>? clear() {
if (_prefs == null) return null;
return _prefs!.clear();
}
///Sp is initialized.
static bool isInitialized() {
return _prefs != null;
}
}
+2
View File
@@ -0,0 +1,2 @@
enum Status { success, pending, empty, error, noConnection }
+23
View File
@@ -0,0 +1,23 @@
const welcomeText = 'Welcome';
const welcomeContent = '';
const getStarted = 'Get Started';
const topMovies = 'Top Movies';
const entering = 'entering';
const choseFavoriteGenre =
'Choose your interests and get the best movie recommendations. Don\'t worry, you can always change it later.';
const skip = 'Skip';
const continui = 'Continue';
const seeAll = 'See all';
const populars = 'Popular';
const topRated = 'Top rated movies';
const home = 'Home';
const explore = 'Explore';
const myList = 'My List';
const profile = 'Profile';
const movies = 'Movies';
const tryAgain = 'Try again';
const errorMessage = 'Something went wrong!';
const emptyMessage = 'Your List is Empty';
const play = 'Play';
const releaseDate = 'Release date: ';
+27
View File
@@ -0,0 +1,27 @@
class TransferUtil {
double _transfer = 0;
int _level = 0;
List suffix = [
'B',
'KB',
'MB',
'GB',
'TB',
'PB'
];
String toHumanReadable(int transfer) {
_transfer = transfer.toDouble();
handleTransfer();
return '${_transfer.toStringAsFixed(2)} ${suffix[_level]}';
}
handleTransfer() {
if (_transfer > 1024) {
_transfer = _transfer / 1024;
++_level;
handleTransfer();
}
}
}
+3
View File
@@ -0,0 +1,3 @@
enum RequestStatus { loading, loaded, error }
enum GetAllRequestStatus { loading, loaded, error, fetchMoreError }
+12
View File
@@ -0,0 +1,12 @@
///无参数请求回调
typedef ParamVoidCallback = dynamic Function();
///回调一个参数
typedef ParamSingleCallback<D> = dynamic Function(D data);
///回到俩个参数
typedef ParamTwiceCallback<O, T> = dynamic Function(O dataOne, T dataTwo);
///回调三个参数
typedef ParamThreeCallback<O, T, K> = dynamic Function(
O dataOne, T dataTwo, K threeData);
+248
View File
@@ -0,0 +1,248 @@
import 'package:flutter/material.dart';
// import 'package:sail/go_router.dart';
import 'package:intl/intl.dart';
import 'package:sail/resources/app_colors.dart';
import 'package:sail/resources/app_routes.dart';
import 'package:sail/resources/app_values.dart';
String getDate(String? date) {
if (date == null || date.isEmpty) {
return '';
}
final vals = date.split('-');
String year = vals[0];
int monthNb = int.parse(vals[1]);
String day = vals[2];
String month = '';
switch (monthNb) {
case 1:
month = 'Jan';
break;
case 2:
month = 'Feb';
break;
case 3:
month = 'Mar';
break;
case 4:
month = 'Apr';
break;
case 5:
month = 'May';
break;
case 6:
month = 'Jun';
break;
case 7:
month = 'Jul';
break;
case 8:
month = 'Aug';
break;
case 9:
month = 'Sep';
break;
case 10:
month = 'Oct';
break;
case 11:
month = 'Nov';
break;
case 12:
month = 'Dec';
break;
default:
break;
}
return '$month $day, $year';
}
String getPosterUrl(String? path) {
if (path != null) {
return ApiConstants.basePosterUrl + path;
} else {
return ApiConstants.moviePlaceHolder;
}
}
String getBackdropUrl(String? path) {
if (path != null) {
return ApiConstants.baseBackdropUrl + path;
} else {
return ApiConstants.moviePlaceHolder;
}
}
String getStillUrl(String? path) {
if (path != null) {
return ApiConstants.baseStillUrl + path;
} else {
return ApiConstants.stillPlaceHolder;
}
}
String getLength(int? runtime) {
if (runtime == null || runtime == 0) {
return '';
}
if (runtime < 60) {
return '${runtime}m';
}
if (runtime % 60 == 0) {
return '${runtime ~/ 60}h';
}
return '${runtime ~/ 60}h ${runtime % 60}m';
}
String getVotesCount(int voteCount) {
if (voteCount < 1000) {
return '($voteCount)';
}
return '(${voteCount ~/ 1000}k)';
}
String getProfileImageUrl(Map<String, dynamic> json) {
if (json['profile_path'] != null) {
return ApiConstants.baseProfileUrl + json['profile_path'];
} else {
return ApiConstants.castPlaceHolder;
}
}
class ApiConstants {
static String castPlaceHolder = "";
static String baseProfileUrl = "";
static var baseAvatarUrl = "";
static String avatarPlaceHolder = "";
static var baseVideoUrl = "";
static var basePosterUrl = "";
static String moviePlaceHolder = "";
static var baseStillUrl;
static var baseBackdropUrl;
static String stillPlaceHolder = "";
}
String getElapsedTime(String date) {
DateTime reviewDate = DateTime.parse(date);
DateTime today = DateTime.now();
Duration diff = today.difference(reviewDate);
if (diff.inDays >= 365) {
int years = diff.inDays ~/ 365;
return '${years}y';
} else if (diff.inDays >= 30) {
int months = diff.inDays ~/ 30;
return '${months}mo';
} else if (diff.inDays >= 7) {
int weeks = diff.inDays ~/ 7;
return '${weeks}w';
} else if (diff.inDays >= 1) {
return '${diff.inDays}d';
} else if (diff.inHours >= 1) {
int hours = diff.inHours ~/ 24;
return '${hours}h';
} else if (diff.inMinutes >= 1) {
int minutes = diff.inDays ~/ 60;
return '${minutes}min';
} else {
return 'Now';
}
}
String getGenres(List<dynamic> genres) {
if (genres.isNotEmpty) {
return genres.first['name'];
} else {
return '';
}
}
String getDateFromTimeSpan(int timestamp) {
DateTime dateTime = DateTime.fromMillisecondsSinceEpoch(timestamp);
String formattedTime = DateFormat('yyyy-MM-dd HH:mm:ss').format(dateTime);
return formattedTime;
}
String getAvatarUrl(String? path) {
if (path != null) {
if (path.startsWith('/https://www.gravatar.com/avatar')) {
return path.substring(1);
} else {
return ApiConstants.baseAvatarUrl + path;
}
} else {
return ApiConstants.avatarPlaceHolder;
}
}
String getTrailerUrl(Map<String, dynamic> json) {
List videos = json['videos']['results'];
if (videos.isNotEmpty) {
List trailers = videos.where((e) => e['type'] == 'Trailer').toList();
if (trailers.isNotEmpty) {
return ApiConstants.baseVideoUrl + trailers.last['key'];
} else {
return '';
}
} else {
return '';
}
}
void navigateToDetailsView(BuildContext context, Media media) {
if (media.isMovie) {
// context.pushNamed(
// AppRoutes.movieDetailsRoute,
// params: {'movieId': media.tmdbID.toString()},
// );
} else {
// context.pushNamed(
// AppRoutes.tvShowDetailsRoute,
// params: {'tvShowId': media.tmdbID.toString()},
// );
}
}
class Media {
bool get isMovie => false;
get tmdbID => null;
}
void showCustomBottomSheet(BuildContext context, Widget child) {
final size = MediaQuery.of(context).size.height;
showModalBottomSheet(
context: context,
backgroundColor: AppColors.secondaryBackground,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(
top: Radius.circular(AppSize.s20),
),
),
builder: (context) {
return SizedBox(
height: size * 0.5,
child: child,
);
},
);
}
void showSnackBar(BuildContext context, String content) {
final snackBar = SnackBar(content: Text(content));
ScaffoldMessenger.of(context)
..hideCurrentSnackBar()
..showSnackBar(snackBar);
}
+176
View File
@@ -0,0 +1,176 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'dart:math';
import 'dart:ui' as ui;
// ui适配
class UiUtil {
static const Size _defaultSize = Size(360, 690);
static UiUtil? _instance;
static UiUtil get instance => UiUtil();
/// UI设计中手机尺寸
Size? _uiSize;
/// 控制字体是否要根据系统的“字体大小”辅助选项来进行缩放。默认值为false。
late bool _allowFontScaling;
///屏幕方向
Orientation? _orientation;
double? _pixelRatio;
double? _textScaleFactor;
late double _statusBarHeight;
late double _bottomBarHeight;
double? _screenWidth;
double? _screenHeight;
factory UiUtil() {
if (_instance == null) {
_instance = UiUtil._internal();
}
return _instance!;
}
UiUtil._internal() {
var window = WidgetsBinding.instance.window;
_pixelRatio = window.devicePixelRatio;
_statusBarHeight = window.padding.top;
_bottomBarHeight = window.padding.bottom;
_textScaleFactor = window.textScaleFactor;
_allowFontScaling = false;
_uiSize = _defaultSize;
}
static void init({
BuildContext? context,
Size designSize = _defaultSize,
Orientation orientation = Orientation.portrait,
bool allowFontScaling = false,
}) {
instance._init(
context: context,
designSize: designSize,
orientation: orientation,
allowFontScaling: allowFontScaling,
);
}
void _init({
BuildContext? context,
Size? designSize,
Orientation orientation = Orientation.portrait,
bool allowFontScaling = false,
}) {
this._uiSize = designSize;
this._allowFontScaling = allowFontScaling;
this._orientation = orientation;
if (orientation == Orientation.portrait) {
this._screenWidth = MediaQuery.of(context!).size.width;
this._screenHeight = MediaQuery.of(context).size.height;
} else {
this._screenWidth = MediaQuery.of(context!).size.height;
this._screenHeight = MediaQuery.of(context).size.width;
}
}
///获取屏幕方向
Orientation? get orientation => _orientation;
/// 每个逻辑像素的字体像素数,字体的缩放比例
double? get textScaleFactor => _textScaleFactor;
/// 设备的像素密度
double? get pixelRatio => _pixelRatio;
/// 当前设备宽度 dp
double get screenWidth => _screenWidth ?? _defaultSize.width;
///当前设备高度 dp
double get screenHeight => _screenHeight ?? _defaultSize.height;
/// 状态栏高度 dp 刘海屏会更高
double get statusBarHeight => _statusBarHeight / _pixelRatio!;
/// 底部安全区距离 dp
double get bottomBarHeight => _bottomBarHeight / _pixelRatio!;
/// 实际尺寸与UI设计的比例
double get scaleWidth => (_screenWidth ?? _uiSize!.width) / _uiSize!.width;
double get scaleHeight => (_screenWidth ?? _uiSize!.height) / _uiSize!.height;
double get scaleText => min(scaleWidth, scaleHeight);
/// 根据UI设计的设备宽度适配
double setWidth(num width) => width * scaleWidth;
/// 根据UI设计的设备高度适配
/// 高度适配主要针对想根据UI设计的一屏展示一样的效果
double setHeight(num height) => height * scaleHeight;
///根据宽度或高度中的较小值进行适配
double radius(num r) => r * scaleText;
///字体大小适配方法
double setSp(num fontSize, {bool? allowFontScalingSelf}) =>
allowFontScalingSelf == null
? (_allowFontScaling
? (fontSize * scaleText) * _textScaleFactor!
: (fontSize * scaleText))
: (allowFontScalingSelf
? (fontSize * scaleText) * _textScaleFactor!
: (fontSize * scaleText));
}
///适配文字
@deprecated
num setSp(num size) => UiUtil().setSp(size);
///自动适配,后面方便扩展
@deprecated
num auto(num size) => UiUtil().setWidth(size);
extension NumExtend on num {
///自动适配移动界面
double get dp {
//如果没初始化,需要初始化,防止web端直接导航页面报错
AutoUi.init();
return UiUtil().setWidth(this);
}
///配置文字,文字适配请用sp单位
double get sp {
//如果没初始化,需要初始化,防止web端直接导航页面报错
AutoUi.init();
return UiUtil().setWidth(this);
}
}
class AutoUi {
static AutoUi? _instance;
static void init() {
if (_instance == null) {
_instance = AutoUi();
initAutoUi(Get.context);
}
}
}
//界面适配
void initAutoUi(BuildContext? context) {
if (context != null) return;
UiUtil.init(
// 通过context获取设备像素大小
context: context,
// 设计尺寸
// designSize: Size(1920 / 2.72, 1080 / 2.72),
designSize: Size(1920, 1080),
);
}