可拖动滚动通知+快照+设置状态



onNotification事件中,使用snap属性设置为true的DraggableScrollableNotification+DraggableScrollableSheet会导致DraggableRollableSheet无法正常工作。

void _update(double extent) {
double _scrollPosition = extent;
setState(() {
newBorderRadiusSize =
((minChildSize * defaulBorderRadiusSize) / _scrollPosition);
newHorizontalPadding =
((horizontalPadding * minChildSize) / _scrollPosition);
newVerticalPadding = ((verticalPadding * minChildSize) / _scrollPosition);
//does not look smooth :/
if (extent >= maxChildSize) {
newBorderRadiusSize = 0;
newHorizontalPadding = 0;
newVerticalPadding = 0;
}
});
}
return NotificationListener<DraggableScrollableNotification>(
onNotification: (notification) {
_update(notification.extent);
return true;
},
child: Positioned.fill(
left: newHorizontalPadding,
right: newHorizontalPadding,
bottom: newVerticalPadding,
child: DraggableScrollableSheet(
maxChildSize: maxChildSize,
minChildSize: minChildSize,
initialChildSize: minChildSize,
controller: _draggableScrollableController,
snap: true,
builder: ((context, scrollController) {

return ClipRRect(
borderRadius: BorderRadius.circular(newBorderRadiusSize),
child: Container(
decoration: BoxDecoration(color: AppColors.secondary),
padding: EdgeInsets.all(16),
child: SingleChildScrollView(
controller: scrollController,
child: Column(
children: [
TaxiDragger(),
Divider(color: Colors.transparent),
TaxiNotification(),
],
),
),
),
);
}),
),
),
);

如果我删除snap属性(默认设置为false(,一切都会很好地工作,但是我希望拥有快照属性

我发现了一件非常有趣的事情:如果您在onNotification函数中修改状态变量而不实际使用setState,它的工作原理与预期的完全一样

class _MyStatefullWidgetState extends State<MyStatefullWidget> {
bool shouldDisplaySomething = false;

@override
Widget build(BuildContext context) => NotificationListener<DraggableScrollableNotification>(
onNotification: (DraggableScrollableNotification event) {
// doing this in setState breaks DraggableScrollableSheet behaviour
shouldDisplaySomething = event.extent > 0.9;
return false;
},
child: DraggableScrollableSheet(
...

似乎DraggableScrollableSheet会导致子项在被拖动时重新渲染,并且新的渲染周期会拾取更新的状态,即使setState没有明确使用

从onNotification函数返回false可能也很重要,因为bool决定了通知冒泡——如果返回true,冒泡将停止,这反过来又会干扰默认的预期行为

在回答我自己的问题时,这似乎是一个关于flutter的错误,在任何情况下,我都可以存档我想要的东西,而不是动画定位,而是在DraggableScrollable中动画容器。

return Positioned.fill(
child: NotificationListener<DraggableScrollableNotification>(
onNotification: (notification) {
_scrolledSize = notification.extent;
newBorderRadiusSize =
((minChildSize * defaulBorderRadiusSize) / _scrolledSize);
newHorizontalPadding =
((horizontalPadding * minChildSize) / _scrolledSize);
newVerticalPadding =
((verticalPadding * minChildSize) / _scrolledSize);
//does not look smooth :/
if (_scrolledSize >= maxChildSize) {
newBorderRadiusSize = 0;
newHorizontalPadding = 0;
newVerticalPadding = 0;
}
return true;
},
child: DraggableScrollableSheet(
maxChildSize: maxChildSize,
minChildSize: minChildSize,
initialChildSize: minChildSize,
controller: _draggableScrollableController,
snap: true,
builder: ((context, scrollController) {
return Container(
decoration: BoxDecoration(
color: AppColors.secondary,
borderRadius: BorderRadius.circular(newBorderRadiusSize)),
//width: newBorderRadiusSize,
margin: EdgeInsets.only(
left: newHorizontalPadding,
right: newHorizontalPadding,
bottom: newVerticalPadding,
),
padding: EdgeInsets.all(16),
child: CustomScrollView(
physics: ClampingScrollPhysics(),
controller: scrollController,
slivers: [
SliverList(
delegate: SliverChildBuilderDelegate(
(context, i) => Column(
children: [
Text(newHorizontalPadding.toString(),
style: TextStyle(fontSize: newHorizontalPadding)),
TaxiDragger(),
Divider(color: Colors.transparent),
TaxiNotification(),
],
),
childCount: 20,
),
)
],
),
);
}),
),
),
);

我希望这能帮助其他人。

最新更新