Files
xianyan/lib/core/layout/split_divider.dart
Developer 5a49d20c8a chore: 完成项目品牌域名批量替换与功能迭代
本次提交包含多项核心更新:
1. 全量替换项目内所有xianyan.app域名变更为s2ss.com,包含配置文件、路由、隐私政策等
2. 重构图表库从fl_chart迁移至syncfusion_flutter_charts,优化图表渲染效果
3. 新增宽屏分屏布局支持,包含右侧面板注册表与可拖拽分割线
4. 完善触觉反馈服务与认证感知Mixin,修复多处内存泄漏问题
5. 合并勋章墙与金币记录入口至成就中心,简化个人中心导航
6. 新增收藏与时间线数据合并导入功能
7. 修复多处UI样式问题,统一主题颜色使用规范
8. 新增日历同步与跨平台触觉反馈依赖库
9. 修复BotToast初始化流程,避免路由切换时的弹窗崩溃
2026-05-29 10:06:55 +08:00

102 lines
3.1 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.
/// ============================================================
/// 闲言APP — 可拖拽分割线
/// 创建时间: 2026-05-29
/// 更新时间: 2026-05-29
/// 作用: 宽屏分屏的分割线组件支持拖拽调整比例、hover高亮、触觉反馈
/// 上次更新: 初始创建
/// ============================================================
import 'package:flutter/cupertino.dart';
import 'package:flutter/services.dart';
import '../theme/app_theme.dart';
class SplitDivider extends StatefulWidget {
const SplitDivider({
required this.onPositionChanged,
this.currentPosition = 0.4,
this.minPosition = 0.2,
this.maxPosition = 0.7,
this.isVertical = true,
super.key,
});
final ValueChanged<double> onPositionChanged;
final double currentPosition;
final double minPosition;
final double maxPosition;
final bool isVertical;
@override
State<SplitDivider> createState() => _SplitDividerState();
}
class _SplitDividerState extends State<SplitDivider> {
bool _isHovering = false;
bool _isDragging = false;
@override
Widget build(BuildContext context) {
final ext = AppTheme.ext(context);
final dividerColor = ext.textHint.withValues(alpha: 0.15);
final handleColor = _isDragging
? ext.accent.withValues(alpha: 0.8)
: _isHovering
? ext.accent.withValues(alpha: 0.5)
: ext.textHint.withValues(alpha: 0.3);
return MouseRegion(
onEnter: (_) => setState(() => _isHovering = true),
onExit: (_) => setState(() => _isHovering = false),
cursor: SystemMouseCursors.resizeColumn,
child: GestureDetector(
onHorizontalDragStart: _onDragStart,
onHorizontalDragUpdate: _onDragUpdate,
onHorizontalDragEnd: _onDragEnd,
behavior: HitTestBehavior.translucent,
child: Container(
width: 17,
alignment: Alignment.center,
child: Container(
width: 1,
color: dividerColor,
child: Center(
child: AnimatedContainer(
duration: const Duration(milliseconds: 150),
curve: Curves.easeOut,
width: _isDragging ? 6 : _isHovering ? 4 : 4,
height: 32,
decoration: BoxDecoration(
color: handleColor,
borderRadius: BorderRadius.circular(2),
),
),
),
),
),
),
);
}
void _onDragStart(DragStartDetails details) {
setState(() => _isDragging = true);
HapticFeedback.selectionClick();
}
void _onDragUpdate(DragUpdateDetails details) {
final box = context.findRenderObject() as RenderBox;
final parent = box.parent as RenderBox;
final totalWidth = parent.size.width;
if (totalWidth <= 0) return;
final localX = details.globalPosition.dx - parent.localToGlobal(Offset.zero).dx;
final newPosition = (localX / totalWidth).clamp(widget.minPosition, widget.maxPosition);
widget.onPositionChanged(newPosition);
}
void _onDragEnd(DragEndDetails details) {
setState(() => _isDragging = false);
}
}