【问题标题】:How to pin multiple SliverPersistentHeaders in a CustomScrollView?如何在 CustomScrollView 中固定多个 SliverPersistentHeaders?
【发布时间】:2022-07-30 04:36:20
【问题描述】:

我正在尝试创建个人资料页面。我开发了一个自定义的 SliverAppBar 将它包裹在 SliverPersistentHeader 中并固定它。

现在,我还制作了一个 TabBar 并将其放入 SliverPersistentHeader 中,但它没有固定在我的第一个持久标题下方。

import 'package:flutter/material.dart';
import 'package:twitter/components/CustomSliverAppBarDelegate.dart';
import 'package:twitter/components/CustomSliverTabBarDelegate.dart';

class ProfileScreen extends StatefulWidget {
  const ProfileScreen({Key? key}) : super(key: key);

  @override
  _ProfileScreenState createState() => _ProfileScreenState();
}

class _ProfileScreenState extends State<ProfileScreen>
    with SingleTickerProviderStateMixin {
  late TabController tabController;

  @override
  void initState() {
    tabController = TabController(length: 3, vsync: this);
    super.initState();
  }

  @override
  void dispose() {
    tabController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    Size deviceSize = MediaQuery.of(context).size;
    return Scaffold(
      body: CustomScrollView(
        slivers: [
          const SliverPersistentHeader(
            delegate: CustomSliverAppBarDelegate(expandedHeight: 200),
            pinned: true,
          ),
          SliverList(
            delegate: SliverChildListDelegate([
              Row(
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                children: [
                  Container(
                    margin: const EdgeInsets.fromLTRB(20, 40, 0, 0),
                    child: Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: <Widget>[
                        Text(
                          'Name',
                          style: TextStyle(
                            fontSize: 18,
                            fontWeight: FontWeight.bold,
                          ),
                        ),
                        Text(
                          '@username',
                          style: TextStyle(
                            fontSize: 14,
                            fontWeight: FontWeight.w300,
                          ),
                        ),
                      ],
                    ),
                  ),
                  Container(
                    margin: const EdgeInsets.only(right: 20),
                    child: ElevatedButton(
                      onPressed: () {},
                      child: Text(
                        'Edit Profile',
                        style: TextStyle(
                            color: Colors.black, fontWeight: FontWeight.bold),
                      ),
                      style: ButtonStyle(
                          backgroundColor:
                              MaterialStateProperty.all(Colors.white),
                          overlayColor:
                              MaterialStateProperty.all(Colors.black26),
                          side: MaterialStateProperty.all(
                            BorderSide(style: BorderStyle.solid),
                          ),
                          shape: MaterialStateProperty.all(
                              RoundedRectangleBorder(
                                  borderRadius: BorderRadius.circular(20)))),
                    ),
                  ),
                ],
              ),
              Container(
                margin: const EdgeInsets.fromLTRB(20, 10, 0, 0),
                child: Column(
                  children: <Widget>[
                    Row(
                      children: <Widget>[
                        Icon(
                          Icons.bubble_chart,
                          color: Colors.black54,
                        ),
                        const SizedBox(width: 5),
                        Text(
                          'Born September 2, 1998',
                          style: TextStyle(fontWeight: FontWeight.w300),
                        ),
                      ],
                    ),
                    const SizedBox(height: 5),
                    Row(
                      children: <Widget>[
                        Icon(
                          Icons.calendar_today,
                          color: Colors.black54,
                        ),
                        const SizedBox(width: 5),
                        Text(
                          'Joined December 2021',
                          style: TextStyle(fontWeight: FontWeight.w300),
                        ),
                      ],
                    ),
                  ],
                ),
              ),
            ]),
          ),
          SliverPersistentHeader(
            delegate: CustomSliverTabBarDelegate(tabController: tabController),
          ),
          SliverFillRemaining(
            child: TabBarView(controller: tabController, children: const [
              Center(
                child: Text(
                  'Tweets',
                  style: TextStyle(color: Colors.black),
                ),
              ),
              Center(
                child: Text(
                  'Likes',
                  style: TextStyle(color: Colors.black),
                ),
              ),
              Center(
                child: Text(
                  'Media',
                  style: TextStyle(color: Colors.black),
                ),
              ),
            ]),
          )
        ],
      ),
    );
  }
}

如果我将第二个标题更改为 pinned = true:

SliverPersistentHeader(
            pinned: true,
            delegate: CustomSliverTabBarDelegate(tabController: tabController),
          ),

我收到以下错误:

The following assertion was thrown during performLayout():
SliverGeometry is not valid: The "layoutExtent" exceeds the "paintExtent".

The paintExtent is 48.0, but the layoutExtent is 200.0.

我在使用 NestedScrollView 时也遇到了同样的错误。我可以使用哪些方法来固定 2 个 SliverPersistentHeaders?

【问题讨论】:

    标签: flutter


    【解决方案1】:

    用 Align 小部件包裹我的条子为我解决了这个问题。

    class SearchBar extends SliverPersistentHeaderDelegate {
    
      SearchBar();
    
      @override
      Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) {
        
        return Align(
        //default value is Alignment.center
        child: AnimatedCrossFade(...
    
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-09-23
      • 2021-05-15
      • 1970-01-01
      • 2021-08-29
      • 2019-12-25
      • 2022-01-16
      • 2013-06-13
      相关资源
      最近更新 更多