我有这个应用程序,它有一个 sliverlist 和一个 sliverAppbar。我需要获取 sliverlist 中每个项目的当前滚动位置onscroll,并确定它是否越过 sliverAppbar 并使用该项目的标题更新 sliverappbar。假设从 Item1 开始,一旦它穿过 SliverAppBar,这意味着我正在查看 Item1 内容,当 Item2 穿过 SliverAppBar 时,用标题更新 SliverAppBarItem2意味着用户正在查看Item2内容
我正在尝试使用 a 来实现这一点,NotificationListener<ScrollEndNotification>但我被困在第二个NotificationListener上,它应该在这一行向父级顶部发出通知,ScrollEndNotification(metrics: , context:context).dispatch(context);它会抛出一个错误,我应该提供一个metrics我不知道要提供什么的参数。
SliverList(
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
ScrollEndNotification(metrics: , context:context).dispatch(context);
return AutoScrollTag(
key: ValueKey(index),
controller: controller,
index: index,
child: Padding(
padding: const EdgeInsets.only(
top: 30.0, left: 20.0, right: 20.0),
child: Container(
color: Colors.red,
//height: 120.0
//height: A varying height
),),},); ),
Run Code Online (Sandbox Code Playgroud)
完整的代码是
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.grey[100],
body: NotificationListener<ScrollEndNotification>(
onNotification: (notification) {
if (notification is ScrollEndNotification) {
///Here I need to know what widget index bubbled the notification, its position
///on the screen and its index
//in the list, in order to do further implementation like update the
//SliverAppBar
print('$notification');
return true;
},
child: CustomScrollView(
controller: controller
slivers: <Widget>[
SliverAppBar(
title: Text(title),
),
SliverList(
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
ScrollEndNotification(metrics: , context:context).dispatch(context);
return AutoScrollTag(
key: ValueKey(index),
controller: controller,
index: index,
child: Padding(
padding: const EdgeInsets.only(
top: 30.0, left: 20.0, right: 20.0),
child: Container(
color: Colors.red,
//height: 120.0
//height: A varying height
),),},); ),
Run Code Online (Sandbox Code Playgroud)
另外,如果您对如何实现这一目标有更好的实现,请帮助我。简而言之,我需要跟踪某个项目何时从屏幕上滚出,并index在 Sliverlist 中了解它的情况。请记住,它item有一个可变大小的容器,可以根据其中的子对象数量进行扩展。这是电子商务应用程序中常见的用户体验模式。例如,当用户向下滚动时查看菜单,并在标题穿过屏幕时更新用户正在查看的菜单。
提供要点链接,以便您了解完整的实现
我为不同身高的孩子实现了你想要的。
要制作不同的孩子身高,请随机给出身高。
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:scroll_to_index/scroll_to_index.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
String title = 'Viewing item 0';
Random random = Random();
Map<int, double> itemHeight = {};
int currentHideIndex = 0;
final _mainScrollController = ScrollController();
@override
void initState() {
super.initState();
_mainScrollController.addListener(_onMainScroll);
}
void _onMainScroll() {
int justHiddenIndex =
findIndexJustHidden(_mainScrollController.position.pixels);
print('justHiddenIndex: $justHiddenIndex');
if (currentHideIndex != justHiddenIndex) {
setState(() {
title = 'Viewing item ${justHiddenIndex + 1}';
});
currentHideIndex = justHiddenIndex;
}
}
int findIndexJustHidden(currentPosition) {
int index = -1;
for (var item in itemHeight.entries) {
if (currentPosition > item.value) {
index = item.key;
} else {
if (index != 0) {
return index;
}
}
}
return index;
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.grey[100],
body: CustomScrollView(
controller: _mainScrollController,
slivers: <Widget>[
SliverAppBar(
title: Text(title),
pinned: true,
),
SliverList(
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
double randomHeight;
if (!itemHeight.containsKey(index)) {
randomHeight = (random.nextInt(100) + 40) * 1.0;
print('index: $index, randomHeight: $randomHeight');
double beforeSumHeight =
index == 0 ? 0 : itemHeight[index - 1];
print({
'index': index,
'beforeSumHeight': beforeSumHeight,
'height': randomHeight
});
itemHeight[index] = beforeSumHeight + randomHeight;
} else {
randomHeight = index == 0
? itemHeight[index]
: itemHeight[index] - itemHeight[index - 1];
}
return AutoScrollTag(
key: ValueKey(index),
controller: AutoScrollController(),
index: index,
child: Container(
height: randomHeight,
decoration: BoxDecoration(
color: Colors.red.withOpacity(0.5),
border: Border(
bottom: BorderSide(
color: Color(0XFF000000).withOpacity(0.08),
width: 1.0,
style: BorderStyle.solid,
),
)),
padding: EdgeInsets.only(top: 10, left: 20.0, right: 20.0),
child: Text('$index'),
),
);
},
),
),
],
),
);
}
Widget _buildBody() {
return Container();
}
}
class WidgetSize extends StatefulWidget {
final Widget child;
final Function onChange;
const WidgetSize({
Key key,
@required this.onChange,
@required this.child,
}) : super(key: key);
@override
_WidgetSizeState createState() => _WidgetSizeState();
}
class _WidgetSizeState extends State<WidgetSize> {
@override
Widget build(BuildContext context) {
SchedulerBinding.instance.addPostFrameCallback(postFrameCallback);
return Container(
key: widgetKey,
child: widget.child,
);
}
var widgetKey = GlobalKey();
var oldSize;
void postFrameCallback(_) {
var context = widgetKey.currentContext;
if (context == null) return;
var newSize = context.size;
if (oldSize == newSize) return;
oldSize = newSize;
widget.onChange(newSize);
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2440 次 |
| 最近记录: |