深色模式、首页设置页面和功能优化
This commit is contained in:
190
lib/views/home/set/home-set.dart
Normal file
190
lib/views/home/set/home-set.dart
Normal file
@@ -0,0 +1,190 @@
|
||||
/// 时间: 2026-04-02
|
||||
/// 功能: 主页设置和控制组件
|
||||
/// 介绍: 包含收起/恢复悬浮按钮的管理器和组件
|
||||
/// 最新变化: 2026-04-02 初始创建
|
||||
|
||||
import 'dart:async';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import '../../../../constants/app_constants.dart';
|
||||
|
||||
/// 悬浮按钮收起管理器
|
||||
class FloatingButtonsVisibilityManager {
|
||||
static const String _key = 'floating_buttons_visible';
|
||||
|
||||
static FloatingButtonsVisibilityManager? _instance;
|
||||
bool _isVisible = true;
|
||||
bool _isFlashing = false;
|
||||
int _flashCount = 0;
|
||||
final ValueNotifier<bool> _visibleNotifier = ValueNotifier<bool>(true);
|
||||
final ValueNotifier<bool> _flashingNotifier = ValueNotifier<bool>(false);
|
||||
Timer? _hideTimer;
|
||||
Timer? _flashTimer;
|
||||
|
||||
FloatingButtonsVisibilityManager._internal();
|
||||
|
||||
factory FloatingButtonsVisibilityManager() {
|
||||
_instance ??= FloatingButtonsVisibilityManager._internal();
|
||||
return _instance!;
|
||||
}
|
||||
|
||||
Future<void> init() async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
_isVisible = prefs.getBool(_key) ?? true;
|
||||
_visibleNotifier.value = _isVisible;
|
||||
}
|
||||
|
||||
bool get isVisible => _isVisible;
|
||||
bool get isFlashing => _isFlashing;
|
||||
ValueNotifier<bool> get visibleNotifier => _visibleNotifier;
|
||||
ValueNotifier<bool> get flashingNotifier => _flashingNotifier;
|
||||
|
||||
Future<void> toggle() async {
|
||||
if (_isFlashing) {
|
||||
await _restoreFromFlashing();
|
||||
return;
|
||||
}
|
||||
|
||||
_isVisible = !_isVisible;
|
||||
_visibleNotifier.value = _isVisible;
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
await prefs.setBool(_key, _isVisible);
|
||||
|
||||
if (!_isVisible) {
|
||||
_startHideTimer();
|
||||
} else {
|
||||
_cancelAllTimers();
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _restoreFromFlashing() async {
|
||||
_cancelAllTimers();
|
||||
_isFlashing = false;
|
||||
_flashingNotifier.value = false;
|
||||
_isVisible = true;
|
||||
_visibleNotifier.value = true;
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
await prefs.setBool(_key, true);
|
||||
}
|
||||
|
||||
void _startHideTimer() {
|
||||
_cancelAllTimers();
|
||||
_hideTimer = Timer(const Duration(seconds: 5), () {
|
||||
_startFlashing();
|
||||
});
|
||||
}
|
||||
|
||||
void _startFlashing() {
|
||||
_isFlashing = true;
|
||||
_flashingNotifier.value = true;
|
||||
_flashCount = 0;
|
||||
_flashTimer = Timer.periodic(const Duration(seconds: 1), (timer) async {
|
||||
_flashCount++;
|
||||
_flashingNotifier.value = !_flashingNotifier.value;
|
||||
|
||||
if (_flashCount >= 6) {
|
||||
timer.cancel();
|
||||
_isFlashing = false;
|
||||
_flashingNotifier.value = false;
|
||||
_isVisible = false;
|
||||
_visibleNotifier.value = false;
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
await prefs.setBool(_key, false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void _cancelAllTimers() {
|
||||
if (_hideTimer != null) {
|
||||
_hideTimer!.cancel();
|
||||
_hideTimer = null;
|
||||
}
|
||||
if (_flashTimer != null) {
|
||||
_flashTimer!.cancel();
|
||||
_flashTimer = null;
|
||||
}
|
||||
}
|
||||
|
||||
void dispose() {
|
||||
_cancelAllTimers();
|
||||
_visibleNotifier.value = true;
|
||||
_flashingNotifier.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// 收起/恢复悬浮按钮组件
|
||||
class FloatingButtonsToggleButton extends StatelessWidget {
|
||||
final FloatingButtonsVisibilityManager manager;
|
||||
final bool isDark;
|
||||
|
||||
const FloatingButtonsToggleButton({
|
||||
super.key,
|
||||
required this.manager,
|
||||
required this.isDark,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ValueListenableBuilder<bool>(
|
||||
valueListenable: manager.flashingNotifier,
|
||||
builder: (context, isFlashing, child) {
|
||||
return ValueListenableBuilder<bool>(
|
||||
valueListenable: manager.visibleNotifier,
|
||||
builder: (context, isVisible, child) {
|
||||
final shouldShow = isFlashing ? !isFlashing : isVisible;
|
||||
|
||||
return SizedBox(
|
||||
width: 44,
|
||||
height: 44,
|
||||
child: shouldShow || isFlashing
|
||||
? Container(
|
||||
decoration: BoxDecoration(
|
||||
color: isDark ? const Color(0xFF2A2A2A) : Colors.white,
|
||||
shape: BoxShape.circle,
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.black.withAlpha(isDark ? 40 : 20),
|
||||
blurRadius: 8,
|
||||
offset: const Offset(0, 2),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Material(
|
||||
color: Colors.transparent,
|
||||
child: InkWell(
|
||||
borderRadius: BorderRadius.circular(22),
|
||||
onTap: () {
|
||||
manager.toggle();
|
||||
},
|
||||
child: Center(
|
||||
child: Icon(
|
||||
isFlashing
|
||||
? Icons.visibility
|
||||
: Icons.visibility_off,
|
||||
color: isFlashing
|
||||
? AppConstants.primaryColor
|
||||
: (isDark
|
||||
? Colors.grey[300]
|
||||
: AppConstants.primaryColor),
|
||||
size: 24,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
: Material(
|
||||
color: Colors.transparent,
|
||||
child: InkWell(
|
||||
borderRadius: BorderRadius.circular(22),
|
||||
onTap: () {
|
||||
manager.toggle();
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user