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
来实现一个具有可折叠工具栏和嵌套滚动视图的复杂布局。根据具体需求,您可以进一步定制和扩展这个基础示例。