Flutte Advanced - Sliver Example

 

 

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<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  List<Member> 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<dynamic>).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<String, dynamic> 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<DetailPage> {
  @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())),
      ]))
    ]));
  }
}

Guess you like

Origin blog.csdn.net/RreamigOfGirls/article/details/131112496