嵌套滚动正文中的正文显示在 headerSliv​​erBuilder 后面

Don*_*n P 11 flutter

我创建了一个 flutter 小部件,它由几个组成应用栏和选项卡的条子组成,在其下方,我有 TabBarView。

1) 选项卡和主体 ScrollView 之间有过多的填充,但我不确定是什么元素导致了它。

2) 在 ListView 中滚动内容时,它显示在选项卡后面,我不确定我需要做什么来防止这种情况发生。

3)最后,您可以滚动直到 ListView 中没有更多可见项目,您将如何滚动类似于 html/css 溢出,它在内容末尾停止滚动?

这是我的看法

import 'package:flutter/material.dart';
import 'package:nssa/bloc/conference/bloc.dart';

class ConferencePage extends StatelessWidget {

  final Conference conference;

  ConferencePage(@required this.conference);

  TabBar getTabBar(List<Zone> zones) {
    return  TabBar(
      tabs: zones.map((zone) {
        return new Tab(text: zone.type);
      }).toList(growable: false)
    );
  }

  TabBarView getTabBody(List<Zone> zones) {
    return TabBarView(
      children: zones.map((zone) {
        return ListView(
          children: zone.upcomingEvents().map((event) {
            return new ListTile(title: Text(event.name));
          }).toList(growable: false)
        );
      }).toList(growable: false)
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: DefaultTabController(
        length: this.conference.zones.length,
        child: NestedScrollView(
          headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
            return <Widget>[
              SliverAppBar(
                expandedHeight: 200.0,
                floating: true,
                pinned: true,
                flexibleSpace: FlexibleSpaceBar(
                  centerTitle: true,
                  title: Text(
                    this.conference.name,
                    style: TextStyle(
                      color: Colors.white,
                      fontSize: 16.0,
                    )
                  ),
                  background: Hero(
                    tag: this.conference.name,
                    child: Image.network(
                      this.conference.image,
                      fit: BoxFit.cover,
                    )
                  )
                ),
              ),
              SliverPersistentHeader(
                delegate: _SliverAppBarDelegate(
                  this.getTabBar(this.conference.zones),
                ),
                pinned: true,
              ),
            ];
          },
          body: this.getTabBody(this.conference.zones)
        ),
      ),
      floatingActionButton: FloatingActionButton(
        child: Icon(Icons.card_membership)
      ),
    );
  }
}

class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
  _SliverAppBarDelegate(this._tabBar);

  final TabBar _tabBar;

  @override
  double get minExtent => _tabBar.preferredSize.height;
  @override
  double get maxExtent => _tabBar.preferredSize.height;

  @override
  Widget build(
      BuildContext context, double shrinkOffset, bool overlapsContent) {
    return new Container(
      child: _tabBar,
    );
  }

  @override
  bool shouldRebuild(_SliverAppBarDelegate oldDelegate) {
    return false;
  }
}
Run Code Online (Sandbox Code Playgroud)

这是我的模型

import 'package:flutter/foundation.dart';
import 'package:equatable/equatable.dart';
import 'package:meta/meta.dart';
import 'package:intl/intl.dart';

import 'dart:developer';

@immutable
class Zone extends Equatable {
  final String type;
  final List<String> divisions;
  final List<Event> events;
  final DateTime _now = DateTime.now();

  Zone (
    @required this.type,
    @required this.divisions,
    @required this.events,
  );

  @override
  List<Object> get props => [type, /*divisions,*/ events];

  Event currentEvent() {
    return this.events.firstWhere((event) => event.startDate.isBefore(_now) && event.endDate.isAfter(_now), orElse: () => null);
  }

  List<Event> pastEvents() {
    return this.events.where((event) => event.endDate.isBefore(_now)).toList(growable: false);
  }

  List<Event> upcomingEvents() {
    return this.events.where((event) => event.startDate.isAfter(_now)).toList(growable: false);
  }

  factory Zone.fromJson(Map<String, dynamic> zoneJSON) {
    List<String> divisions = (zoneJSON['divisions'] as List).map((division) {
      return division.toString();
    }).toList(growable: true);

    List<Event> events = (zoneJSON['events'] as List).map((event) {
      return new Event.fromJson(event);
    }).toList(growable: true);

    events.sort((a,b) => a.startDate.compareTo(b.startDate));

    return Zone(
        zoneJSON['type'],
        divisions,
        events,
    );
  }
}
@immutable
class Event extends Equatable {
  final String name;
  final String details;
  final DateTime startDate;
  final DateTime endDate;
  final String image;
  final String ticketURL;

  Event (
    @required this.name,
    @required this.details,
    @required this.startDate,
    @required this.endDate,
    @required this.image,
    @required this.ticketURL,
  );

  @override
  List<Object> get props => [name, startDate, endDate, details, image, ticketURL];

  factory Event.fromJson(Map<String, dynamic> eventJSON) {
    DateFormat dateFormat = DateFormat("yyyy-MM-dd");
    return Event(
        eventJSON['name'],
        eventJSON['details'],
        dateFormat.parse(eventJSON['startDate'].toString()),
        dateFormat.parse(eventJSON['endDate'].toString()),
        eventJSON['image'],
        eventJSON['ticketURL']
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

过度填充

标签后面的内容

小智 1

使用 NestedScrollView 时,您可能需要使用 SliverOverlapAbsorber 包裹 SliverAppBar,以避免主体内容在应用栏下方滚动。

另外,您最好将 TabBar 放在bottomSliverAppBar 中,就像官方示例一样。

请参阅此处的文档:https ://api.flutter.dev/flutter/widgets/NestedScrollView-class.html