CustomScrollView 中能实现一些 滚动的效果:这里请出你们的 女神 ‘伊琳格娃’
page_sliver_list.dart
import 'dart:convert' as convert;
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
class PageSliverList extends StatefulWidget {
const PageSliverList({Key? key}) : super(key: key);
@override
_PageSliverListState createState() => _PageSliverListState();
}
class _PageSliverListState extends State<PageSliverList> {
List<CountryInfo> _countryArray = [];
List<Map> items = [
{'title': 'A', 'color': Colors.green, 'pinned': true},
{'title': 'B', 'color': Colors.red, 'pinned': true},
{'title': 'C', 'color': Colors.blue, 'pinned': true},
{'title': 'D', 'color': Colors.amberAccent, 'pinned': true},
{'title': 'E', 'color': Colors.deepOrangeAccent, 'pinned': true},
{'title': 'F', 'color': Colors.cyan, 'pinned': true},
];
@override
void initState() {
// TODO: implement initState
super.initState();
_request();
}
@override
Widget build(BuildContext context) {
final args = ModalRoute.of(context)!.settings.arguments as Map;
return Scaffold(
appBar: AppBar(
title: Text(args['title']),
),
body: CustomScrollView(
slivers: _buildSliver(),
// slivers: [
// // SliverToBoxAdapter(
// // child: Container(
// // color: Colors.deepOrangeAccent,
// // height: 50,
// // child: Text("A"),
// // ),
// // ),
// SliverPersistentHeader(
// delegate: _DelegateSliverPersistent(
// title: 'A',
// color: Colors.deepOrangeAccent,
// ),
// pinned: true,
// floating: false,
// ),
//
// _buildSliverItem('A'),
// SliverPersistentHeader(
// delegate: _DelegateSliverPersistent(
// title: 'B',
// color: Colors.greenAccent,
// ),
// pinned: true,
// floating: false,
// ),
// _buildSliverItem('B'),
// SliverPersistentHeader(
// delegate: _DelegateSliverPersistent(
// title: 'C',
// color: Colors.pinkAccent,
// ),
// pinned: true,
// floating: false,
// ),
// _buildSliverItem('C'),
// SliverPersistentHeader(
// delegate: _DelegateSliverPersistent(
// title: 'D',
// color: Colors.lightBlueAccent,
// ),
// pinned: true,
// floating: false,
// ),
// _buildSliverItem('D'),
// SliverPersistentHeader(
// delegate: _DelegateSliverPersistent(
// title: 'E',
// color: Colors.orange,
// ),
// pinned: true,
// floating: false,
// ),
// _buildSliverItem('E'),
// SliverPersistentHeader(
// delegate: _DelegateSliverPersistent(
// title: 'F',
// color: Colors.green,
// ),
// pinned: true,
// floating: false,
// ),
// _buildSliverItem('F'),
// ],
),
floatingActionButton: FloatingActionButton(
child: const Icon(Icons.refresh),
onPressed: () {
setState(() {
_countryArray.clear();
});
_request();
},
),
);
}
_request() async {
const String url = 'https://m.gbm001.com/area/country/getAllCountry?type=2';
final res = await http.get(Uri.parse(url));
if (res.statusCode != 200) {
throw ('http error, code ${res.statusCode}');
}
final json = convert.jsonDecode(res.body)['data'];
final List<CountryInfo> countryArray = [];
json.forEach(
(item) {
countryArray.add(CountryInfo(
countryNameZh: item['countryNameZh'],
countryId: item['countryId'],
flagImgUrl: item['flagImgUrl'],
));
},
);
setState(() => _countryArray = countryArray);
// print(json);
}
_buildSliverItem(String str) {
final List<CountryInfo> list = _countryArray
.where((element) => element.countryId.startsWith(str))
.toList();
return SliverGrid(
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
return InkWell(
onTap: () {
Navigator.pushNamed(context, "/page_sliver_detail",
arguments: list);
},
child: Column(
children: [
CircleAvatar(
backgroundColor: Colors.white,
child: ClipOval(
child: Image.network(
list[index].flagImgUrl,
fit: BoxFit.cover,
width: 40,
height: 40,
),
),
),
FittedBox(
child: Text(list[index].countryNameZh),
)
],
),
);
// return ListTile(
// title: Text(list[index].countryNameZh),
// subtitle: Text(list[index].countryId),
// leading: CircleAvatar(
// backgroundColor: Colors.white,
// child: ClipOval(
// child: Image.network(
// list[index].flagImgUrl,
// fit: BoxFit.cover,
// width: 40,
// height: 40,
// ),
// ),
// ),
// trailing: Icon(Icons.keyboard_arrow_right_outlined),
// );
},
childCount: list.length,
),
gridDelegate:
SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 4),
);
// return SliverList(
// delegate: SliverChildBuilderDelegate(
// (BuildContext context, int index) {
// return ListTile(
// title: Text(list[index].countryNameZh),
// subtitle: Text(list[index].countryId),
// leading: CircleAvatar(
// backgroundColor: Colors.white,
// child: ClipOval(
// child: Image.network(
// list[index].flagImgUrl,
// fit: BoxFit.cover,
// width: 40,
// height: 40,
// ),
// ),
// ),
// trailing: Icon(Icons.keyboard_arrow_right_outlined),
// );
// },
// childCount: list.length,
// ),
// );
}
_buildSliver() {
List<Widget> widgetArray = [];
for (var element in items) {
widgetArray.addAll([
SliverPersistentHeader(
delegate: _DelegateSliverPersistent(
element: element,
),
pinned: element['pinned'],
floating: false,
),
_buildSliverItem(element['title']),
]);
}
return widgetArray;
// items.map((e) {
// return [
// SliverPersistentHeader(
// delegate: _DelegateSliverPersistent(
// title: 'A',
// color: Colors.deepOrangeAccent,
// ),
// pinned: true,
// floating: false,
// ),
// _buildSliverItem('A'),
// ];
// }).toList(),
}
}
class _DelegateSliverPersistent extends SliverPersistentHeaderDelegate {
final Map element;
_DelegateSliverPersistent({required this.element});
@override
Widget build(
BuildContext context, double shrinkOffset, bool overlapsContent) {
print(
'_DelegateSliverPersistent title${element['color']}; title${element['title']}; overlapsContent:$overlapsContent');
return Container(
color: element['color'],
height: 50,
child: Text(element['title']),
);
}
@override
// TODO: implement maxExtent
double get maxExtent => 50;
@override
// TODO: implement minExtent
double get minExtent => 50;
@override
bool shouldRebuild(covariant _DelegateSliverPersistent oldDelegate) {
// TODO: implement shouldRebuild
// return oldDelegate.title == title;
return 50 != oldDelegate.maxExtent || 50 != oldDelegate.minExtent;
}
}
class CountryInfo {
final String countryNameZh;
final String countryId;
final String flagImgUrl;
CountryInfo(
{required this.countryNameZh,
required this.countryId,
required this.flagImgUrl});
@override
String toString() {
// TODO: implement toString
return 'countryNameZh:$countryNameZh ,countryId:$countryId';
}
}
page_sliver_detail.dart
import 'package:flutter/material.dart';
import 'package:flutter_sliver/pages/subPages/page_sliver_list.dart';
class PageSliverDetail extends StatefulWidget {
const PageSliverDetail({Key? key}) : super(key: key);
@override
_PageSliverDetailState createState() => _PageSliverDetailState();
}
class _PageSliverDetailState extends State<PageSliverDetail> {
@override
Widget build(BuildContext context) {
final List<CountryInfo> args =
ModalRoute.of(context)!.settings.arguments as List<CountryInfo>;
return Scaffold(
// appBar: AppBar(
// centerTitle: true,
// title: const Text("Sliver Detail"),
// ),
body: CustomScrollView(
physics: const BouncingScrollPhysics(),
slivers: [
SliverAppBar(
expandedHeight: 200,
centerTitle: true,
// title: Text("nihao"),
floating: false,
pinned: true,
snap: false,
stretch: true,
onStretchTrigger: () async {
print('onStretchTrigger');
return;
},
flexibleSpace: FlexibleSpaceBar(
title: Text("nihao"),
background: Image.network(
'http://cdn.max-c.com/heybox/dailynews/img/343ab5e0f8489978c6bab49ef73daac6.jpg',
fit: BoxFit.cover,
),
collapseMode: CollapseMode.parallax,
),
),
SliverList(
delegate: SliverChildListDelegate(
_buildInfo(args),
))
],
),
);
}
_buildInfo(List<CountryInfo> args) {
return args
.map((e) => Card(
child: Row(
children: [
CircleAvatar(
child: ClipOval(
child: Image.network(
e.flagImgUrl,
width: 50,
height: 50,
),
),
),
Padding(
padding: EdgeInsets.only(left: 10),
child: Text(e.countryNameZh),
),
],
),
))
.toList();
}
}