Flutter学习(八)滚动Widget
2020-04-16 本文已影响0人
yanhooIT
ListView
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text("ListView"),
),
body: HomeView(),
),
);
}
}
class HomeView extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ListViewDemo3();
}
}
class ListViewDemo3 extends StatelessWidget {
const ListViewDemo3({
Key key,
}) : super(key: key);
@override
Widget build(BuildContext context) {
/** ListView.separated
*
* 根据子元素的布局父组件会自适应高度
*/
return ListView.separated(
itemCount: 100,
itemBuilder: (BuildContext ctx, int index) {
return Text(
"Hello World: $index",
style: TextStyle(fontSize: 20),
);
},
// 构建分割Widget
separatorBuilder: (BuildContext ctx, int index) {
// 分隔线
return Divider(
color: Colors.red,
// 设置Divider的高度
height: 30,
// 设置距起始位置的距离
indent: 10,
// 设置距结尾位置的距离
endIndent: 10,
// 设置线高
thickness: 2,
);
},
);
}
}
class ListViewDemo2 extends StatelessWidget {
const ListViewDemo2({
Key key,
}) : super(key: key);
@override
Widget build(BuildContext context) {
/** ListView.builder(这个比较常用)
*
* 适合动态创建子元素
*/
return ListView.builder(
// 要创建多少个子元素
itemCount: 100,
// 设置固定高度
itemExtent: 60,
// 当即将显示到屏幕上时才开始构建
itemBuilder: (BuildContext ctx, int index) {
return Text(
"Hello World: $index",
style: TextStyle(fontSize: 20),
);
},
);
}
}
class ListViewDemo1 extends StatelessWidget {
const ListViewDemo1({
Key key,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return ListView(
// 设置滚动方向
// scrollDirection: Axis.horizontal,
// 显示反转
// reverse: true,
// 设置子组件的固定高度
// 当设置scrollDirection: Axis.horizontal,须指定每一个item的固定宽度
itemExtent: 80,
/** ListView.generate批量创建ListView的子元素
*
* (1)只适合子元素比较少的场景,如果元素比较多就会比较耗费内存
* (2)动态不固定的的子元素不建议用此方法,建议用List.builder替代
*/
children: List.generate(100, (index) {
return ListTile(
// 左边显示的组件
leading: Icon(Icons.people),
// 右边显示的组件
trailing: Icon(Icons.delete),
// 主标题
title: Text("联系人${index + 1}"),
// 子标题
subtitle: Text("联系人电话号码:18866665555"),
);
}),
);
}
}
GridView
import 'package:flutter/material.dart';
import 'dart:math';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text("GridView"),
),
body: HomeView(),
),
);
}
}
class HomeView extends StatelessWidget {
@override
Widget build(BuildContext context) {
return GridViewDemo3();
}
}
class GridViewDemo3 extends StatelessWidget {
const GridViewDemo3({
Key key,
}) : super(key: key);
@override
Widget build(BuildContext context) {
/// 这种方式在开发中比较常用
return GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
// 每一行固定显示几个
crossAxisCount: 3,
// 宽高比,即:这个比率 = 宽度 / 高度,可以根据这个值来确定子元素的高度
childAspectRatio: 2,
// 交叉轴每个子元素之间的间距
crossAxisSpacing: 8,
// 主轴每个子元素之间的间距
mainAxisSpacing: 20
),
itemBuilder: (BuildContext ctx, int index) {
return Container(
color: Color.fromARGB(255, Random().nextInt(256), Random().nextInt(256), Random().nextInt(256)),
);
}
);
}
}
class GridViewDemo2 extends StatelessWidget {
const GridViewDemo2({
Key key,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return GridView(
gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
// 设置固定宽度
maxCrossAxisExtent: 400,
// 宽高比,即:这个比率 = 宽度 / 高度,可以根据这个值来确定子元素的高度
childAspectRatio: 2,
crossAxisSpacing: 8,
mainAxisSpacing: 20,
),
children: List.generate(100, (index) {
return Container(
color: Color.fromARGB(255, Random().nextInt(256), Random().nextInt(256), Random().nextInt(256)),
);
}),
);
}
}
class GridViewDemo1 extends StatelessWidget {
const GridViewDemo1({
Key key,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return GridView(
// 固定子元素个数
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
// 每一行固定显示几个
crossAxisCount: 3,
// 宽高比,即:这个比率 = 宽度 / 高度,可以根据这个值来确定子元素的高度
childAspectRatio: 2,
// 交叉轴每个子元素之间的间距
crossAxisSpacing: 8,
// 主轴每个子元素之间的间距
mainAxisSpacing: 20
),
children: List.generate(100, (index) {
return Container(
color: Color.fromARGB(255, Random().nextInt(256), Random().nextInt(256), Random().nextInt(256)),
);
}),
);
}
}
CustomScrollView
import 'package:flutter/material.dart';
import 'dart:math';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
// appBar: AppBar(
// title: Text("CustomScrollView"),
// ),
body: HomeView(),
),
);
}
}
class HomeView extends StatelessWidget {
@override
Widget build(BuildContext context) {
return CustomScrollView2();
}
}
class CustomScrollView2 extends StatelessWidget {
const CustomScrollView2({
Key key,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return CustomScrollView(
slivers: <Widget>[
// 属于滚动条的导航栏
SliverAppBar(
// 固定导航栏
pinned: true,
// 设置导航栏的扩展区域高度
expandedHeight: 200,
// 设置在扩展区域要显示的内容
flexibleSpace: FlexibleSpaceBar(
title: Container(
color: Colors.black,
child: Text("Hello World", style: TextStyle(color: Colors.white, fontSize: 20),)),
// BoxFit.cover:会按图片的长宽比放大后居中填满显示空间,图片不会变形,超出显示空间部分会被剪裁
background: Image.asset("assets/images/xuebao.png", fit: BoxFit.cover),
),
),
// 类似GridView
SliverGrid(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
crossAxisSpacing: 8,
mainAxisSpacing: 8,
childAspectRatio: 2
),
delegate: SliverChildBuilderDelegate(
(BuildContext ctx, int int) {
return Container(color: Color.fromARGB(255, Random().nextInt(
256), Random().nextInt(256), Random().nextInt(256)));
},
// 显示四个元素
childCount: 4
),
),
// 类似ListView
SliverList(
delegate: SliverChildBuilderDelegate(
(BuildContext ctx, int index) {
return ListTile(
leading: Icon(Icons.people),
title: Text("联系人$index"),
);
},
childCount: 20
),
)
],
);
}
}
class CustomScrollView1 extends StatelessWidget {
const CustomScrollView1({
Key key,
}) : super(key: key);
@override
Widget build(BuildContext context) {
/// 可以统一管理多个滚动视图
/// 在CustomScrollView中,每一个独立的,可滚动的Widget被称之为Sliver
return CustomScrollView(
slivers: <Widget>[
// 设置安全区域,只在安全区域里显示,类似的还有SafeArea
SliverSafeArea(
// 设置内间距
sliver: SliverPadding(
padding: EdgeInsets.all(8),
/// SliverGrid类似于我们之前使用过的GridView
sliver: SliverGrid(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
crossAxisSpacing: 8,
mainAxisSpacing: 8,
childAspectRatio: 1.5
),
// 设置代理,之前的generate、builder方法分别对应SliverChildListDelegate、SliverChildBuilderDelegate
delegate: SliverChildBuilderDelegate(
(BuildContext ctx, int int) {
return Container(color: Color.fromARGB(255, Random().nextInt(
256), Random().nextInt(256), Random().nextInt(256)));
},
// 一共有多少个元素,不设置就是无限个
childCount: 20
),
),
),
)
],
);
}
}
事件监听
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: '监听滚动事件',
theme: ThemeData(
primarySwatch: Colors.blue, splashColor: Colors.transparent),
home: HomeView(),
);
}
}
class HomeView extends StatefulWidget {
@override
_HomeViewState createState() => _HomeViewState();
}
class _HomeViewState extends State<HomeView> {
// 可以指定初始的偏移量,这里直接设置为0,没有初始偏移量
ScrollController _controller = ScrollController(initialScrollOffset: 0);
bool _isShowFloatingBtn = false;
@override
void initState() {
super.initState();
_controller.addListener(() {
print("监听到滚动....: ${_controller.offset}");
setState(() {
_isShowFloatingBtn = _controller.offset >= 300;
});
});
}
@override
Widget build(BuildContext context) {
/**
* 两种方式可以监听:
*
* 1、controller:
* 可以设置默认值offset
* 监听滚动, 也可以监听滚动的位置
*
* 2、NotificationListener
* 开始滚动 和 结束滚动
*/
return Scaffold(
appBar: AppBar(
title: Text("监听滚动事件"),
),
body: NotificationListener(
onNotification: (ScrollNotification notification) {
if (notification is ScrollStartNotification) {
print("开始滚动,可滚动距离:${notification.metrics.maxScrollExtent}");
} else if (notification is ScrollUpdateNotification) {
print(
"正在滚动... 当前滚动的位置: ${notification.metrics.pixels}");
} else if (notification is ScrollEndNotification) {
print("结束滚动");
}
// 返回一个布尔值,代表是否阻止该事件继续向上冒
// 如果为true时,则冒泡终止,事件停止向上传播
// 如果不返回 或者 返回值为false时,则冒泡继续
return true;
},
child: ListView.builder(
controller: _controller,
itemCount: 30,
itemBuilder: (BuildContext ctx, int index) {
return ListTile(
leading: Icon(Icons.people),
title: Text("联系人$index"),
);
}),
),
floatingActionButton: _isShowFloatingBtn
? FloatingActionButton(
child: Icon(Icons.arrow_upward),
onPressed: () {
// 滚动到顶部
// jumpTo没有动画效果
// _controller.jumpTo(0);
// animateTo是带动画效果的
_controller.animateTo(0, duration: Duration(seconds: 1), curve: Curves.easeIn);
},
)
: null,
);
}
@override
void dispose() {
super.dispose();
_controller.dispose();
}
}