我們在前幾天的List&Grid中,介紹了不同的列表用法,其中在ListView
, ListView.builder
,GridView
, GridView.builder
也使用到了基礎的滾動特效。而接續我們會介紹更多Flutter中關於「滾動效果」的特色與使用方法,方便我們在規劃app時能夠給予用戶更好的使用體驗!
DraggableScrollableSheet
元件提供我們一個在特定螢幕大小範圍內可以滾動的效果,通常用於在視窗底部(Bottom)彈出資訊的欄位。以下提供本元件用法:
DraggableScrollableSheet(
initialChildSize: 0.5, // 初始高度佔父元件的比例
maxChildSize: 0.9, // 最大高度佔父元件的比例
minChildSize: 0.2, // 最小高度佔父元件的比例
builder: (BuildContext context, ScrollController scrollController) {
return Container(
color: Colors.blue[100],//背景顏色
child: ListView.builder( //主要可滾動區域
controller: scrollController,//滾動控制器
itemCount: 25,
itemBuilder: (BuildContext context, int index) {
return ListTile(title: Text('Item $index'));
},
),
);
},
),
這個範例我們示範如何用DraggableScrollableSheet
元件製作個預設佔有一半螢幕空間的List效果,index從0~24
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return const MaterialApp(
home: HomePage(),
);
}
}
class HomePage extends StatelessWidget {
const HomePage({Key? key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('DraggableScrollableSheet'),
),
body: SizedBox.expand(
child: DraggableScrollableSheet(
initialChildSize: 0.5, // 初始高度佔父元件的比例
maxChildSize: 0.9, // 最大高度佔父元件的比例
minChildSize: 0.2, // 最小高度佔父元件的比例
builder: (BuildContext context, ScrollController scrollController) {
return Container(
color: Colors.blue[100],
child: ListView.builder(
controller: scrollController,
itemCount: 25,
itemBuilder: (BuildContext context, int index) {
return ListTile(title: Text('Item $index'));
},
),
);
},
),
),
);
}
}
DraggableScrollableSheet 使用範例
藍色的List部分可以滾動,上方白色部分則可以放置原有的內容,不會跟著滾動!
當我們在視窗中需要多個滾動的事件,為了達成較為複雜的滾動嵌套事件,我們會使用SilverGrid
、SilverList
的方式來達成。而以下我們會用SliverChildBuilderDelegate
元件來介紹如何靈活運用此複雜滾動效果!
以下提供本元件的範例用法:
SliverChildBuilderDelegatem元件建立一個包含兩個卡片的SliverList。 每個卡片內部包含
元件詳細內部功能細分如下:
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
return Card( //卡片元件
margin: const EdgeInsets.all(8.0),
child: Column(
children: <Widget>[
Text('Grid Item $index'),
Expanded(
child: ListView.builder(
itemCount: 10, // 列表中的項目數
itemBuilder: (BuildContext context, int subIndex) {
return ListTile(
title: Text('Sub Item $subIndex'),
);
},
),
),
],
),
);
},
childCount: 2, //index值為0~1
),
最外層我們使用CustomScrollView
元件,預先設定
接下來,slivers內具有兩個SliverGrid
元件,分別包含了上面提及的SliverChildBuilderDelegate
元件,其中
SliverGrid
內,有兩列SliverChildBuilderDelegate
,並且每個卡片子索引ListTile由0~9計算SliverGrid
內,同樣有兩列SliverChildBuilderDelegate
,並且每個卡片子索引ListTile做了"subindex+5"的變化,由5~14計算最後我們會再由semanticIndexOffset: 2
代表兩行卡片間的 index (第一行為Griditem 0-1、第二行為2-3),相差(偏移量)為2
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('CustomScrollView Example'),
),
body: CustomScrollView(
semanticChildCount: 4,
slivers: <Widget>[
SliverGrid(
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
),
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
return Card(
margin: const EdgeInsets.all(8.0),
child: Column(
children: <Widget>[
Text('Grid Item $index'),//設為第二行的索引號Grid item0,1
Expanded(
child: ListView.builder(
itemCount: 10, // 列表中的項目數
itemBuilder: (BuildContext context, int subIndex) {
return ListTile(
title: Text('Sub Item $subIndex'), //設為卡片索引號,為0~9
);
},
),
),
],
),
);
},
childCount: 2,
),
),
SliverGrid(
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
),
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
return Card(
margin: const EdgeInsets.all(8.0),
child: Column(
children: <Widget>[
Text('Grid Item ${index + 2}'),//設為第二行的索引號Grid item2,3
Expanded(
child: ListView.builder(
itemCount: 10, // 列表中的項目數
itemBuilder: (BuildContext context, int subIndex) {
return ListTile(
title: Text('Sub Item ${subIndex + 5}'), //設為卡片索引號+5,為5~14
);
},
),
),
],
),
);
},
childCount: 2,
semanticIndexOffset: 2,//兩者語意項目索引的偏移量
),
),
],
),
),
);
}
}