赞
踩
CustomScrollView是可以使用Sliver来自定义滚动模型(效果)的组件。它可以包含多种滚动模型。包括header,footer,以及类似Android Coordinglayout布局的滑动效果,CustomScrollView可以实现把多个彼此独立的可滑动widget组合起来
Flutter中提出一个Sliver(中文为“薄片”的意思)概念,如果一个可滚动组件支持Sliver模型,那么该滚动可以将子组件分成好多个“薄片”(Sliver),只有当Sliver出现在视口中时才会去构建它,这种模型也称为“基于Sliver的延迟构建模型”。可滚动组件中有很多都支持基于Sliver的延迟构建模型,如ListView、GridView,但是也有不支持该模型的,如SingleChildScrollView。
这个跟安卓的思维是一致的,类似与分页加载,复用加载,数据量比较大的时候对提高加载效率非常有帮助。SingleChildScrollView只包含一个子widget,本身也只适用于子widget数量有限的场景。
1、添加Header和Footer
import 'dart:ui'; import 'package:flutter/material.dart'; class CsWidget extends StatelessWidget { @override Widget build(BuildContext context) { // TODO: implement build return Scaffold( appBar: PreferredSize( preferredSize: Size.fromHeight(MediaQueryData.fromWindow(window).padding.top), child: SafeArea( top: true, child: Offstage(), ), ), body: CustomScrollViewWidget(), ); } } class CustomScrollViewWidget extends StatelessWidget { @override Widget build(BuildContext context) { // TODO: implement build return CustomScrollView( scrollDirection: Axis.vertical, slivers: <Widget>[ SliverAppBar( pinned: false, expandedHeight: 250.0, backgroundColor: Colors.blue, flexibleSpace: FlexibleSpaceBar( background: Image.network("http://b-ssl.duitang.com/uploads/blog/201312/04/20131204184148_hhXUT.jpeg",fit: BoxFit.cover,), ), ), SliverFixedExtentList( delegate: SliverChildBuilderDelegate((BuildContext context, int index) { return Container( color: Colors.red, alignment: Alignment.center, child: Text("$index"), ); }, childCount: 20), itemExtent: 50), SliverAppBar( pinned: false, expandedHeight: 250.0, backgroundColor: Colors.blue, flexibleSpace: FlexibleSpaceBar( background: Image.network("http://b-ssl.duitang.com/uploads/blog/201312/04/20131204184148_hhXUT.jpeg",fit: BoxFit.cover,), ), ), ], ); } }
CustomScrollView里添加的子widget都必须是Sliver,比如添加Image或者Text都会报错
分析一下SliverAppBar
const SliverAppBar({ Key key, this.leading,//左侧的图标或文字,多为返回箭头 this.automaticallyImplyLeading = true,//没有leading为true的时候,默认返回箭头,没有leading且为false,则显示title this.title,//标题 this.actions,//标题右侧的操作 this.flexibleSpace,//可以理解为SliverAppBar的背景内容区 this.bottom,//SliverAppBar的底部区 this.elevation,//阴影 this.forceElevated = false,//是否显示阴影 this.backgroundColor,//背景颜色 this.brightness,//状态栏主题,默认Brightness.dark,可选参数light this.iconTheme,//SliverAppBar图标主题 this.actionsIconTheme,//action图标主题 this.textTheme,//文字主题 this.primary = true,//是否显示在状态栏的下面,false就会占领状态栏的高度 this.centerTitle,//标题是否居中显示 this.titleSpacing = NavigationToolbar.kMiddleSpacing,//标题横向间距 this.expandedHeight,//合并的高度,默认是状态栏的高度加AppBar的高度 this.floating = false,//滑动时是否悬浮 this.pinned = false,//标题栏是否固定 this.snap = false,//配合floating使用 })
其中比较常用的leading,title,actions,backgroundColor,flexibleSpace,pinned,expandedHeight
class CustomScrollViewWidget extends StatelessWidget { @override Widget build(BuildContext context) { // TODO: implement build return CustomScrollView( scrollDirection: Axis.vertical, slivers: <Widget>[ SliverAppBar( leading: IconButton(icon: Icon(Icons.arrow_back), onPressed: () {}), title: Text("标题"), actions: <Widget>[ IconButton(icon: Icon(Icons.share), onPressed: () {}) ], primary: true, pinned: true, centerTitle: true, expandedHeight: 250.0, backgroundColor: Colors.blue, flexibleSpace: FlexibleSpaceBar( background: Image.network( "http://b-ssl.duitang.com/uploads/blog/201312/04/20131204184148_hhXUT.jpeg", fit: BoxFit.cover, ), ), ), SliverFixedExtentList( delegate: SliverChildBuilderDelegate((BuildContext context, int index) { return Container( height: 30, color: index % 2 == 0 ? Colors.red : Colors.purpleAccent, alignment: Alignment.center, child: Text("$index"), ); }, childCount: 20), itemExtent: 50), ], ); } }
SliverAppBar+SliverGrid+SliverFixedExtentList实现滑动列表
class CustomScrollViewWidget extends StatelessWidget { @override Widget build(BuildContext context) { // TODO: implement build return CustomScrollView( scrollDirection: Axis.vertical, slivers: <Widget>[ SliverAppBar( leading: IconButton(icon: Icon(Icons.arrow_back), onPressed: () {}), title: Text("标题"), actions: <Widget>[ IconButton(icon: Icon(Icons.share), onPressed: () {}) ], primary: true, pinned: true, centerTitle: true, expandedHeight: 250.0, backgroundColor: Colors.blue, flexibleSpace: FlexibleSpaceBar( background: Image.network( "http://b-ssl.duitang.com/uploads/blog/201312/04/20131204184148_hhXUT.jpeg", fit: BoxFit.cover, ), ), ), SliverPadding( padding: EdgeInsets.all(20), sliver: SliverGrid( delegate: SliverChildBuilderDelegate((BuildContext context, int index) { return Container( color: index % 2 == 0 ? Colors.greenAccent : Colors.yellow, alignment: Alignment.center, child: Text("$index"), ); }, childCount: 8), gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 3, crossAxisSpacing: 20, mainAxisSpacing: 20, childAspectRatio: 1)), ), SliverFixedExtentList( delegate: SliverChildBuilderDelegate((BuildContext context, int index) { return Container( height: 30, color: index % 2 == 0 ? Colors.red : Colors.purpleAccent, alignment: Alignment.center, child: Text("$index"), ); }, childCount: 20), itemExtent: 50), ], ); } }
这样就能实现多维列表+单列表的组合布局。但是距离android的多type布局还有一定距离,因为CustomScrollView子widget必须是Sliver,但是换个思路,gradview和listview的子widget没有这个限制,是否以此作为多type实现的方式呢?
我实验了一下是可以的,由此可以断言,CustomScrollView可以完全实现Android多type布局的效果
class CustomScrollViewWidget extends StatelessWidget { @override Widget build(BuildContext context) { // TODO: implement build return CustomScrollView( scrollDirection: Axis.vertical, slivers: <Widget>[ SliverAppBar( leading: IconButton(icon: Icon(Icons.arrow_back), onPressed: () {}), title: Text("标题"), actions: <Widget>[ IconButton(icon: Icon(Icons.share), onPressed: () {}) ], primary: true, pinned: true, centerTitle: true, expandedHeight: 250.0, backgroundColor: Colors.blue, flexibleSpace: FlexibleSpaceBar( background: Image.network( "http://b-ssl.duitang.com/uploads/blog/201312/04/20131204184148_hhXUT.jpeg", fit: BoxFit.cover, ), ), ), SliverFixedExtentList( delegate: SliverChildBuilderDelegate((BuildContext context, int index) { return Container( color: Colors.deepPurpleAccent, alignment: Alignment.center, child: Text("这只是中间type"), ); }, childCount: 1), itemExtent: 60), SliverPadding( padding: EdgeInsets.all(20), sliver: SliverGrid( delegate: SliverChildBuilderDelegate((BuildContext context, int index) { return Container( color: index % 2 == 0 ? Colors.greenAccent : Colors.yellow, alignment: Alignment.center, child: Text("$index"), ); }, childCount: 8), gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 3, crossAxisSpacing: 20, mainAxisSpacing: 20, childAspectRatio: 1)), ), SliverFixedExtentList( delegate: SliverChildBuilderDelegate((BuildContext context, int index) { return Container( height: 30, color: index % 2 == 0 ? Colors.red : Colors.purpleAccent, alignment: Alignment.center, child: Text("$index"), ); }, childCount: 20), itemExtent: 50), SliverFixedExtentList( delegate: SliverChildBuilderDelegate((BuildContext context, int index) { return Container( color: Colors.deepPurpleAccent, alignment: Alignment.center, child: Text("这只是一个footer"), ); }, childCount: 1), itemExtent: 60), SliverFixedExtentList( delegate: SliverChildBuilderDelegate((BuildContext context, int index) { return Container( child: Image.network( "http://b-ssl.duitang.com/uploads/item/201208/08/20120808125749_UxUu8.jpeg", height: 60, fit: BoxFit.fitWidth, ), ); }, childCount: 1), itemExtent: 60), ], ); } }
今天的学习就到此为止
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。