Flutter嵌套布局插件nester的使用
Flutter嵌套布局插件nester的使用
nester
Flutter库用于将一个Widget列表转换为一组嵌套的Widget。这是一个美化插件,以简化代码语法。
特性
- 简化代码语法
- 可以像处理普通列表一样管理
- 可以像处理队列一样管理
安装
添加依赖
dependencies:
nester: ^1.2.1
导入包
import 'package:nester/nester.dart';
示例用法
NESTER LIST
将作为简单的列表处理。每个项目在列表中只允许有一个"next"引用。这是使用Nester最简单的方式。建议在你的列表中大多数情况下只有一个子Widget时使用。
原始代码
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Scaffold(
appBar: AppBar(
title: const Text("Example"),
),
body: Padding(
padding: const EdgeInsets.all(20),
child: Container(
color: Colors.black12,
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: const <Widget>[Text("Just a description")],
),
),
),
),
),
);
使用Nester
return Nester.list([
(next) => MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(primarySwatch: Colors.blue),
home: next,
),
(next) => Scaffold(
appBar: AppBar(title: const Text("Example")),
body: next,
),
(next) => Padding(
padding: const EdgeInsets.all(20),
child: next,
),
(next) => Container(
color: Colors.black12,
child: next,
),
(next) => Center(child: next),
(_) => Column(
mainAxisAlignment: MainAxisAlignment.center,
children: const <Widget>[Text("Just a text")],
),
]);
注意: 列表中的最后一个next项将始终是一个空的Container对象。因此传递它是多余的。
NESTER QUEUE
Widget列表将被当作队列处理。每次"next"调用都会消耗列表中的下一个元素。这在你使用包含多个子Widget的Widget时非常有用。
原始代码
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(primarySwatch: Colors.blue),
home: Scaffold(
appBar: AppBar(
title: const Text("Example"),
),
body: Padding(
padding: const EdgeInsets.all(50),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: const [
Text("Left", textAlign: TextAlign.left),
Text("Center", textAlign: TextAlign.center),
Text("Right", textAlign: TextAlign.right),
],
),
),
),
);
使用Nester
return Nester.queue([
(next) => MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(primarySwatch: Colors.blue),
home: next(),
),
(next) => Scaffold(
appBar: next() as PreferredSizeWidget,
body: next(),
),
(_) => AppBar(title: const Text("Example")),
(next) => Padding(
padding: const EdgeInsets.all(50),
child: next(),
),
(next) => Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: next(take: 3), // 或者 [ next(), next(), next() ],
),
(_) => const Text("Left", textAlign: TextAlign.left),
(_) => const Text("Center", textAlign: TextAlign.center),
(_) => const Text("Right", textAlign: TextAlign.right),
]);
Skip 和 Take
next({int skip, int take})函数接受两个参数。
- 参数
skip会跳过队列列表中的n个调用。请注意,该函数不会检查嵌套调用,只是跳过列表中的下一个n个项目。skip总是先于take应用。 - 参数
take会消耗同一级别的n个项目。如果一个项目有嵌套调用,则不会被计算为已消耗。结果将是一个Widget数组。
约束条件
- 如果
skip和take小于0,则被视为0。 - 如果
skip不是null或0且take为null,则返回一个空的Container。
抛出范围异常
queue构造函数接受throwRangeException(默认值为false)来避免RangeError检查。如果为true,则每次调用next超出列表边界时都会抛出RangeError异常。
当使用take参数时,结果数组不会超过列表中剩余项目的数量。如果不使用take且next调用超出列表边界,则返回一个空的Container。
深度在队列模式下
使用skip和take参数可能会造成混淆,因此编写一些示例来更好地解释它们的行为。
假设有一个布尔变量trigger用于跳过Column组件中的某些项。
return Nester.queue([
...,
(next) => Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
next(skip: trigger ? 0: 2),
next(),
next(),
]),
(next) => Padding(..., child: next()),
(_) => const Text("If trigger true"),
(_) => const Text("Always show"),
(_) => const Text("Always show"),
]);
或者
return Nester.queue([
...,
(next) => Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: []
..addAll(next(skip: trigger ? 0: 2, take: trigger ? 1: 0))
..addAll(next(take: 2)),
),
(next) => Padding(..., child: next()),
(_) => const Text("If trigger true"),
(_) => const Text("Always show"),
(_) => const Text("Always show"),
]);
如果trigger为true,则skip为0且take为1。如果trigger为false,则skip为2且take为0。
为什么skip为2?
因为skip不会进入树中检查嵌套项。它只会跳过原始列表中的项。因此需要跳过下一个Padding和Text(两个项)。而take会消耗所有树中的项。take为1意味着消耗下一个Padding然后消耗下一个Text(两个项)。
为什么使用addAll?
因为在使用take参数时,结果总是会是一个Widget数组,即使取值为0或1。
NESTER EXTENDED
Queue的一个扩展。将以与queue相同的方式处理,但通过在next函数中添加一个额外的参数来传递dynamic值。
return Nester.extended([
(next, _) => MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(primarySwatch: Colors.blue),
home: next(),
),
(next, _) => Scaffold(
appBar: next(param: "Example") as PreferredSizeWidget,
body: next(),
),
(_, title) => AppBar(title: Text(title)),
(next, _) => Padding(
padding: const EdgeInsets.all(50),
child: next(),
),
(next, _) => Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: next(take: 3, param: ["Left", "Center", "Right"]),
),
(_, param) => Text(param[0], textAlign: TextAlign.left),
(_, param) => Text(param[1], textAlign: TextAlign.center),
(_, param) => Text(param[2], textAlign: TextAlign.right),
]);
更多关于Flutter嵌套布局插件nester的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter嵌套布局插件nester的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,下面是一个关于如何在Flutter中使用nested_scroll_view插件(虽然nester不是Flutter官方或广泛认知的插件名,但基于您的要求,我假设您指的是实现嵌套滚动功能的插件或模式,这在Flutter中通常通过NestedScrollView实现)的示例代码。
NestedScrollView是Flutter中用于创建嵌套滚动视图的强大组件,它允许内部滚动视图(如ListView)与外部滚动视图(如Column中包含的其他可滚动部件)协同工作。
以下是一个简单的示例,展示了如何使用NestedScrollView结合SliverAppBar和SliverList来实现一个带有可折叠工具栏的嵌套布局:
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'NestedScrollView Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: NestedScrollViewDemo(),
);
}
}
class NestedScrollViewDemo extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('NestedScrollView Demo'),
),
body: NestedScrollView(
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
return <Widget>[
SliverAppBar(
title: Text('SliverAppBar'),
pinned: true,
expandedHeight: 200.0,
flexibleSpace: FlexibleSpaceBar(
background: Image.network(
'https://via.placeholder.com/1500x500',
fit: BoxFit.cover,
),
),
actions: <Widget>[
IconButton(
icon: Icon(Icons.search),
tooltip: 'Search',
onPressed: () {},
),
],
),
];
},
body: Builder(
builder: (BuildContext context) {
return Column(
children: <Widget>[
Container(
color: Colors.amber[600],
height: 50,
child: Center(
child: Text('Fixed Header'),
),
),
Expanded(
child: ListView.builder(
itemCount: 50,
itemBuilder: (context, index) {
return ListTile(
title: Text('Item $index'),
);
},
),
),
],
);
},
),
),
);
}
}
代码解释
-
NestedScrollView:headerSliverBuilder: 构建头部Sliver组件的回调。在这个例子中,我们返回了一个SliverAppBar。body: 内部滚动视图,通常是一个不可滚动的组件,如Column,其中可以包含固定高度的组件和一个可扩展的滚动视图(如ListView)。
-
SliverAppBar:pinned: 当true时,AppBar会在滚动时保持固定在顶部。expandedHeight: 展开时的高度。flexibleSpace: 允许在AppBar下方放置一个可伸缩的空间,如图片。
-
Column:- 包含了一个固定高度的
Container(作为固定头部)和一个Expanded的ListView,后者占据了剩余的空间并允许垂直滚动。
- 包含了一个固定高度的
这个示例展示了如何在Flutter中使用NestedScrollView来实现一个具有可折叠工具栏和嵌套滚动视图的复杂布局。根据具体需求,您可以进一步定制和扩展这个基础示例。

