目錄
- SingleChildScrollView(可滑動(dòng) View)
- ListView(列表 View)
- GridView(網(wǎng)格 View)
- CustomScrollView(自定義滑動(dòng) View)
- ScrollController(控制器)
SingleChildScrollView(可滑動(dòng) View)
SingleChildScrollView 類似 Android 中的 scrollview 默辨,且同樣的只可包含有一個(gè)子元素
const SingleChildScrollView({
Key key,
this.scrollDirection = Axis.vertical,
this.reverse = false,
this.padding,
bool primary,
this.physics,
this.controller,
this.child,
this.dragStartBehavior = DragStartBehavior.down,
}) : assert(scrollDirection != null),
assert(dragStartBehavior != null),
assert(!(controller != null && primary == true),
'Primary ScrollViews obtain their ScrollController via inheritance from a PrimaryScrollController widget. '
'You cannot both set primary to true and pass an explicit controller.'
),
primary = primary ?? controller == null && identical(scrollDirection, Axis.vertical),
super(key: key);
- key:當(dāng)前元素的唯一標(biāo)識(shí)符(類似于 Android 中的 id)
- scrollDirection:滾動(dòng)方向德频,默認(rèn)是垂直
- reverse:是否按照閱讀方向相反的方向滑動(dòng)。
- padding:填充距離
- primary:是否使用 widget 樹(shù)中默認(rèn)的 PrimaryScrollController 缩幸。當(dāng)滑動(dòng)方向?yàn)榇怪狈较颍╯crollDirection值為Axis.vertical)并且controller沒(méi)有指定時(shí)壹置,primary默認(rèn)為true
-
physics:此屬性接受一個(gè)ScrollPhysics對(duì)象竞思,它決定可滾動(dòng)Widget如何響應(yīng)用戶操作,比如用戶滑動(dòng)完抬起手指后钞护,繼續(xù)執(zhí)行動(dòng)畫(huà)盖喷;或者滑動(dòng)到邊界時(shí),如何顯示难咕。默認(rèn)情況下课梳,F(xiàn)lutter會(huì)根據(jù)具體平臺(tái)分別使用不同的ScrollPhysics對(duì)象,應(yīng)用不同的顯示效果余佃,如當(dāng)滑動(dòng)到邊界時(shí)暮刃,繼續(xù)拖動(dòng)的話,在iOS上會(huì)出現(xiàn)彈性效果爆土,而在Android上會(huì)出現(xiàn)微光效果椭懊。如果你想在所有平臺(tái)下使用同一種效果,可以顯式指定步势,F(xiàn)lutter SDK中包含了兩個(gè)ScrollPhysics的子類可以直接使用:
ClampingScrollPhysics→Android下微光效果 / BouncingScrollPhysics→iOS下彈性效果 - controller:此屬性接受一個(gè)ScrollController對(duì)象氧猬。ScrollController的主要作用是控制滾動(dòng)位置和監(jiān)聽(tīng)滾動(dòng)事件
- child:子元素
import 'package:flutter/material.dart';
/**
* @des Scroll Widget
* @author liyongli 20190506
* */
class SingleChildScrollViewWidget extends StatefulWidget{
@override
State<StatefulWidget> createState() => new _StackState();
}
/**
* @des Scroll Widget State
* @author liyongli 20190506
* */
class _StackState extends State<SingleChildScrollViewWidget>{
String numberStr = "12345678909876543210123456789";
@override
Widget build(BuildContext context) {
return new MaterialApp(
home: new Scaffold(
appBar: new AppBar(
title: new Text("Scroll Widget"),
),
body: Scrollbar(
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Center(
child: Row(
children: numberStr.split("").map((c) => Text(c, textScaleFactor: 2.0,)).toList(),
),
),
),
)
),
);
}
}
import 'package:flutter/material.dart';
/**
* @des Scroll Widget
* @author liyongli 20190506
* */
class SingleChildScrollViewWidget extends StatefulWidget{
@override
State<StatefulWidget> createState() => new _StackState();
}
/**
* @des Scroll Widget State
* @author liyongli 20190506
* */
class _StackState extends State<SingleChildScrollViewWidget>{
String numberStr = "1234567890987654321";
@override
Widget build(BuildContext context) {
return new MaterialApp(
home: new Scaffold(
appBar: new AppBar(
title: new Text("Scroll Widget"),
),
body: Scrollbar(
child: SingleChildScrollView(
child: Center(
child: Column(
children: numberStr.split("").map((c) => Text(c, textScaleFactor: 2.0,)).toList(),
),
),
),
)
),
);
}
}
ListView(列表 View)
ListView 可以構(gòu)建一個(gè)列表視圖
ListView({
Key key,
Axis scrollDirection = Axis.vertical,
bool reverse = false,
ScrollController controller,
bool primary,
ScrollPhysics physics,
bool shrinkWrap = false,
EdgeInsetsGeometry padding,
this.itemExtent,
bool addAutomaticKeepAlives = true,
bool addRepaintBoundaries = true,
bool addSemanticIndexes = true,
double cacheExtent,
List<Widget> children = const <Widget>[],
int semanticChildCount,
DragStartBehavior dragStartBehavior = DragStartBehavior.down,
}) : childrenDelegate = SliverChildListDelegate(
children,
addAutomaticKeepAlives: addAutomaticKeepAlives,
addRepaintBoundaries: addRepaintBoundaries,
addSemanticIndexes: addSemanticIndexes,
),
super(
key: key,
scrollDirection: scrollDirection,
reverse: reverse,
controller: controller,
primary: primary,
physics: physics,
shrinkWrap: shrinkWrap,
padding: padding,
cacheExtent: cacheExtent,
semanticChildCount: semanticChildCount ?? children.length,
dragStartBehavior: dragStartBehavior,
);
- key:當(dāng)前元素的唯一標(biāo)識(shí)符(類似于 Android 中的 id)
- scrollDirection:滾動(dòng)方向,默認(rèn)是垂直
- reverse:是否按照閱讀方向相反的方向滑動(dòng)坏瘩。
- controller:控制器對(duì)象盅抚,主要作用是控制滾動(dòng)位置和監(jiān)聽(tīng)滾動(dòng)事件
- primary:是否使用 widget 樹(shù)中默認(rèn)的 PrimaryScrollController 。當(dāng)滑動(dòng)方向?yàn)榇怪狈较颍╯crollDirection值為Axis.vertical)并且controller沒(méi)有指定時(shí)倔矾,primary默認(rèn)為true
-
physics:此屬性接受一個(gè)ScrollPhysics對(duì)象妄均,它決定可滾動(dòng)Widget如何響應(yīng)用戶操作,比如用戶滑動(dòng)完抬起手指后哪自,繼續(xù)執(zhí)行動(dòng)畫(huà)丛晦;或者滑動(dòng)到邊界時(shí),如何顯示提陶。默認(rèn)情況下,F(xiàn)lutter會(huì)根據(jù)具體平臺(tái)分別使用不同的ScrollPhysics對(duì)象匹层,應(yīng)用不同的顯示效果隙笆,如當(dāng)滑動(dòng)到邊界時(shí),繼續(xù)拖動(dòng)的話升筏,在iOS上會(huì)出現(xiàn)彈性效果撑柔,而在Android上會(huì)出現(xiàn)微光效果。如果你想在所有平臺(tái)下使用同一種效果您访,可以顯式指定铅忿,F(xiàn)lutter SDK中包含了兩個(gè)ScrollPhysics的子類可以直接使用:
ClampingScrollPhysics→Android下微光效果 / BouncingScrollPhysics→iOS下彈性效果 - shrinkWrap:表示是否根據(jù)子 widget 的總長(zhǎng)度設(shè)置 listview 的長(zhǎng)度,默認(rèn)為 false灵汪。
- padding:填充距離
- itemExtent:強(qiáng)制 listview 的 children 的長(zhǎng)度 為 itemExtent 的值檀训。指定 itemExtent 的值比讓子元素決定自身長(zhǎng)度在繪制時(shí)更高效柑潦,特別是在滾動(dòng)位置頻繁變化的狀態(tài)下,因?yàn)樵O(shè)置 itemExtent 可以讓滾動(dòng)系統(tǒng)提前知道列表的長(zhǎng)度峻凫。
- addAutomaticKeepAlives:表示是否將列表項(xiàng)包裹在 AutomaticKeepAlive widget 中渗鬼。(在懶加載時(shí),如果設(shè)置了包裹那么在此列表項(xiàng)滑出屏幕外時(shí)不會(huì)被GC荧琼。如果此列表項(xiàng)需要自己維護(hù) KeepAlive 狀態(tài)譬胎,那么此參數(shù)需為 false)
- addRepaintBoundaries:表示是否將列表項(xiàng)包裹在 RepaintBoundary 中。(當(dāng)選擇將列表項(xiàng)包裹在 RepaintBoundary 時(shí)命锄,在滾動(dòng)過(guò)程中可以避免重繪堰乔,如果此列表項(xiàng)需要自己維護(hù) KeepAlive 狀態(tài),那么此參數(shù)需為 false)
- addSemanticIndexes:表示是否給子元素添加索引脐恩,默認(rèn)為 true
- cacheExtent:設(shè)置預(yù)加載的區(qū)域镐侯,范圍在窗口可見(jiàn)范圍之前與之后。如果設(shè)置為 0.0被盈,表示關(guān)閉預(yù)加載
- children:列表項(xiàng)集合
- semanticChildCount:提供語(yǔ)義信息的孩子的數(shù)量
item 數(shù)量固定的 listview 示例
listview 構(gòu)造方法中的參數(shù) children 表示子列表集析孽,使用這種方式構(gòu)建列表需要我們提前準(zhǔn)備好子 widget 集合。這種方式只適合實(shí)現(xiàn)少量且數(shù)量固定的列表展示需求
import 'package:flutter/material.dart';
/**
* @des Listview Widget
* @author liyongli 20190506
* */
class ListViewWidget extends StatefulWidget{
@override
State<StatefulWidget> createState() {
return new _ListViewWigetState();
}
}
/**
* @des Listview Widget State
* @author liyongli 20190506
* */
class _ListViewWigetState extends State<ListViewWidget>{
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: new AppBar(
title: new Text("Scroll Widget"),
),
body: ListView(
shrinkWrap: true,
padding: const EdgeInsets.all(20.0),
children: <Widget>[
const Text("1111111111111111111111111111111111", style: TextStyle(color: Colors.blue)),
const Text("2222222222222222222222222222222222", style: TextStyle(color: Colors.blue)),
const Text("3333333333333333333333333333333333", style: TextStyle(color: Colors.blue)),
const Text("4444444444444444444444444444444444", style: TextStyle(color: Colors.blue)),
const Text("5555555555555555555555555555555555", style: TextStyle(color: Colors.blue)),
const Text("6666666666666666666666666666666666", style: TextStyle(color: Colors.blue)),
const Text("7777777777777777777777777777777777", style: TextStyle(color: Colors.blue)),
const Text("8888888888888888888888888888888888", style: TextStyle(color: Colors.blue)),
],
),
);
}
}
ListView.builder
當(dāng) listview 的列表項(xiàng)較多或數(shù)量未知時(shí)只怎,就需要使用 ListView.builder 來(lái)構(gòu)建列表了
import 'package:flutter/material.dart';
/**
* @des Listview.builder Widget
* @author liyongli 20190506
* */
class ListViewBuilderWidget extends StatefulWidget{
@override
State<StatefulWidget> createState() {
return new _ListViewBuilderWidget ();
}
}
/**
* @des Listview.builder Widget State
* @author liyongli 20190506
* */
class _ListViewBuilderWidget extends State<ListViewBuilderWidget>{
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: new AppBar(
title: new Text("ListviewBuilder Widget"),
),
body: ListView.builder(
itemCount: 100,
itemExtent: 50.0, //強(qiáng)制高度為50.0
itemBuilder: (BuildContext context, int index) {
return ListTile(title: Text(" $index - "));
}
),
);
}
}
ListView.separated
當(dāng) listview 的 item 間需要分割線時(shí)袜瞬,我們就需要用到 ListView.separated
import 'package:flutter/material.dart';
/**
* @des Listview.builder Widget
* @author liyongli 20190506
* */
class ListViewBuilderWidget extends StatefulWidget{
@override
State<StatefulWidget> createState() {
return new _ListViewBuilderWidget ();
}
}
/**
* @des Listview.builder Widget State
* @author liyongli 20190506
* */
class _ListViewBuilderWidget extends State<ListViewBuilderWidget>{
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: new AppBar(
title: new Text("ListviewBuilder Widget"),
),
body: ListView.separated(
itemCount: 100,
itemBuilder: (BuildContext context, int index) {
return ListTile(title: Text(" $index - ", style: TextStyle(color: Colors.blue),));
},
separatorBuilder: (BuildContext context, int index) {
return Divider(color: Colors.blue, height: 10,);
}
),
);
}
}
ListView 分頁(yè)加載
工程 yaml 文件中要添加 english_words 的依賴
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^0.1.2
english_words: ^3.1.0
import 'package:flutter/material.dart';
import 'package:english_words/english_words.dart';
/**
* @des Listview Widget
* @author liyongli 20190507
* */
class InfiniteListView extends StatefulWidget {
@override
_InfiniteListViewState createState() => new _InfiniteListViewState();
}
/**
* @des Listview Widget State
* @author liyongli 20190507
* */
class _InfiniteListViewState extends State<InfiniteListView> {
static const loadingTag = "##loading##"; //表尾標(biāo)記
var _words = <String>[loadingTag];
@override
void initState() {
_retrieveData();
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text("listview 分頁(yè)加載"),
),
body: ListView.separated(
itemCount: _words.length,
itemBuilder: (context, index) {
//如果到了表尾
if (_words[index] == loadingTag) {
//不足100條,繼續(xù)獲取數(shù)據(jù)
if (_words.length - 1 < 100) {
//獲取數(shù)據(jù)
_retrieveData();
//加載時(shí)顯示loading
return Container(
padding: const EdgeInsets.all(16.0),
alignment: Alignment.center,
child: SizedBox(
width: 24.0,
height: 24.0,
child: CircularProgressIndicator(strokeWidth: 2.0)
),
);
} else {
//已經(jīng)加載了100條數(shù)據(jù)身堡,不再獲取數(shù)據(jù)邓尤。
return Container(
alignment: Alignment.center,
padding: EdgeInsets.all(16.0),
child: Text("沒(méi)有更多了", style: TextStyle(color: Colors.grey),)
);
}
}
//顯示單詞列表項(xiàng)
return ListTile(title: Text(_words[index], style: TextStyle(color: Colors.blue),));
},
separatorBuilder: (context, index) => Divider(height: 1, color: Colors.blue,),
),
),
);
}
void _retrieveData() {
Future.delayed(Duration(seconds: 2)).then((e) {
_words.insertAll(_words.length - 1,
//每次生成20個(gè)單詞
generateWordPairs().take(20).map((e) => e.asPascalCase).toList()
);
setState(() {
//重新構(gòu)建列表
});
});
}
}
GridView(網(wǎng)格 View)
GridView 可以構(gòu)建一個(gè)網(wǎng)格列表視圖
GridView.builder({
Key key,
Axis scrollDirection = Axis.vertical,
bool reverse = false,
ScrollController controller,
bool primary,
ScrollPhysics physics,
bool shrinkWrap = false,
EdgeInsetsGeometry padding,
@required this.gridDelegate,
@required IndexedWidgetBuilder itemBuilder,
int itemCount,
bool addAutomaticKeepAlives = true,
bool addRepaintBoundaries = true,
bool addSemanticIndexes = true,
double cacheExtent,
int semanticChildCount,
}) : assert(gridDelegate != null),
childrenDelegate = SliverChildBuilderDelegate(
itemBuilder,
childCount: itemCount,
addAutomaticKeepAlives: addAutomaticKeepAlives,
addRepaintBoundaries: addRepaintBoundaries,
addSemanticIndexes: addSemanticIndexes,
),
super(
key: key,
scrollDirection: scrollDirection,
reverse: reverse,
controller: controller,
primary: primary,
physics: physics,
shrinkWrap: shrinkWrap,
padding: padding,
cacheExtent: cacheExtent,
semanticChildCount: semanticChildCount ?? itemCount,
);
- key:當(dāng)前元素的唯一標(biāo)識(shí)符(類似于 Android 中的 id)
- scrollDirection:滾動(dòng)方向,默認(rèn)是垂直
- reverse:是否按照閱讀方向相反的方向滑動(dòng)贴谎。
- controller:控制器對(duì)象汞扎,主要作用是控制滾動(dòng)位置和監(jiān)聽(tīng)滾動(dòng)事件
- primary:是否使用 widget 樹(shù)中默認(rèn)的 PrimaryScrollController 。當(dāng)滑動(dòng)方向?yàn)榇怪狈较颍╯crollDirection值為Axis.vertical)并且controller沒(méi)有指定時(shí)擅这,primary默認(rèn)為true
-
physics:此屬性接受一個(gè)ScrollPhysics對(duì)象澈魄,它決定可滾動(dòng)Widget如何響應(yīng)用戶操作,比如用戶滑動(dòng)完抬起手指后仲翎,繼續(xù)執(zhí)行動(dòng)畫(huà)痹扇;或者滑動(dòng)到邊界時(shí),如何顯示溯香。默認(rèn)情況下鲫构,F(xiàn)lutter會(huì)根據(jù)具體平臺(tái)分別使用不同的ScrollPhysics對(duì)象,應(yīng)用不同的顯示效果玫坛,如當(dāng)滑動(dòng)到邊界時(shí)结笨,繼續(xù)拖動(dòng)的話,在iOS上會(huì)出現(xiàn)彈性效果,而在Android上會(huì)出現(xiàn)微光效果炕吸。如果你想在所有平臺(tái)下使用同一種效果伐憾,可以顯式指定,F(xiàn)lutter SDK中包含了兩個(gè)ScrollPhysics的子類可以直接使用:
ClampingScrollPhysics→Android下微光效果 / BouncingScrollPhysics→iOS下彈性效果 - shrinkWrap:表示是否根據(jù)子 widget 的總長(zhǎng)度設(shè)置 listview 的長(zhǎng)度算途,默認(rèn)為 false塞耕。
- padding:填充距離
- itemCount:子元素?cái)?shù)量
- addAutomaticKeepAlives:表示是否將列表項(xiàng)包裹在 AutomaticKeepAlive widget 中。(在懶加載時(shí)嘴瓤,如果設(shè)置了包裹那么在此列表項(xiàng)滑出屏幕外時(shí)不會(huì)被GC扫外。如果此列表項(xiàng)需要自己維護(hù) KeepAlive 狀態(tài),那么此參數(shù)需為 false)
- addRepaintBoundaries:表示是否將列表項(xiàng)包裹在 RepaintBoundary 中廓脆。(當(dāng)選擇將列表項(xiàng)包裹在 RepaintBoundary 時(shí)筛谚,在滾動(dòng)過(guò)程中可以避免重繪,如果此列表項(xiàng)需要自己維護(hù) KeepAlive 狀態(tài)停忿,那么此參數(shù)需為 false)
- addSemanticIndexes:表示是否給子元素添加索引驾讲,默認(rèn)為 true
- cacheExtent:設(shè)置預(yù)加載的區(qū)域,范圍在窗口可見(jiàn)范圍之前與之后席赂。如果設(shè)置為 0.0吮铭,表示關(guān)閉預(yù)加載
- semanticChildCount:提供語(yǔ)義信息的孩子的數(shù)量
GridView 固定列數(shù)
import 'package:flutter/material.dart';
/**
* @des GridView 固定列數(shù)
* @author liyongli 20190508
* */
class GridViewTest extends StatefulWidget{
@override
State<StatefulWidget> createState() => new _GridViewState();
}
/**
* @des GridView Widget State
* @author liyongli 20190508
* */
class _GridViewState extends State<GridViewTest>{
@override
Widget build(BuildContext context) {
return new MaterialApp(
home: new Scaffold(
appBar: new AppBar(
title: new Text("GridView 固定列數(shù)"),
),
body: GridView.count(
crossAxisCount: 4,
childAspectRatio: 0.7,
children: <Widget>[
Icon(Icons.add_a_photo),
Icon(Icons.add_a_photo),
Icon(Icons.add_a_photo),
Icon(Icons.add_a_photo),
Icon(Icons.add_a_photo),
Icon(Icons.add_a_photo),
Icon(Icons.add_a_photo),
Icon(Icons.add_a_photo),
Icon(Icons.add_a_photo),
Icon(Icons.add_a_photo),
Icon(Icons.add_a_photo),
Icon(Icons.add_a_photo),
],
),
),
);
}
}
import 'package:flutter/material.dart';
/**
* @des GridView 等分寬度
* @author liyongli 20190508
* */
class GridViewTest extends StatefulWidget{
@override
State<StatefulWidget> createState() => new _GridViewState();
}
/**
* @des GridView Widget State
* @author liyongli 20190508
* */
class _GridViewState extends State<GridViewTest>{
@override
Widget build(BuildContext context) {
return new MaterialApp(
home: new Scaffold(
appBar: new AppBar(
title: new Text("GridView 等分寬度"),
),
body: GridView.extent(
maxCrossAxisExtent: 200,
childAspectRatio: 1.0,
children: <Widget>[
Icon(Icons.add_a_photo),
Icon(Icons.add_a_photo),
Icon(Icons.add_a_photo),
Icon(Icons.add_a_photo),
Icon(Icons.add_a_photo),
],
),
),
);
}
}
GridView 分頁(yè)加載
import 'package:flutter/material.dart';
/**
* @des GridView 分頁(yè)加載
* @author liyongli 20190508
* */
class GridViewTest extends StatefulWidget{
@override
State<StatefulWidget> createState() => new _GridViewState();
}
/**
* @des GridView Widget State
* @author liyongli 20190508
* */
class _GridViewState extends State<GridViewTest>{
List<IconData> _iconList = [];
@override
void initState() {
_getData();
}
@override
Widget build(BuildContext context) {
return new MaterialApp(
home: new Scaffold(
appBar: new AppBar(
title: new Text("GridView 分頁(yè)加載"),
),
body: GridView.builder(
itemCount: _iconList.length,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 5, childAspectRatio: 1.0),
itemBuilder: (context, index){
if(index == _iconList.length - 1 && _iconList.length < 200){
_getData();
}
return Icon(_iconList[index]);
}
)
),
);
}
// 請(qǐng)求數(shù)據(jù)
void _getData(){
Future.delayed(Duration(milliseconds: 200)).then((e) {
setState(() {
_iconList.addAll([
Icons.add_a_photo,
Icons.add_a_photo,
Icons.add_a_photo,
Icons.add_a_photo, Icons.cake,
Icons.add_a_photo
]);
});
});
}
}
CustomScrollView(自定義滑動(dòng) View)
Sliver
Sliver 是分片、分區(qū)的意思颅停。當(dāng)我們需要將不同的可滑動(dòng)組件組合在一起時(shí)谓晌,就需要使用此對(duì)象來(lái)完成。ListView 和 GridView 都有對(duì)應(yīng)的組合對(duì)象如:SliverList 和 SliverGrid癞揉。
import 'package:flutter/material.dart';
/**
* @des CustomScrollView Widget
* @author liyongli 20190509
* */
class CustomScrollViewTest extends StatelessWidget{
@override
Widget build(BuildContext context) {
return Material(
child: CustomScrollView(
slivers: <Widget>[
// 跟隨頁(yè)面滑動(dòng)的導(dǎo)航欄
SliverAppBar(
pinned: true, // 是否固定
expandedHeight: 200.0, // 高度
flexibleSpace: FlexibleSpaceBar(
title: Text("title"),
background: Image.asset("images/custom_scroll_title.png", fit: BoxFit.cover,)
),
),
// Grid
SliverPadding(
padding: EdgeInsets.all(10.0),
sliver: SliverGrid(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3, // 4行
mainAxisSpacing: 20.0,
crossAxisSpacing: 10.0,
childAspectRatio: 5.0,
),
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index){
return Container(
alignment: Alignment.center,
color: Colors.blue,
child: Text("grid Item $index", style: TextStyle(color: Colors.white),),
);
},
childCount: 12
),
),
),
// List
SliverFixedExtentList(
itemExtent: 20,
delegate: SliverChildBuilderDelegate((BuildContext context , int index){
return Container(
alignment: Alignment.center,
color: Colors.blue,
child: Text("list Item $index", style: TextStyle(color: Colors.white),),
);
},
childCount: 30
),
),
],
),
);
}
}
ScrollController(控制器)
可設(shè)置滑動(dòng) View 的滾動(dòng)位置纸肉,還可監(jiān)聽(tīng)并獲取滑動(dòng) View 的滾動(dòng)狀態(tài)及數(shù)據(jù)
ScrollController({
double initialScrollOffset = 0.0,
this.keepScrollOffset = true,
this.debugLabel,
}) : assert(initialScrollOffset != null),
assert(keepScrollOffset != null),
_initialScrollOffset = initialScrollOffset;
- initialScrollOffset:初始位置
- keepScrollOffset:是否保存滾動(dòng)位置
- ScrollController.jumpTo(0.0):直接滾動(dòng)至指定位置
- ScrollController.animateTo(0.0, duration: Duration(milliseconds: 500), curve: Curves.decelerate):帶動(dòng)畫(huà)滾動(dòng)至指定位置
import 'package:flutter/material.dart';
/**
* des ScrollController Test
* @author liyongli 20190513
* */
class ScrollControllerTest extends StatefulWidget{
@override
State<StatefulWidget> createState() {
return new _ScrollControllerTestState();
}
}
/**
* des ScrollController Test State
* @author liyongli 20190513
* */
class _ScrollControllerTestState extends State<ScrollControllerTest>{
ScrollController _controller = new ScrollController();
double oldOffset = -1;
@override
void initState() {
super.initState();
_controller.addListener((){
print("$_controller.offset" + " / " + "$oldOffset");
if(oldOffset > _controller.offset){
print("向下滑");
}else{
print("向上滑");
}
oldOffset = _controller.offset;
});
}
@override
void dispose() {
super.dispose();
_controller.dispose(); // 釋放資源
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text("ScrollController"),
),
body: Scrollbar(
child: ListView.builder(
controller: _controller, // 控制器
itemCount: 50, // item count
itemExtent: 100.0, // item height
itemBuilder: (context, index){
return ListTile(title:Text("$index", style: TextStyle(color: Colors.blue),));
}
)
),
floatingActionButton: FloatingActionButton(
onPressed: _up,
child: Icon(Icons.arrow_upward)
),
),
);
}
// 滾動(dòng)
void _up(){
// 帶動(dòng)畫(huà)滾動(dòng)
_controller.animateTo(0.0, duration: Duration(milliseconds: 500), curve: Curves.decelerate);
// 無(wú)動(dòng)畫(huà)滾動(dòng)
// _controller.jumpTo(0.0);
}
}
本篇到此完結(jié),更多 Flutter 跨平臺(tái)移動(dòng)端開(kāi)發(fā) 原創(chuàng)內(nèi)容持續(xù)更新中~
期待您 關(guān)注 / 點(diǎn)贊 / 收藏 向著 大前端工程師 晉級(jí)喊熟!