前言
主要講解Flutter常用的滾動(dòng)型組件GridView
組件绊茧,希望你們會(huì)喜歡刀荒。
滾動(dòng)型組件的用法十分相似明肮,可參考學(xué)習(xí)
ListView
組件,因?yàn)閮烧叨祭^承自BoxScrollView
>閱讀本文前可閱讀文章:
目錄
1. 屬性介紹
GridView({
Key key,
Axis scrollDirection = Axis.vertical, // 列表的滾動(dòng)方向簸州,可選值:Axis的horizontal鉴竭、vertical
bool reverse = false,
ScrollController controller, // 控制器,與列表滾動(dòng)相關(guān)岸浑,比如監(jiān)聽(tīng)列表的滾動(dòng)事件
ScrollPhysics physics, // 列表滾動(dòng)至邊緣后繼續(xù)拖動(dòng)的物理效果搏存,Android與iOS效果不同:Android = 波紋狀(ClampingScrollPhysics),而iOS = 回彈的彈性效果(BouncingScrollPhysics)矢洲。若想不同的平臺(tái)上呈現(xiàn)各自的效果可使用AlwaysScrollableScrollPhysics璧眠,它會(huì)根據(jù)不同平臺(tái)自動(dòng)選用各自的物理效果。若想禁用在邊緣的拖動(dòng)效果读虏,可使用NeverScrollableScrollPhysics
bool shrinkWrap = false, // 決定列表的長(zhǎng)度是否僅包裹其內(nèi)容的長(zhǎng)度责静。當(dāng)ListView嵌在一個(gè)無(wú)限長(zhǎng)的容器組件中時(shí),shrinkWrap必須為true盖桥,否則Flutter會(huì)給出警告灾螃;
EdgeInsetsGeometry padding, // 列表內(nèi)邊距
double cacheExtent,// 預(yù)渲染區(qū)域長(zhǎng)度,ListView會(huì)在其可視區(qū)域的兩邊留一個(gè)cacheExtent長(zhǎng)度的區(qū)域作為預(yù)渲染區(qū)域(對(duì)于ListView.build或ListView.separated構(gòu)造函數(shù)創(chuàng)建的列表揩徊,不在可視區(qū)域和預(yù)渲染區(qū)域內(nèi)的子元素不會(huì)被創(chuàng)建或會(huì)被銷毀)腰鬼;
List<Widget> children = const <Widget>[], // 容納子元素的組件數(shù)組
@required this.gridDelegate, // 控制排列子元素的一個(gè)委托
})
下面主要講解屬性 gridDelegate
:類型 = SliverGridDelegate
,是一個(gè)抽象類 & 有2個(gè)實(shí)現(xiàn)類:
- 類型1:
SliverGridDelegateWithFixedCrossAxisCount
= 用于固定列數(shù)場(chǎng)景 - 類型2:
SliverGridDelegateWithMaxCrossAxisExtent
= 用于子元素有最大寬度限制場(chǎng)景
下面將詳細(xì)介紹
// 類型1:SliverGridDelegateWithFixedCrossAxisCount
// 應(yīng)用場(chǎng)景:布局中每一行的列數(shù) = 固定
// 常用屬性(構(gòu)造函數(shù))
SliverGridDelegateWithFixedCrossAxisCount({
@required this.crossAxisCount, // 列數(shù)塑荒,即一行有幾個(gè)子元素熄赡;
this.mainAxisSpacing = 0.0, // 主軸方向上的空隙間距;
this.crossAxisSpacing = 0.0, // 次軸方向上的空隙間距齿税;
this.childAspectRatio = 1.0, // 子元素的寬高比例彼硫。
})
// 類型2:SliverGridDelegateWithMaxCrossAxisExtent
// 應(yīng)用場(chǎng)景:子元素有最大寬度限制
// 常用屬性(構(gòu)造函數(shù))
SliverGridDelegateWithMaxCrossAxisExtent({
this.mainAxisSpacing = 0.0, // 主軸方向上的空隙間距;
this.crossAxisSpacing = 0.0, // 次軸方向上的空隙間距偎窘;
this.childAspectRatio = 1.0, // 子元素的寬高比例
@required this.maxCrossAxisExtent, // 子元素的最大寬度可能是多少乌助,然后計(jì)算得到合適的列寬
// 示例:假如手機(jī)屏寬375溜在,crossAxisSpacing值為0陌知,
// maxCrossAxisExtent值 = 125時(shí),網(wǎng)格列數(shù) = 3掖肋。因?yàn)?25 * 3 = 375仆葡,剛好,每一列的寬度就是375/3。
// maxCrossAxisExtent值 = 126時(shí)沿盅,網(wǎng)格列數(shù) = 3把篓。因?yàn)?26 * 3 > 375,顯示不下腰涧,每一列的寬度將是375/3韧掩。
// maxCrossAxisExtent值為124時(shí),網(wǎng)格列數(shù) = 4窖铡。因?yàn)?24 * 3 < 375疗锐,仍有多余,每一列的寬度將是375/4费彼。
})
2. 基礎(chǔ)使用(含示例講解)
2.1 示例1
使用:SliverGridDelegateWithFixedCrossAxisCount
= 用于固定列數(shù)場(chǎng)景
- 示例代碼
import 'package:flutter/material.dart'; // Material UI組件庫(kù)
void main() => runApp(MyApp());
// 無(wú)狀態(tài)控件顯示
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
// 主界面入口返回的組件 = MaterialApp
return MaterialApp(
title: 'Widget_Demo', //標(biāo)題
theme: ThemeData(primarySwatch: Colors.blue), //主題色
home: MyWidget(), // 返回一個(gè)Widget對(duì)象滑臊,用來(lái)定義當(dāng)前應(yīng)用打開(kāi)的時(shí)候,所顯示的界面
);
}
}
class MyWidget extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return new _MyWidgetState();
}
}
class _MyWidgetState extends State<MyWidget> {
ScrollController _controller = new ScrollController(); // 定義控制器
@override
void initState() {
super.initState();
// 設(shè)置監(jiān)聽(tīng)方法
_controller.addListener(() {
print('_controller Listener');
print(_controller.offset); // 打印滾動(dòng)位置
});
}
@override
Widget build(BuildContext context) {
return GridView(
scrollDirection: Axis.vertical, // 排列方向
controller: _controller, // 設(shè)置控制器
padding: EdgeInsets.all(10), // 內(nèi)邊距
physics: new AlwaysScrollableScrollPhysics(), // 設(shè)置到邊緣后的效果
children: getWidgetList(), // 表格數(shù)據(jù)(僅作demo展示箍铲,代碼在下方)
// 設(shè)置控制排列子元素的一個(gè)委托:固定列數(shù)
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3, // 每列3個(gè)
childAspectRatio: 0.5,//寬高比為1:2
mainAxisSpacing: 10, // 主軸雇卷、次軸方向間隔
crossAxisSpacing: 10,
),
);
}
// GridView數(shù)據(jù)(僅作demo展示)
List<String> litems = [
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"10",
"11",
"12",
"13",
"14",
"15"
];
List<Widget> getWidgetList() {
return litems.map((item) => getItemContainer(item)).toList();
}
Widget getItemContainer(String item) {
return Container(
alignment: Alignment.center,
child: Text(
item,
style: TextStyle(color: Colors.white, fontSize: 20),
),
color: Colors.blue,
);
}
}
- 示意圖
2.2 示例2
使用:SliverGridDelegateWithMaxCrossAxisExtent
= 用于子元素有最大寬度限制場(chǎng)景
- 示例代碼
import 'package:flutter/material.dart'; // Material UI組件庫(kù)
void main() => runApp(MyApp());
// 無(wú)狀態(tài)控件顯示
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
// 主界面入口返回的組件 = MaterialApp
return MaterialApp(
title: 'Widget_Demo', //標(biāo)題
theme: ThemeData(primarySwatch: Colors.blue), //主題色
home: MyWidget(), // 返回一個(gè)Widget對(duì)象,用來(lái)定義當(dāng)前應(yīng)用打開(kāi)的時(shí)候颠猴,所顯示的界面
);
}
}
class MyWidget extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return new _MyWidgetState();
}
}
class _MyWidgetState extends State<MyWidget> {
ScrollController _controller = new ScrollController(); // 定義控制器
@override
void initState() {
super.initState();
// 設(shè)置監(jiān)聽(tīng)方法
_controller.addListener(() {
print('_controller Listener');
print(_controller.offset); // 打印滾動(dòng)位置
});
}
@override
Widget build(BuildContext context) {
return GridView(
scrollDirection: Axis.vertical, // 排列方向
controller: _controller, // 設(shè)置控制器
padding: EdgeInsets.all(10), // 內(nèi)邊距
physics: new AlwaysScrollableScrollPhysics(), // 設(shè)置到邊緣后的效果
children: getWidgetList(), // 表格數(shù)據(jù)(僅作demo展示关划,代碼在下方)
// 設(shè)置控制排列子元素的一個(gè)委托:限制子元素的最大寬度
gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
maxCrossAxisExtent: 200, //子控件最大寬度為200
childAspectRatio: 0.5,//寬高比為1:2
mainAxisSpacing: 10, // 主軸、次軸方向間隔
crossAxisSpacing: 10,
),
);
}
// GridView數(shù)據(jù)(僅作demo展示)
List<String> litems = [
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"10",
"11",
"12",
"13",
"14",
"15"
];
List<Widget> getWidgetList() {
return litems.map((item) => getItemContainer(item)).toList();
}
Widget getItemContainer(String item) {
return Container(
alignment: Alignment.center,
child: Text(
item,
style: TextStyle(color: Colors.white, fontSize: 20),
),
color: Colors.blue,
);
}
}
- 示意圖
3. 進(jìn)階使用
GridView
組件除了上面說(shuō)的基礎(chǔ)使用方式(默認(rèn)構(gòu)造函數(shù))翘瓮,還有一些進(jìn)階使用:
GridView.builder
GridView.count
GridView.extent
GridView.custom
下面祭玉,我將詳細(xì)介紹其使用。
類型1:GridView.builder
a. 特點(diǎn)
根據(jù)子元素是否出現(xiàn)在屏幕內(nèi)而動(dòng)態(tài)創(chuàng)建銷毀春畔,減少內(nèi)存消耗脱货,更高效渲染
b. 應(yīng)用場(chǎng)景
長(zhǎng)列表、數(shù)據(jù)量不確定(如網(wǎng)絡(luò)請(qǐng)求)
c. 屬性(構(gòu)造函數(shù))
GridView.builder({
Key key,
Axis scrollDirection = Axis.vertical, // 列表的滾動(dòng)方向律姨,可選值:Axis的horizontal振峻、vertical
ScrollController controller, // 控制器,與列表滾動(dòng)相關(guān)择份,比如監(jiān)聽(tīng)列表的滾動(dòng)事件
ScrollPhysics physics, // 列表滾動(dòng)至邊緣后繼續(xù)拖動(dòng)的物理效果扣孟,Android與iOS效果不同:Android = 波紋狀(ClampingScrollPhysics),而iOS = 回彈的彈性效果(BouncingScrollPhysics)荣赶。若想不同的平臺(tái)上呈現(xiàn)各自的效果可使用AlwaysScrollableScrollPhysics凤价,它會(huì)根據(jù)不同平臺(tái)自動(dòng)選用各自的物理效果。若想禁用在邊緣的拖動(dòng)效果拔创,可使用NeverScrollableScrollPhysics
bool shrinkWrap = false, // 決定列表的長(zhǎng)度是否僅包裹其內(nèi)容的長(zhǎng)度利诺。當(dāng)ListView嵌在一個(gè)無(wú)限長(zhǎng)的容器組件中時(shí),shrinkWrap必須為true剩燥,否則Flutter會(huì)給出警告慢逾;
EdgeInsetsGeometry padding, // 列表內(nèi)邊距
double cacheExtent,// 預(yù)渲染區(qū)域長(zhǎng)度,ListView會(huì)在其可視區(qū)域的兩邊留一個(gè)cacheExtent長(zhǎng)度的區(qū)域作為預(yù)渲染區(qū)域(對(duì)于ListView.build或ListView.separated構(gòu)造函數(shù)創(chuàng)建的列表,不在可視區(qū)域和預(yù)渲染區(qū)域內(nèi)的子元素不會(huì)被創(chuàng)建或會(huì)被銷毀)侣滩;
List<Widget> children = const <Widget>[], // 容納子元素的組件數(shù)組
@required this.gridDelegate, // 控制排列子元素的一個(gè)委托
// 上面屬性同默認(rèn)構(gòu)造函數(shù)口注,主要關(guān)注下面兩個(gè)特別的屬性
@required IndexedWidgetBuilder itemBuilder,// 列表項(xiàng)構(gòu)造器,返回一個(gè)Widget
int itemCount, // 列表的數(shù)量君珠,一般都是集合的長(zhǎng)度
})
d. 示例代碼
import 'package:flutter/material.dart'; // Material UI組件庫(kù)
void main() => runApp(MyApp());
// 無(wú)狀態(tài)控件顯示
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
// 主界面入口返回的組件 = MaterialApp
return MaterialApp(
title: 'Widget_Demo', //標(biāo)題
theme: ThemeData(primarySwatch: Colors.blue), //主題色
home: MyWidget(), // 返回一個(gè)Widget對(duì)象寝志,用來(lái)定義當(dāng)前應(yīng)用打開(kāi)的時(shí)候,所顯示的界面
);
}
}
class MyWidget extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return new _MyWidgetState();
}
}
class _MyWidgetState extends State<MyWidget> {
ScrollController _controller = new ScrollController(); // 定義控制器
// GridView數(shù)據(jù)(僅作demo展示)
List<String> litems = [
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"10",
"11",
"12",
"13",
"14",
"15"
];
@override
void initState() {
super.initState();
// 設(shè)置監(jiān)聽(tīng)方法
_controller.addListener(() {
print('_controller Listener');
print(_controller.offset); // 打印滾動(dòng)位置
});
}
@override
Widget build(BuildContext context) {
return GridView.builder(
scrollDirection: Axis.vertical, // 排列方向
controller: _controller, // 設(shè)置控制器
padding: EdgeInsets.all(10), // 內(nèi)邊距
physics: new AlwaysScrollableScrollPhysics(), // 設(shè)置到邊緣后的效果
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( // 設(shè)置控制排列子元素的一個(gè)委托:固定列數(shù)
crossAxisCount: 3, // 每列3個(gè)
childAspectRatio: 0.5,//寬高比為1:2
mainAxisSpacing: 10, // 主軸策添、次軸方向間隔
crossAxisSpacing: 10,
),
// 設(shè)置元素?cái)?shù)量 & 具體元素(僅作demo展示澈段,代碼在下方)
itemCount: litems.length,
itemBuilder: (BuildContext ctxt, int index) {
// 當(dāng)數(shù)據(jù)加載完畢時(shí) 追加數(shù)據(jù)
if (index == litems.length - 1 && litems.length < 200) {
_addIndex();
}
return Container(
alignment: Alignment.center,
child: Text(
litems[index],
style: TextStyle(color: Colors.white, fontSize: 20),
),
color: Colors.blue,
);
}
);
}
void _addIndex() {
// 此處需延時(shí)加載 否則會(huì)抱The widget on which setState() or markNeedsBuild() was called was:錯(cuò)誤
Future.delayed(Duration(milliseconds: 200)).then((e) {
setState(() {
litems.add("add");
});
});
}
}
e. 示意圖
類型2:GridView.count
a. 特點(diǎn)
封裝了SliverGridDelegateWithFixedCrossAxisCount
b. 應(yīng)用場(chǎng)景
布局中每一行的列數(shù) = 固定
c. 屬性(構(gòu)造函數(shù))
GridView.count({
Key key,
Axis scrollDirection = Axis.vertical, // 列表的滾動(dòng)方向,可選值:Axis的horizontal舰攒、vertical
@required this.crossAxisCount, // 列數(shù)败富,即一行有幾個(gè)子元素;
this.mainAxisSpacing = 0.0, // 主軸方向上的空隙間距摩窃;
this.crossAxisSpacing = 0.0, // 次軸方向上的空隙間距兽叮;
this.childAspectRatio = 1.0, // 子元素的寬高比例
}
d. 示例代碼
import 'package:flutter/material.dart'; // Material UI組件庫(kù)
void main() => runApp(MyApp());
// 無(wú)狀態(tài)控件顯示
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
// 主界面入口返回的組件 = MaterialApp
return MaterialApp(
title: 'Widget_Demo', //標(biāo)題
theme: ThemeData(primarySwatch: Colors.blue), //主題色
home: MyWidget(), // 返回一個(gè)Widget對(duì)象,用來(lái)定義當(dāng)前應(yīng)用打開(kāi)的時(shí)候猾愿,所顯示的界面
);
}
}
class MyWidget extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return new _MyWidgetState();
}
}
class _MyWidgetState extends State<MyWidget> {
ScrollController _controller = new ScrollController(); // 定義控制器
@override
void initState() {
super.initState();
// 設(shè)置監(jiān)聽(tīng)方法
_controller.addListener(() {
print('_controller Listener');
print(_controller.offset); // 打印滾動(dòng)位置
});
}
@override
Widget build(BuildContext context) {
return GridView.count(
scrollDirection: Axis.vertical, // 排列方向
controller: _controller, // 設(shè)置控制器
padding: EdgeInsets.all(10), // 內(nèi)邊距
physics: new AlwaysScrollableScrollPhysics(), // 設(shè)置到邊緣后的效果
crossAxisCount: 3, // 每列3個(gè)
childAspectRatio: 0.5,//寬高比為1:2
mainAxisSpacing: 10, // 主軸鹦聪、次軸方向間隔
crossAxisSpacing: 10,
children: getWidgetList(), // 表格數(shù)據(jù)(僅作demo展示,代碼在下方)
);
}
// GridView數(shù)據(jù)(僅作demo展示)
List<String> litems = [
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"10",
"11",
"12",
"13",
"14",
"15"
];
List<Widget> getWidgetList() {
return litems.map((item) => getItemContainer(item)).toList();
}
Widget getItemContainer(String item) {
return Container(
alignment: Alignment.center,
child: Text(
item,
style: TextStyle(color: Colors.white, fontSize: 20),
),
color: Colors.blue,
);
}
}
e. 示意圖
類型3:GridView.extent
a. 特點(diǎn)
封裝了SliverGridDelegateWithMaxCrossAxisExtent
b. 應(yīng)用場(chǎng)景
子元素有最大寬度限制
c. 屬性(構(gòu)造函數(shù))
GridView.extent({
Key key,
Axis scrollDirection = Axis.vertical, // 列表的滾動(dòng)方向蒂秘,可選值:Axis的horizontal泽本、vertical
this.mainAxisSpacing = 0.0, // 主軸方向上的空隙間距;
this.crossAxisSpacing = 0.0, // 次軸方向上的空隙間距姻僧;
this.childAspectRatio = 1.0, // 子元素的寬高比例
@required this.maxCrossAxisExtent, // 子元素的最大寬度可能是多少规丽,然后計(jì)算得到合適的列寬
// 示例:假如手機(jī)屏寬375,crossAxisSpacing值為0撇贺,
// maxCrossAxisExtent值 = 125時(shí)赌莺,網(wǎng)格列數(shù) = 3。因?yàn)?25 * 3 = 375松嘶,剛好艘狭,每一列的寬度就是375/3。
// maxCrossAxisExtent值 = 126時(shí)翠订,網(wǎng)格列數(shù) = 3巢音。因?yàn)?26 * 3 > 375,顯示不下尽超,每一列的寬度將是375/3官撼。
// maxCrossAxisExtent值為124時(shí),網(wǎng)格列數(shù) = 4橙弱。因?yàn)?24 * 3 < 375歧寺,仍有多余燥狰,每一列的寬度將是375/4棘脐。
})
d. 示例代碼
import 'package:flutter/material.dart'; // Material UI組件庫(kù)
void main() => runApp(MyApp());
// 無(wú)狀態(tài)控件顯示
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
// 主界面入口返回的組件 = MaterialApp
return MaterialApp(
title: 'Widget_Demo', //標(biāo)題
theme: ThemeData(primarySwatch: Colors.blue), //主題色
home: MyWidget(), // 返回一個(gè)Widget對(duì)象斜筐,用來(lái)定義當(dāng)前應(yīng)用打開(kāi)的時(shí)候,所顯示的界面
);
}
}
class MyWidget extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return new _MyWidgetState();
}
}
class _MyWidgetState extends State<MyWidget> {
ScrollController _controller = new ScrollController(); // 定義控制器
@override
void initState() {
super.initState();
// 設(shè)置監(jiān)聽(tīng)方法
_controller.addListener(() {
print('_controller Listener');
print(_controller.offset); // 打印滾動(dòng)位置
});
}
@override
Widget build(BuildContext context) {
return GridView.extent(
scrollDirection: Axis.vertical, // 排列方向
controller: _controller, // 設(shè)置控制器
padding: EdgeInsets.all(10), // 內(nèi)邊距
physics: new AlwaysScrollableScrollPhysics(), // 設(shè)置到邊緣后的效果
maxCrossAxisExtent: 200, // 子元素寬度最大是200
childAspectRatio: 0.5,//寬高比為1:2
mainAxisSpacing: 10, // 主軸蛀缝、次軸方向間隔
crossAxisSpacing: 10,
children: getWidgetList(), // 表格數(shù)據(jù)(僅作demo展示顷链,代碼在下方)
);
}
// GridView數(shù)據(jù)(僅作demo展示)
List<String> litems = [
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"10",
"11",
"12",
"13",
"14",
"15"
];
List<Widget> getWidgetList() {
return litems.map((item) => getItemContainer(item)).toList();
}
Widget getItemContainer(String item) {
return Container(
alignment: Alignment.center,
child: Text(
item,
style: TextStyle(color: Colors.white, fontSize: 20),
),
color: Colors.blue,
);
}
}
e. 示意圖
類型4:GridView.custom
a. 特點(diǎn)
可自定義SliverGridDelegate 和 SliverChildBuilderDelegate
b. 應(yīng)用場(chǎng)景
更高程度的自定義監(jiān)聽(tīng) & 實(shí)現(xiàn)效果
c. 屬性(構(gòu)造函數(shù))
GridView.custom({
Key key,
Axis scrollDirection = Axis.vertical, // 列表的滾動(dòng)方向,可選值:Axis的horizontal屈梁、vertical
this.mainAxisSpacing = 0.0, // 主軸方向上的空隙間距嗤练;
this.crossAxisSpacing = 0.0, // 次軸方向上的空隙間距;
this.childAspectRatio = 1.0, // 子元素的寬高比例
@required SliverGridDelegate gridDelegate, // 可傳入自定義的SliverGridDelegate
@required SliverChildDelegate childrenDelegate, // 可傳入自定義的SliverChildDelegate childrenDelegate
})
d. 示例代碼
/**
* 導(dǎo)入庫(kù)
**/
import 'package:flutter/material.dart'; // Material UI組件庫(kù)
void main() => runApp(MyApp());
// 無(wú)狀態(tài)控件顯示
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
// 主界面入口返回的組件 = MaterialApp
return MaterialApp(
title: 'Widget_Demo', //標(biāo)題
theme: ThemeData(primarySwatch: Colors.blue), //主題色
home: MyWidget(), // 返回一個(gè)Widget對(duì)象在讶,用來(lái)定義當(dāng)前應(yīng)用打開(kāi)的時(shí)候煞抬,所顯示的界面
);
}
}
class MyWidget extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return new _MyWidgetState();
}
}
class _MyWidgetState extends State<MyWidget> {
ScrollController _controller = new ScrollController(); // 定義控制器
@override
void initState() {
super.initState();
// 設(shè)置監(jiān)聽(tīng)方法
_controller.addListener(() {
print('_controller Listener');
print(_controller.offset); // 打印滾動(dòng)位置
});
}
@override
Widget build(BuildContext context) {
return GridView.custom(
scrollDirection: Axis.vertical, // 排列方向
controller: _controller, // 設(shè)置控制器
padding: EdgeInsets.all(10), // 內(nèi)邊距
physics: new AlwaysScrollableScrollPhysics(), // 設(shè)置到邊緣后的效果
gridDelegate:SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,// 列表數(shù)量是3
childAspectRatio: 0.5,//寬高比為1:2
mainAxisSpacing: 10, // 主軸、次軸方向間隔
crossAxisSpacing: 10,
),
childrenDelegate: MyGridChildrenDelegate( // 更高程度的自定義
(BuildContext context, int i) {
return Container(
alignment: Alignment.center,
child: Text(
litems[i],
style: TextStyle(color: Colors.white, fontSize: 20),
),
color: Colors.blue,
);
},
childCount: litems.length,
),
// children: getWidgetList(), // 表格數(shù)據(jù)(僅作demo展示构哺,代碼在下方)
);
}
// GridView數(shù)據(jù)(僅作demo展示)
List<String> litems = [
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"10",
"11",
"12",
"13",
"14",
"15"
];
List<Widget> getWidgetList() {
return litems.map((item) => getItemContainer(item)).toList();
}
Widget getItemContainer(String item) {
return Container(
alignment: Alignment.center,
child: Text(
item,
style: TextStyle(color: Colors.white, fontSize: 20),
),
color: Colors.blue,
);
}
}
/**
* 自定義有SliverChildBuilderDelegate
* 可實(shí)現(xiàn)對(duì)列表的監(jiān)聽(tīng)
*/
class MyGridChildrenDelegate extends SliverChildBuilderDelegate {
MyGridChildrenDelegate(
Widget Function(BuildContext, int) builder, {
int childCount,
bool addAutomaticKeepAlive = true,
bool addRepaintBoundaries = true,
}) : super(builder,
childCount: childCount,
addAutomaticKeepAlives: addAutomaticKeepAlive,
addRepaintBoundaries: addRepaintBoundaries);
//監(jiān)聽(tīng)列表
// 在可見(jiàn)的列表中 顯示的第一個(gè)位置和最后一個(gè)位置
@override
void didFinishLayout(int firstIndex, int lastIndex) {
print('firstIndex: $firstIndex, lastIndex: $lastIndex');
}
// 判斷添加進(jìn)來(lái)的實(shí)例與之前的實(shí)例是否相同
// 相同返回true革答;反之false
// 可不重寫,默認(rèn)是true
@override
bool shouldRebuild(SliverChildBuilderDelegate oldDelegate) {
// TODO: implement shouldRebuild
print("oldDelegate$oldDelegate");
return super.shouldRebuild(oldDelegate);
}
}
e. 示意圖
至此曙强,關(guān)于GridView
的使用講解完畢残拐。
4. 總結(jié)
本文全面介紹了Flutter GridView
組件的使用,總結(jié)如下:
接下來(lái)推出的文章碟嘴,我將繼續(xù)講解 Flutter
的相關(guān)知識(shí)溪食,包括使用語(yǔ)法、實(shí)戰(zhàn)等娜扇,感興趣的讀者可以繼續(xù)關(guān)注我的博客哦:Carson_Ho的Android博客
請(qǐng)點(diǎn)贊错沃!因?yàn)槟銈兊馁澩?鼓勵(lì)是我寫作的最大動(dòng)力!
相關(guān)文章閱讀
Android開(kāi)發(fā):最全面雀瓢、最易懂的Android屏幕適配解決方案
Android開(kāi)發(fā):史上最全的Android消息推送解決方案
Android開(kāi)發(fā):最全面维哈、最易懂的Webview詳解
Android開(kāi)發(fā):JSON簡(jiǎn)介及最全面解析方法!
Android四大組件:Service服務(wù)史上最全面解析
Android四大組件:BroadcastReceiver史上最全面解析
歡迎關(guān)注Carson_Ho的簡(jiǎn)書灌砖!
不定期分享關(guān)于安卓開(kāi)發(fā)的干貨,追求短、平回窘、快,但卻不缺深度摊灭。