data.json
assets:
- assets/data.json
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'dart:convert' as convert;
import 'package:flutter/services.dart';
import 'detail_page.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.pink,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
@override
State createState() => _MyHomePageState();
}
class _MyHomePageState extends State {
List members = [];
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: RefreshIndicator(
onRefresh: () async {
members.clear();
await Future.delayed(const Duration(seconds: 3));
String json = await rootBundle.loadString("assets/data.json");
final res = convert.jsonDecode(json);
members = ((res["rows"] ?? []) as List).map((item) {
return Member.fromJson(item);
}).toList();
setState(() {});
},
child: Scrollbar(
child: CustomScrollView(
slivers: [
const SliverToBoxAdapter(),
SliverPersistentHeader(
pinned: true,
delegate: _MyDelegate('Team SII', const Color(0xffb4006e))),
_builsTeamList("SII"),
SliverPersistentHeader(
pinned: true,
delegate: _MyDelegate('Team G', const Color(0xff91cdeb))),
_builsTeamList("G"),
SliverPersistentHeader(
pinned: true,
delegate: _MyDelegate('Team HII', const Color(0xfff39800))),
_builsTeamList("HII"),
SliverPersistentHeader(
floating: true,
pinned: false,
delegate: _MyDelegate('Team X', const Color(0xffb4002e))),
_builsTeamList("X"),
SliverPersistentHeader(
floating: true,
pinned: false,
delegate: _MyDelegate('Team 预备生', const Color(0xffb4002e))),
_builsTeamList("预备生"),
],
)),
));
}
Widget _builsTeamList(String teamName) {
final teamMembers = members.where((m) => m.team == teamName).toList();
return SliverGrid(
delegate: SliverChildBuilderDelegate(
(context, index) {
final m = teamMembers[index];
return InkWell(
onTap: () => Navigator.of(context).push(
MaterialPageRoute(builder: (_) => DetailPage(member: m))),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Hero(
tag: m.avartUrl,
child: ClipOval(
child: CircleAvatar(
backgroundColor: Colors.white,
child: Image.network(m.avartUrl),
),
)),
const SizedBox(
height: 10,
),
Text(
m.name.toString(),
),
]));
},
childCount: teamMembers.length,
),
gridDelegate:
const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 4),
);
}
}
class _MyDelegate extends SliverPersistentHeaderDelegate {
final String title;
final Color color;
_MyDelegate(this.title, this.color);
@override
Widget build(Object context, double shrinkOffset, bool overlapsContent) {
return Container(
color: color,
child: FittedBox(
child: Text(title),
));
}
@override
double get maxExtent => 60;
@override
double get minExtent => 60;
@override
bool shouldRebuild(covariant _MyDelegate oldDelegate) {
return title == oldDelegate.title;
}
}
class Member {
dynamic id;
dynamic name;
dynamic team;
dynamic color;
dynamic nickname;
dynamic company;
dynamic join_day;
dynamic height;
dynamic birth_day;
dynamic star_sign_12;
dynamic star_sign_48;
dynamic birth_place;
dynamic speciality;
dynamic hobby;
String get avartUrl => "https://www.snh48.com/images/member/zp_$id.jpg";
Member(
this.id,
this.name,
this.team,
this.color,
this.nickname,
this.company,
this.join_day,
this.height,
this.birth_day,
this.star_sign_12,
this.star_sign_48,
this.birth_place,
this.speciality,
this.hobby);
factory Member.fromJson(Map json) => Member(
json['sid'],
json['sname'],
json['tname'],
json['tColor'],
json["nickname"],
json["company"],
json["join_day"],
json["height"],
json["birth_day"],
json["star_sign_12"],
json["star_sign_48"],
json["birth_place"],
json["speciality"],
json["hobby"]);
}
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:flutter_demo/main.dart';
class DetailPage extends StatefulWidget {
final Member member;
const DetailPage({Key? key, required this.member}) : super(key: key);
@override
_DetailPageState createState() => _DetailPageState();
}
class _DetailPageState extends State {
@override
Widget build(BuildContext context) {
return Scaffold(
body: CustomScrollView(slivers: [
SliverAppBar(
pinned: true,
backgroundColor: Colors.pink[100],
expandedHeight: 300,
flexibleSpace: FlexibleSpaceBar(
title: Text(
'SNH48-${widget.member.name}',
style: const TextStyle(fontSize: 14),
),
background: Center(
child: Padding(
padding: const EdgeInsets.all(100.0),
child: AspectRatio(
aspectRatio: 1,
child: Hero(
tag: widget.member.avartUrl,
child: Material(
shadowColor: Colors.red,
shape: const CircleBorder(),
elevation: 8,
child: ClipOval(
child: Image.network(widget.member.avartUrl,
fit: BoxFit.cover),
)),
),
),
),
),
collapseMode: CollapseMode.pin)),
SliverList(
delegate: SliverChildListDelegate([
ListTile(
title: const Text('昵称'),
trailing: Text(widget.member.nickname.toString())),
ListTile(
title: const Text('所属公司'),
trailing: Text(widget.member.company.toString())),
ListTile(
title: const Text('加入时间'),
trailing: Text(widget.member.join_day.toString())),
ListTile(
title: const Text('身高'),
trailing: Text(widget.member.height.toString())),
ListTile(
title: const Text('生日'),
trailing: Text(widget.member.birth_day.toString())),
ListTile(
title: const Text('加入所属'),
trailing: Text(widget.member.star_sign_12.toString())),
ListTile(
title: const Text('最终所属'),
trailing: Text(widget.member.star_sign_48.toString())),
ListTile(
title: const Text('出生地'),
trailing: Text(widget.member.birth_place.toString())),
ListTile(
title: const Text('个人特长'),
trailing: Text(widget.member.speciality.toString())),
ListTile(
title: const Text('兴趣爱好'),
trailing: Text(widget.member.hobby.toString())),
]))
]));
}
}