Flutter第六期 - ListView+GridView混合

列表是APP的核心功能,目前這個庫不算完善,以後國外的大神應該會補全,現在的樣式就是很基礎的東西,解決一些常用的加載,至於後面的自定義tag需要一個過程,混合佈局可以參考flutter_staggered_grid_view,下面是基礎的寫法:

import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
//Stateless widgets 是不可變的, 這意味著它們的屬性不能改變 - 所有的值都是最終的.
//Stateful widgets 持有的狀態可能在widget生命週期中發生變化. 實現一個 stateful widget 至少需要兩個類:
class MyApp extends StatelessWidget {
 @override
 Widget build(BuildContext context) {
// final wordPair = new WordPair.random();
 return new MaterialApp(
 title: 'ListView3+GridView33',
 debugShowCheckedModeBanner: false,
 theme: new ThemeData(
 primarySwatch: Colors.blue,
// fontFamily: 'fontdemo1'
 ),
 home: new Scaffold(
 appBar: new AppBar(
 title: new Text('圖片加載'),
 ),
 body: new Center(
// child: new ListView(
// shrinkWrap: true,
// padding: const EdgeInsets.all(20.0),
// children: [
// const Text('I\'m dedicating every day to you'),
// const Text('Domestic life was never quite my style'),
// const Text('When you smile, you knock me out, I fall apart'),
// const Text('And I thought I was so smart'),
// ],
// ),
// child: new ListView3(),
// child: new GridView3(),
// child: new GridView33(),
 child: new InfiniteGridView(),
 ),
 ),
 );
 }
}
class ListView3 extends StatelessWidget {
 @override
 Widget build(BuildContext context) {
 //下劃線widget預定義以供複用。
 Widget divider1 = Divider(
 color: Colors.blue,
 );
 Widget divider2 = Divider(color: Colors.green);
 return ListView.separated(
 itemCount: 100,
 //列表項構造器
 itemBuilder: (BuildContext context, int index) {
 return ListTile(title: Text("$index"));
 },
 //分割器構造器
 separatorBuilder: (BuildContext context, int index) {
 return index % 2 == 0 ? divider1 : divider2;
 },
 );
 }
}
class GridView3 extends StatelessWidget {
 @override
 Widget build(BuildContext context) {
 return GridView(
 gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
 crossAxisCount: 3, //橫軸三個子widget
 childAspectRatio: 1.0, //寬高比為1時,子widget
 ),
 children: [
 Icon(Icons.ac_unit),
 Icon(Icons.airport_shuttle),
 Icon(Icons.all_inclusive),
 Icon(Icons.beach_access),
 Icon(Icons.cake),
 Icon(Icons.free_breakfast)
 ]);
 }
}
class GridView33 extends StatelessWidget {
 @override
 Widget build(BuildContext context) {
 return GridView(
 padding: EdgeInsets.zero,
 gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
 maxCrossAxisExtent: 120.0, childAspectRatio: 2.0, //寬高比為2
 ),
 children: [
 Icon(Icons.ac_unit),
 Icon(Icons.airport_shuttle),
 Icon(Icons.all_inclusive),
 Icon(Icons.beach_access),
 Icon(Icons.cake),
 Icon(Icons.free_breakfast),
 ],
 );
 }
}
class InfiniteGridView extends StatefulWidget {
 @override
 _InfiniteGridViewState createState() => new _InfiniteGridViewState();
}
class _InfiniteGridViewState extends State {
 List _icons = []; //保存Icon數據
 @override
 void initState() {
 // 初始化數據
 _retrieveIcons();
 }
 @override
 Widget build(BuildContext context) {
 return GridView.builder(
 gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
 crossAxisCount: 3, //每行三列
 childAspectRatio: 1.0 //顯示區域寬高相等
 ),
 itemCount: _icons.length,
 itemBuilder: (context, index) {
 //如果顯示到最後一個並且Icon總數小於200時繼續獲取數據
 if (index == _icons.length - 1 && _icons.length < 200) {
 _retrieveIcons();
 }
 return Icon(_icons[index]);
 }
 );
 }
 //模擬異步獲取數據
 void _retrieveIcons() {
 Future.delayed(Duration(milliseconds: 200)).then((e) {
 setState(() {
 _icons.addAll([
 Icons.ac_unit,
 Icons.airport_shuttle,
 Icons.all_inclusive,
 Icons.beach_access, Icons.cake,
 Icons.free_breakfast
 ]);
 });
 });
 }
}
Flutter第六期 - ListView+GridView混合

