Files
CloudHome-Ops/lib/providers/display_provider.dart

98 lines
3.2 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:shared_preferences/shared_preferences.dart';
/// 显示方向偏好:跟随系统 / 竖屏 / 横屏。
///
/// 与主题、语言并列,作为「我的」页可手动切换的显示设置;切换后通过
/// [SystemChrome.setPreferredOrientations] 实时生效,并重渲染界面(横屏沿用
/// NavigationRail 布局,竖屏沿用 NavigationBar 布局,二者共用同一套橙白主题,
/// 视觉风格保持一致)。
enum DisplayOrientation {
/// 跟随系统(默认):允许全部四个方向,由设备物理朝向决定。
system,
/// 仅竖屏。
portrait,
/// 仅横屏。
landscape,
}
const String _kDisplayOrientation = 'display_orientation';
/// 将偏好映射为 [SystemChrome] 需要的设备方向列表。
List<DeviceOrientation> deviceOrientationsFor(DisplayOrientation mode) {
switch (mode) {
case DisplayOrientation.portrait:
return const [DeviceOrientation.portraitUp];
case DisplayOrientation.landscape:
return const [DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight];
case DisplayOrientation.system:
return const [
DeviceOrientation.portraitUp,
DeviceOrientation.portraitDown,
DeviceOrientation.landscapeLeft,
DeviceOrientation.landscapeRight,
];
}
}
/// 立即应用显示方向(调用 [SystemChrome.setPreferredOrientations])。
void applyDisplayOrientation(DisplayOrientation mode) {
SystemChrome.setPreferredOrientations(deviceOrientationsFor(mode));
}
/// 从持久化读取已保存偏好;异常或无记录时返回 [DisplayOrientation.system]。
Future<DisplayOrientation> loadSavedOrientation() async {
try {
final prefs = await SharedPreferences.getInstance();
final v = prefs.getString(_kDisplayOrientation);
if (v != null) {
for (final e in DisplayOrientation.values) {
if (e.name == v) return e;
}
}
} catch (_) {
// 忽略:SharedPreferences 不可用时退化为系统。
}
return DisplayOrientation.system;
}
/// 显示方向偏好管理(持久化 + 实时生效)。
class DisplayOrientationNotifier extends Notifier<DisplayOrientation> {
@override
DisplayOrientation build() {
// 首选项在 main 启动期已应用;这里异步回读以保证 UI 选中态与持久值一致。
_load();
return DisplayOrientation.system;
}
Future<void> _load() async {
final saved = await loadSavedOrientation();
if (saved != state) {
state = saved;
applyDisplayOrientation(saved);
}
}
/// 切换显示方向:更新状态、即时生效并持久化。
Future<void> set(DisplayOrientation mode) async {
state = mode;
applyDisplayOrientation(mode);
try {
final prefs = await SharedPreferences.getInstance();
await prefs.setString(_kDisplayOrientation, mode.name);
} catch (_) {
// 忽略持久化失败,运行时仍生效。
}
}
}
/// 显示方向偏好提供者。
final displayOrientationProvider =
NotifierProvider<DisplayOrientationNotifier, DisplayOrientation>(
DisplayOrientationNotifier.new,
);