gpt4 book ai didi

flutter - CustomScrollView 内带有 TabBar 和 SliverList 的 SliverAppBar 导致 : ScrollController is currently attached to more than one ScrollPosition

转载 作者:行者123 更新时间:2023-12-05 04:36:39 49 4
gpt4 key购买 nike

SliverAppBar 带有 TabBar 和项目列表,导致滚动 Controller 报错。

我用下面的方式实现了它,有一个 NestedScrollView 有一个 SliverAppBar,一个 SliverPersistentHeader 包含 TabBar 然后是 NestedScrollView 的主体,其中包含 TabBarViewCustomScrollViews 内的 SliverLists

滚动 Controller 似乎会导致问题。它说它附加到多个 View 。因此,我尝试向每个自定义 ScrollView 添加一个新的滚动 Controller ,但这会阻止条形应用栏在滚动列表本身时折叠。

除此之外,它也不会记住切换选项卡时的滚动状态...我尝试过使用 AutomaticKeepAliveClientMixin,但这似乎不起作用。任何关于如何解决滚动问题和滚动 Controller 状态的建议都会受到欢迎? :)

另请注意:我只在 Flutter Web 上进行测试,而不是在移动设备上进行测试...

不知道是我代码的bug还是flutter的bug。

请看下面我的 flutter 医生:

Doctor summary (to see all details, run flutter doctor -v):
[√] Flutter (Channel unknown, 2.5.0, on Microsoft Windows [Version 10.0.22000.434], locale en-ZA)
[!] Android toolchain - develop for Android devices (Android SDK version 29.0.3)
X cmdline-tools component is missing
Run `path/to/sdkmanager --install "cmdline-tools;latest"`
See https://developer.android.com/studio/command-line for more details.
X Android license status unknown.
Run `flutter doctor --android-licenses` to accept the SDK licenses.
See https://flutter.dev/docs/get-started/install/windows#android-setup for more details.
[√] Chrome - develop for the web
[√] Android Studio (version 4.0)
[√] Connected device (2 available)

! Doctor found issues in 1 category.

滚动 Controller 抛出的异常如下:

══╡ EXCEPTION CAUGHT BY ANIMATION LIBRARY ╞═════════════════════════════════════════════════════════
The following assertion was thrown while notifying status listeners for AnimationController:
The provided ScrollController is currently attached to more than one ScrollPosition.
The Scrollbar requires a single ScrollPosition in order to be painted.
When the scrollbar is interactive, the associated Scrollable widgets must have unique
ScrollControllers. The provided ScrollController must be unique to a Scrollable widget.

When the exception was thrown, this was the stack:
C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart 251:49 throw_
packages/flutter/src/widgets/scrollbar.dart 1315:9 <fn>
packages/flutter/src/widgets/scrollbar.dart 1338:14 [_debugCheckHasValidScrollPosition]
packages/flutter/src/widgets/scrollbar.dart 1257:14 [_validateInteractions]
packages/flutter/src/animation/listener_helpers.dart 233:27 notifyStatusListeners
packages/flutter/src/animation/animation_controller.dart 814:7 [_checkStatusChanged]
packages/flutter/src/animation/animation_controller.dart 748:5 [_startSimulation]
packages/flutter/src/animation/animation_controller.dart 611:12 [_animateToInternal]
packages/flutter/src/animation/animation_controller.dart 495:12 reverse
packages/flutter/src/widgets/scrollbar.dart 1412:37 <fn>
C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/_internal/js_dev_runtime/private/isolate_helper.dart 48:19 internalCallback

The AnimationController notifying status listeners was:
AnimationController#25a6e(◀ 1.000)

下面是我的代码:

class MyApp extends StatefulWidget {

MyApp({Key? key}) : super(key: key);

@override
State<MyApp> createState() {
return _MyAppState();
}
}

class _MyAppState extends State<MyApp> { // with AutomaticKeepAliveClientMixin

ScrollController _scrollController = ScrollController();
bool _isAppBarExpanded = true;

@override
void initState() {
super.initState();

_scrollController.addListener(() {
_isAppBarExpanded = _scrollController.hasClients && _scrollController.offset < (200 - kToolbarHeight);
setState(() { });
});
}

@override
Widget build(BuildContext context) {
// super.build(context); // AutomaticKeepAlive

const String title = "Floating App Bar";

return MaterialApp(
title: title,
home: Scaffold(
body: DefaultTabController(
length: 2,
child: NestedScrollView(
controller: _scrollController,
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
return <Widget> [
SliverAppBar(
backgroundColor: (_isAppBarExpanded) ? Colors.white : Colors.blue,
expandedHeight: 200.0,
floating: false,
pinned: true,
flexibleSpace: FlexibleSpaceBar(
centerTitle: true,
title: Text(
"Collapsing Toolbar",
style: TextStyle(
color: Colors.white,
fontSize: 16.0,
),
),
background: ClipRRect(
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(30.0),
bottomRight: Radius.circular(30.0),
),
child: Image.network(
"https://images.pexels.com/photos/396547/pexels-photo-396547.jpeg?auto=compress&cs=tinysrgb&h=350",
fit: BoxFit.cover,
),
),
),
),
SliverPersistentHeader(
delegate: _SliverAppBarDelegate(
TabBar(
labelColor: Colors.black87,
unselectedLabelColor: Colors.grey,
tabs: <Widget> [
Tab(
icon: Icon(Icons.info),
text: "Tab 1",
),

Tab(
icon: Icon(Icons.lightbulb_outline),
text: "Tab 2",
),
],
),
),
pinned: true,
),
];
},
body: TabBarView(
children: <Widget> [
CustomScrollView(
slivers: <Widget> [
SliverList(
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
return Text("Item " + index.toString());
},
childCount: 200,
// addAutomaticKeepAlives: true,
),
),
],
),
CustomScrollView(
slivers: <Widget> [
SliverList(
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
return Text("Test " + index.toString());
},
childCount: 100,
// addAutomaticKeepAlives: true,
),
),
],
),
],
),
),
),
),
);
}

// for AutomaticKeepAlive
// @override
// bool get wantKeepAlive {
// return true;
// }
}

class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
_SliverAppBarDelegate(this._tabBar);

final TabBar _tabBar;

@override
double get minExtent {
return _tabBar.preferredSize.height + 30;
}

@override
double get maxExtent {
return _tabBar.preferredSize.height + 30;
}

@override
Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) {
return Container(
alignment: Alignment.center,
color: Theme.of(context).scaffoldBackgroundColor,
child: Padding(
padding: EdgeInsets.only(top: 15.0, bottom: 15.0),
child: _tabBar,
),
);
}

@override
bool shouldRebuild(_SliverAppBarDelegate oldDelegate) {
return false;
}
}

最佳答案

这个问题可以通过在CustomScrollView上添加另一个ScrollController来解决。

final ScrollController _scrollController2 = ScrollController();
....
TabBarView(
children: <Widget>[
CustomScrollView(
controller: _scrollController2,

您还可以将另一个添加到下一个 CustomScrollView

关于flutter - CustomScrollView 内带有 TabBar 和 SliverList 的 SliverAppBar 导致 : ScrollController is currently attached to more than one ScrollPosition,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70785638/

49 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com