Flutter第六期 - ListView+GridView混合

ListView+GridView圖文混合:

import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
//Stateless widgets 是不可變的, 這意味著它們的屬性不能改變 - 所有的值都是最終的.
//Stateful widgets 持有的狀態可能在widget生命週期中發生變化. 實現一個 stateful widget 至少需要兩個類:
class MyApp extends StatelessWidget {
 @override
 Widget build(BuildContext context) {
// final wordPair = new WordPair.random();
 return new MaterialApp(
 title: 'ListView+GridView綜合佈局',
 debugShowCheckedModeBanner: false,
 theme: new ThemeData(
 primarySwatch: Colors.blue,
// fontFamily: 'fontdemo1'
 ),
 home: new Scaffold(
// appBar: new AppBar(
//// title: new Text('圖片加載'),
//// ),
 body: new Center(
// child: new ListView(
// shrinkWrap: true,
// padding: const EdgeInsets.all(20.0),
// children: [
// const Text('I\'m dedicating every day to you'),
// const Text('Domestic life was never quite my style'),
// const Text('When you smile, you knock me out, I fall apart'),
// const Text('And I thought I was so smart'),
// ],
// ),
// child: new ListView3(),
// child: new GridView3(),
// child: new GridView33(),
 child: new CustomScrollViewTestRoute(),
 ),
 ),
 );
 }
}
class CustomScrollViewTestRoute extends StatelessWidget {
 @override
 Widget build(BuildContext context) {
 //因為本路由沒有使用Scaffold,為了讓子級Widget(如Text)使用
 //Material Design 默認的樣式風格,我們使用Material作為本路由的根。
 return Material(
 child: CustomScrollView(
 slivers: [
 //AppBar,包含一個導航欄
 SliverAppBar(
 //標題居中
 centerTitle: true,
 leading: Builder(builder: (context) {
 return IconButton(
 icon: Icon(Icons.arrow_back, color: Colors.white), //自定義圖標
 onPressed: () {
 //
 },
 );
 }),
// leading: Icon(
// Icons.arrow_back,
// ),
 //展開高度250
 expandedHeight: 250.0,
 //不隨著滑動隱藏標題
 floating: false,
 //固定在頂部
 pinned: true,
 flexibleSpace: FlexibleSpaceBar(
 title: const Text('YUN'),
 background: Image.asset(
 "assets/images/food04.jpeg",
 fit: BoxFit.cover,
 ),
 ),
 ),
 SliverPadding(
 padding: const EdgeInsets.all(8.0),
 sliver: new SliverGrid(
 //Grid
 gridDelegate: new SliverGridDelegateWithFixedCrossAxisCount(
 crossAxisCount: 2, //Grid按兩列顯示
 mainAxisSpacing: 10.0,
 crossAxisSpacing: 10.0,
 childAspectRatio: 4.0,
 ),
 delegate: new SliverChildBuilderDelegate(
 (BuildContext context, int index) {
 //創建子widget
 return new Container(
 alignment: Alignment.center,
 color: Colors.cyan[100 * (index % 9)],
 child: new Text('grid item $index'),
 );
 },
 childCount: 20,
 ),
 ),
 ),
 //List
 new SliverFixedExtentList(
 itemExtent: 50.0,
 delegate: new SliverChildBuilderDelegate(
 (BuildContext context, int index) {
 //創建列表項
 return new Container(
 alignment: Alignment.center,
 color: Colors.lightBlue[100 * (index % 9)],
 child: new Text('list item $index'),
 );
 }, childCount: 50 //50個列表項
 ),
 ),
 ],
 ),
 );
 }
}
Flutter第六期 - ListView+GridView混合

