fix: 更新诸多bug
This commit is contained in:
@@ -103,6 +103,22 @@ class _HICollapsibleItemWidgetState extends State<HICollapsibleItemWidget> {
|
||||
setState(() {
|
||||
_isExpanded = !_isExpanded;
|
||||
});
|
||||
|
||||
if (_isExpanded) {
|
||||
// 在下一帧之后,等待动画接近完成时滚动到可视区域
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
Future.delayed(const Duration(milliseconds: 200), () {
|
||||
if (mounted && _isExpanded) {
|
||||
Scrollable.ensureVisible(
|
||||
context,
|
||||
duration: const Duration(milliseconds: 300),
|
||||
curve: Curves.easeInOut,
|
||||
alignment: 0.1, // 距离顶部留出一点间距
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
},
|
||||
behavior: HitTestBehavior.translucent,
|
||||
child: Padding(
|
||||
|
||||
@@ -79,13 +79,19 @@ class _HiFixedScrollbarState extends State<HiFixedScrollbar>
|
||||
|
||||
bool _onScrollNotification(ScrollNotification notification) {
|
||||
if (!mounted) return false;
|
||||
|
||||
if (_fadeTimer != null && _fadeTimer!.isActive) {
|
||||
_fadeTimer?.cancel();
|
||||
}
|
||||
|
||||
if (notification is ScrollStartNotification ||
|
||||
notification is ScrollUpdateNotification) {
|
||||
_fadeController.forward();
|
||||
_updateThumbPosition();
|
||||
} else if (notification is ScrollMetricsNotification) {
|
||||
// 仅在最大滚动范围变化时更新位置且保持可见
|
||||
// 避免不必要的闪烁
|
||||
_updateThumbPosition();
|
||||
} else if (notification is ScrollEndNotification ||
|
||||
(notification is UserScrollNotification &&
|
||||
notification.direction == ScrollDirection.idle)) {
|
||||
@@ -119,14 +125,18 @@ class _HiFixedScrollbarState extends State<HiFixedScrollbar>
|
||||
return;
|
||||
}
|
||||
|
||||
// 轨道总高度 = 视口高度 - 拇指高度
|
||||
final trackHeight = viewport - widget.thumbHeight.h;
|
||||
final scrollRatio = offset / maxScrollExtent;
|
||||
final newOffset = (trackHeight * scrollRatio).clamp(0.0, trackHeight);
|
||||
// 滚动比例
|
||||
final scrollRatio = (offset / maxScrollExtent).clamp(0.0, 1.0);
|
||||
final newOffset = trackHeight * scrollRatio;
|
||||
|
||||
if (_thumbOffset != newOffset) {
|
||||
setState(() {
|
||||
_thumbOffset = newOffset;
|
||||
});
|
||||
|
||||
// 当位置发生变化时,保持显示一段时间
|
||||
if (_fadeTimer != null && _fadeTimer!.isActive) {
|
||||
_fadeTimer?.cancel();
|
||||
}
|
||||
@@ -134,8 +144,6 @@ class _HiFixedScrollbarState extends State<HiFixedScrollbar>
|
||||
_fadeTimer = Timer(widget.fadeDelay, () {
|
||||
if (mounted) {
|
||||
_fadeController.reverse();
|
||||
} else {
|
||||
_fadeTimer?.cancel();
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -151,67 +159,69 @@ class _HiFixedScrollbarState extends State<HiFixedScrollbar>
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return LayoutBuilder(
|
||||
builder: (_, constraints) {
|
||||
final position =
|
||||
widget.controller.hasClients ? widget.controller.position : null;
|
||||
return NotificationListener<ScrollNotification>(
|
||||
onNotification: _onScrollNotification,
|
||||
child: Stack(
|
||||
children: [
|
||||
widget.child,
|
||||
// 滚动条渲染逻辑移至内部,确保外部组件树(widget.child 的路径)稳定
|
||||
AnimatedBuilder(
|
||||
animation: _fadeController,
|
||||
builder: (context, child) {
|
||||
final position = widget.controller.hasClients
|
||||
? widget.controller.position
|
||||
: null;
|
||||
|
||||
if (position == null || !position.hasContentDimensions) {
|
||||
return widget.child;
|
||||
}
|
||||
if (position == null || !position.hasContentDimensions) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
|
||||
final maxScrollExtent = position.maxScrollExtent;
|
||||
final canShowScrollbar = widget.isShowScrollbar && maxScrollExtent > 0;
|
||||
final maxScrollExtent = position.maxScrollExtent;
|
||||
final canShowScrollbar =
|
||||
widget.isShowScrollbar && maxScrollExtent > 0;
|
||||
|
||||
return Stack(
|
||||
children: [
|
||||
NotificationListener<ScrollNotification>(
|
||||
onNotification: _onScrollNotification,
|
||||
child: widget.child,
|
||||
),
|
||||
if (canShowScrollbar)
|
||||
AnimatedBuilder(
|
||||
animation: _fadeController,
|
||||
builder: (context, child) {
|
||||
return Opacity(
|
||||
opacity: _fadeController.value,
|
||||
child: Stack(
|
||||
children: [
|
||||
// 滚动条轨道 (Track)
|
||||
Positioned(
|
||||
right: widget.right.w.toDouble(),
|
||||
top: 0,
|
||||
bottom: 0,
|
||||
child: Container(
|
||||
width: widget.thickness.w.toDouble(),
|
||||
decoration: BoxDecoration(
|
||||
color: widget.trackColor,
|
||||
borderRadius: BorderRadius.circular(4),
|
||||
),
|
||||
),
|
||||
if (!canShowScrollbar) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
|
||||
return Opacity(
|
||||
opacity: _fadeController.value,
|
||||
child: Stack(
|
||||
children: [
|
||||
// 滚动条轨道 (Track)
|
||||
Positioned(
|
||||
right: widget.right.w.toDouble(),
|
||||
top: 0,
|
||||
bottom: 0,
|
||||
child: Container(
|
||||
width: widget.thickness.w.toDouble(),
|
||||
decoration: BoxDecoration(
|
||||
color: widget.trackColor,
|
||||
borderRadius: BorderRadius.circular(4),
|
||||
),
|
||||
|
||||
// 滚动条拇指 (Thumb)
|
||||
Positioned(
|
||||
right: widget.right.w.toDouble(),
|
||||
top: _thumbOffset,
|
||||
child: Container(
|
||||
width: widget.thickness.w.toDouble(),
|
||||
height: widget.thumbHeight.h.toDouble(),
|
||||
decoration: BoxDecoration(
|
||||
color: widget.thumbColor,
|
||||
borderRadius: BorderRadius.circular(4),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
|
||||
// 滚动条拇指 (Thumb)
|
||||
Positioned(
|
||||
right: widget.right.w.toDouble(),
|
||||
top: _thumbOffset,
|
||||
child: Container(
|
||||
width: widget.thickness.w.toDouble(),
|
||||
height: widget.thumbHeight.h.toDouble(),
|
||||
decoration: BoxDecoration(
|
||||
color: widget.thumbColor,
|
||||
borderRadius: BorderRadius.circular(4),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user