赞
踩
35.监听滚动事件
- class ScrollControllerTestRoute extends StatefulWidget {
- @override
- ScrollControllerTestRouteState createState() {
- return new ScrollControllerTestRouteState();
- }
- }
-
- class ScrollControllerTestRouteState extends State<ScrollControllerTestRoute> {
- ScrollController _controller = new ScrollController();
- bool showToTopBtn = false; //是否显示“返回到顶部”按钮
-
- @override
- void initState() {
- super.initState();
- //监听滚动事件,打印滚动位置
- _controller.addListener(() {
- print(_controller.offset); //打印滚动位置
- //当偏移量小于1000像素,不显示按钮
- //这里后面之所以&&showToTopBtn,是因为可以通过判断它是true或false省得不断地调用setState,影响性能
- if (_controller.offset < 1000 && showToTopBtn) {
- setState(() {
- showToTopBtn = false;
- });
- //当偏移量大于等于1000像素,显示按钮
- //&&showToTopBtn的理由同上
- } else if (_controller.offset >= 1000 && showToTopBtn == false) {
- setState(() {
- showToTopBtn = true;
- });
- }
- });
- }
-
- @override
- void dispose() {
- //为了避免内存泄露,需要调用_controller.dispose
- _controller.dispose();
- super.dispose();
- }
-
- @override
- Widget build(BuildContext context) {
- return Scaffold(
- appBar: AppBar(title: Text("滚动控制")),
- body: Scrollbar(//滚动条
- child: ListView.builder(
- itemCount: 100,//滚动的总条数
- itemExtent: 50.0, //列表项高度固定时,显式指定高度是一个好习惯(性能消耗小)
- controller: _controller,//添加已加入监听功能的控制器
- itemBuilder: (context, index) {
- return ListTile(title: Text("$index"),);//显示文本
- }
- ),
- ),
- //通过判断showToTopBtn的值来显示按钮
- floatingActionButton: !showToTopBtn ? null : FloatingActionButton(
- child: Icon(Icons.arrow_upward),
- onPressed: () {
- //执行动画返回到顶部
- _controller.animateTo(.0,
- duration: Duration(milliseconds: 200),
- curve: Curves.ease
- );
- }
- ),
- );
- }
- }
效果:
36.根组件数据共享给子组件
- class InheritedWidgetTestRoute extends StatefulWidget {
- @override
- _InheritedWidgetTestRouteState createState() => new _InheritedWidgetTestRouteState();
- }
-
- class _InheritedWidgetTestRouteState extends State<InheritedWidgetTestRoute> {
- //state的数据
- int count = 0;
-
- @override
- Widget build(BuildContext context) {
- return Center(
- //根组件,用于共享数据给它的子组件
- child: ShareDataWidget( //使用ShareDataWidget
- //构建根组件要用到的参数data
- data: count,
- //根组件的子组件
- child: Column(
- //垂直水平方向居中
- mainAxisAlignment: MainAxisAlignment.center,
- children: <Widget>[
- Padding(
- padding: const EdgeInsets.only(bottom: 20.0),
- //根组件的子组件的子组件...
- child: _TestWidget(),//子widget中依赖ShareDataWidget
- ),
- RaisedButton(
- child: Text("Increment"),
- //每点击一次,将count自增,然后重新build,ShareDataWidget的data将被更新
- onPressed: () => setState(() => ++count),
- )
- ],
- ),
- ),
- );
- }
- }
- class _TestWidget extends StatefulWidget {
- @override
- __TestWidgetState createState() => new __TestWidgetState();
- }
-
- class __TestWidgetState extends State<_TestWidget> {
- @override
- Widget build(BuildContext context) {
- //使用ShareDataWidget中的共享数据
- return Text(ShareDataWidget
- .of(context)
- .data
- .toString());
- }
-
- @override
- void didChangeDependencies() {
- super.didChangeDependencies();
- //父或祖先widget中的InheritedWidget改变(updateShouldNotify返回true)时会被调用。
- //如果build中没有依赖InheritedWidget,则此回调不会被调用。
- print("Dependencies change");
- }
- }
- class ShareDataWidget extends InheritedWidget {
- ShareDataWidget({
- //接收_InheritedWidgetTestRouteState组件build时传入的两个参数
- @required this.data,
- Widget child
- }) :super(child: child);
-
- final int data; //需要在子树中共享的数据,保存点击次数
-
- //定义一个便捷方法,方便子树中的widget获取共享数据
- static ShareDataWidget of(BuildContext context) {
- return context.dependOnInheritedWidgetOfExactType<ShareDataWidget>();
- }
-
- //该回调决定当data发生变化时,是否通知子树中依赖data的Widget
- @override
- bool updateShouldNotify(ShareDataWidget old) {
- //如果返回true,则子树中依赖(build函数中有调用)本widget
- //的子widget的`state.didChangeDependencies`会被调用
- return old.data != data;
- }
- }
效果:
37.改变主题
- class ThemeTestRoute extends StatefulWidget {
- @override
- _ThemeTestRouteState createState() => new _ThemeTestRouteState();
- }
-
- class _ThemeTestRouteState extends State<ThemeTestRoute> {
- Color _themeColor = Colors.teal; //当前路由主题色
-
- @override
- Widget build(BuildContext context) {
- ThemeData themeData = Theme.of(context);
- return Theme(
- data: ThemeData(
- primarySwatch: _themeColor, //用于导航栏、FloatingActionButton的背景色等
- iconTheme: IconThemeData(color: _themeColor) //用于Icon颜色
- ),
- child: Scaffold(
- appBar: AppBar(title: Text("主题测试")),
- body: Column(
- mainAxisAlignment: MainAxisAlignment.center,
- children: <Widget>[
- //第一行Icon使用主题中的iconTheme
- Row(
- mainAxisAlignment: MainAxisAlignment.center,
- children: <Widget>[
- Icon(Icons.favorite),
- Icon(Icons.airport_shuttle),
- Text(" 颜色跟随主题")
- ]
- ),
- //为第二行Icon自定义颜色(固定为黑色)
- Theme(
- //局部主题覆盖全局主题
- data: themeData.copyWith(
- iconTheme: themeData.iconTheme.copyWith(
- color: Colors.black
- ),
- ),
- child: Row(
- mainAxisAlignment: MainAxisAlignment.center,
- children: <Widget>[
- Icon(Icons.favorite),
- Icon(Icons.airport_shuttle),
- Text(" 颜色固定黑色")
- ]
- ),
- ),
- ],
- ),
- floatingActionButton: FloatingActionButton(
- onPressed: () => //切换主题
- setState(() =>
- _themeColor =
- _themeColor == Colors.teal ? Colors.blue : Colors.teal
- ),
- child: Icon(Icons.palette)
- ),
- ),
- );
- }
- }
效果:
38.异步UI更新
- class MyHomePage extends StatelessWidget {
- @override
- Widget build(BuildContext context) {
- return new Scaffold(
- appBar: new AppBar(
- title: new Text('标题'),
- ),
- body: StreamBuilder<int>(
- stream: counter(), //调用异步耗时任务
- builder: (BuildContext context, AsyncSnapshot<int> snapshot) {//snapshot会包含当前异步任务的状态信息及结果信息
- //通过snapshot.hasError判断异步任务是否有错误
- if (snapshot.hasError)
- //打印错误
- return Text('Error: ${snapshot.error}');
- //onnectionState是一个枚举类,根据当前异步任务状态ConnectionState来返回不同的widget
- switch (snapshot.connectionState) {
- case ConnectionState.none:
- return Text('没有Stream');
- case ConnectionState.waiting:
- return Text('等待数据...');
- case ConnectionState.active:
- return Text('active: ${snapshot.data}');
- case ConnectionState.done:
- return Text('Stream已关闭');
- }
- return null; // unreachable
- },
- ),
- );
- }
- }
- //使用Stream来实现异步每隔一秒生成一个数字,每次返回一个int类型
- Stream<int> counter() {
- return Stream.periodic(Duration(seconds: 1), (i) {
- return i;
- });
- }
效果:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。