Flutter第六期 - ListView+GridView混合

滾動監聽及控制:

import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
//Stateless widgets 是不可變的, 這意味著它們的屬性不能改變 - 所有的值都是最終的.
//Stateful widgets 持有的狀態可能在widget生命週期中發生變化. 實現一個 stateful widget 至少需要兩個類:
class MyApp extends StatelessWidget {
 @override
 Widget build(BuildContext context) {
// final wordPair = new WordPair.random();
 return new MaterialApp(
 title: '滾動監聽及控制',
 debugShowCheckedModeBanner: false,
 theme: new ThemeData(
 primarySwatch: Colors.blue,
// fontFamily: 'fontdemo1'
 ),
 home: new Scaffold(
 appBar: new AppBar(
 title: new Text('滾動監聽及控制'),
 ),
 body: new Center(
// child: new ListView(
// shrinkWrap: true,
// padding: const EdgeInsets.all(20.0),
// children: [
// const Text('I\'m dedicating every day to you'),
// const Text('Domestic life was never quite my style'),
// const Text('When you smile, you knock me out, I fall apart'),
// const Text('And I thought I was so smart'),
// ],
// ),
// child: new ListView3(),
// child: new GridView3(),
// child: new GridView33(),
 child: new ScrollControllerTestRoute(),
// child: new ScrollNotificationTestRoute(),
 ),
 ),
 );
 }
}
class ScrollControllerTestRoute extends StatefulWidget {
 @override
 ScrollControllerTestRouteState createState() {
 return new ScrollControllerTestRouteState();
 }
}
class ScrollControllerTestRouteState extends State {
 ScrollController _controller = new ScrollController();
 bool showToTopBtn = false; //是否顯示“返回到頂部”按鈕
 @override
 void initState() {
 //監聽滾動事件,打印滾動位置
 _controller.addListener(() {
 print(_controller.offset); //打印滾動位置
 if (_controller.offset < 1000 && showToTopBtn) {
 setState(() {
 showToTopBtn = false;
 });
 } 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"),
 );
 }),
 ),
 floatingActionButton: !showToTopBtn
 ? null
 : FloatingActionButton(
 child: Icon(Icons.arrow_upward),
 onPressed: () {
 //返回到頂部時執行動畫
 _controller.animateTo(.0,
 duration: Duration(milliseconds: 200), curve: Curves.ease);
 }),
 );
 }
}
class ScrollNotificationTestRoute extends StatefulWidget {
 @override
 _ScrollNotificationTestRouteState createState() =>
 new _ScrollNotificationTestRouteState();
}
class _ScrollNotificationTestRouteState
 extends State {
 String _progress = "0%"; //保存進度百分比
 @override
 Widget build(BuildContext context) {
 return Scrollbar(
 //進度條
 // 監聽滾動通知
 child: NotificationListener(
 onNotification: (ScrollNotification notification) {
 double progress = notification.metrics.pixels /
 notification.metrics.maxScrollExtent;
 //重新構建
 setState(() {
 _progress = "${(progress * 100).toInt()}%";
 });
 print("BottomEdge: ${notification.metrics.extentAfter == 0}");
 //return true; //放開此行註釋後,進度條將失效
 },
 child: Stack(
 alignment: Alignment.center,
 children: [
 ListView.builder(
 itemCount: 100,
 itemExtent: 50.0,
 itemBuilder: (context, index) {
 return ListTile(title: Text("$index"));
 }),
 CircleAvatar(
 //顯示進度百分比
 radius: 30.0,
 child: Text(_progress),
 backgroundColor: Colors.black54,
 )
 ],
 ),
 ),
 );
 }
}
 
Flutter第六期 - ListView+GridView混合

總結:學完網絡請求,大家把tolist裡面改寫就可以獨立出來不同的樣式去加載數據,還是挺方便的,代碼精簡不少~加油~

Flutter第六期 - ListView+GridView混合


分享到:


相關文章: