7 votes

Flutter SliverAppBar avec Tabs superpose le contenu

J'ai suivi ce tutoriel ( https://medium.com/@diegoveloper/flutter-collapsing-toolbar-sliver-app-bar-14b858e87abe ) pour créer une CollapsingToolbar avec une TabBar.

Le problème est que, lorsque je fais défiler la page, le contenu du corps se superpose à la barre d'onglets.

Voici le code :

@override
Widget build(BuildContext context) {
return Scaffold(
  body: DefaultTabController(
    length: 2,
    child: NestedScrollView(
      headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
        return <Widget>[
          SliverAppBar(
            expandedHeight: 200.0,
            floating: false,
            pinned: true,
            flexibleSpace: FlexibleSpaceBar(
                centerTitle: true,
                title: Text("Collapsing Toolbar",
                    style: TextStyle(
                      color: Colors.white,
                      fontSize: 16.0,
                    )),
                background: Image.network(
                  "https://images.pexels.com/photos/396547/pexels-photo-396547.jpeg?auto=compress&cs=tinysrgb&h=350",
                  fit: BoxFit.cover,
                )),
          ),
          SliverPersistentHeader(
            delegate: _SliverAppBarDelegate(
              TabBar(
                labelColor: Colors.black87,
                unselectedLabelColor: Colors.grey,
                tabs: [
                  Tab(icon: Icon(Icons.info), text: "Tab 1"),
                  Tab(icon: Icon(Icons.lightbulb_outline), text: "Tab 2"),
                ],
              ),
            ),
            pinned: true,
          ),
        ];
      },
      body: Text("Sample text"),
    ),
  ),
);

Et le délégué :

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;
  }
}

Une idée à ce sujet ?

2voto

niegus Points 1288

Au cas où quelqu'un rencontrerait le même problème, j'ai résolu le problème en utilisant : https://pub.dartlang.org/packages/extended_nested_scroll_view

Exemple :

class _MatchFragmentState extends State<MatchFragment> with TickerProviderStateMixin {
  TabController primaryTC;

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

@override
Widget build(BuildContext context) {

final double statusBarHeight = MediaQuery.of(context).padding.top;
//var tabBarHeight = primaryTabBar.preferredSize.height;
var pinnedHeaderHeight =
//statusBar height
statusBarHeight +
    //pinned SliverAppBar height in header
    kToolbarHeight;

return Scaffold(
    body: NestedScrollViewRefreshIndicator(
      onRefresh: onRefresh,
      child: ExtendedNestedScrollView(
          headerSliverBuilder: (c, f) {
            return <Widget>[
              SliverAppBar(
                pinned: true,
                expandedHeight: kExpandedHeight,
                title: Text('Title'),
                flexibleSpace: FlexibleSpaceBar(
                    background: Image.network(
              "https://images.pexels.com/photos/396547/pexels-photo-396547.jpeg?auto=compress&cs=tinysrgb&h=350",
              fit: BoxFit.cover,
            ))
                ),
              )
            ];
          },
          pinnedHeaderSliverHeight: pinnedHeaderHeight,
          keepOnlyOneInnerNestedScrollPositionActive: true,
          body: Column(
            children: <Widget>[
              TabBar(
                controller: primaryTC,
                labelColor: Colors.black87,
                unselectedLabelColor: Colors.grey,
                tabs: [
                  Tab(text: "Tab1"),
                  Tab(text: "Tab2"),
                  Tab(text: "Tab3"),
                ],
              ),
              Expanded(
                child: TabBarView(
                  controller: primaryTC,
                  children: <Widget>[
                    new Tab1Screen(),
                    new Tab2Screen(),
                    new Tab3Screen()
                  ],
                ),
              )
            ],
          )
        ),
      )
    );
  }
}

Future<Null> onRefresh() {
  final Completer<Null> completer = new Completer<Null>();
  new Timer(const Duration(seconds: 1), () {
    completer.complete(null);
  });
  return completer.future.then((_) {});
}

2voto

kontashi35 Points 1

J'ai passé quelques jours à trouver le problème. Il s'avère qu'il peut être résolu avec extended_nested_scroll_view 1.0.1 comme @niegus l'a mentionné plus haut mais il utilise une ancienne version donc cela n'a pas fonctionné pour moi. Mais j'ai corrigé le problème avec la dernière version
Voici un gif de démonstration :
https://giphy.com/gifs/lMyFPbu74ycEaQFB1v

Etapes à franchir
1. Ajouter le plugin dans pubspec.yaml

mis à jour
extended_nested_scroll_view : ^3.0.0

2. coller le code dans main.dart

import 'dart:async';
import 'package:extended_nested_scroll_view/extended_nested_scroll_view.dart' as extend;
import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  var scrollController = ScrollController();

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        title: 'Flutter Demo',
        theme: ThemeData(
          primarySwatch: Colors.blue,
        ),
        home: MatchFragment());
  }

}
class MatchFragment extends StatefulWidget {
  @override
  _MatchFragmentState createState() => _MatchFragmentState();
}

class _MatchFragmentState extends State<MatchFragment>  with TickerProviderStateMixin {
  TabController primaryTC;

  @override
  void initState() {
    primaryTC = new TabController(length: 2, vsync: this);
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    final double statusBarHeight = MediaQuery.of(context).padding.top;
//var tabBarHeight = primaryTabBar.preferredSize.height;
    var pinnedHeaderHeight =
//statusBar height
    statusBarHeight +
        //pinned SliverAppBar height in header
        kToolbarHeight;
    return Scaffold(
        body: DefaultTabController(
          length: 2,
            child: extend.NestedScrollView(
                headerSliverBuilder: (c, f) {
                  return <Widget>[
                  SliverAppBar(
                  pinned: true,
                  expandedHeight: 200,
                  title: Text('Title'),
                  flexibleSpace: FlexibleSpaceBar(
                  background: Image.network(
                  "https://images.pexels.com/photos/396547/pexels-photo-396547.jpeg?auto=compress&cs=tinysrgb&h=350",
                  fit: BoxFit.cover,
                  ))
                  ),

                  ];

                },
                pinnedHeaderSliverHeightBuilder: () {
                  return pinnedHeaderHeight;
                },
                body: Column(
                  children: <Widget>[
                    TabBar(
                      controller: primaryTC,
                      labelColor: Colors.black87,
                      unselectedLabelColor: Colors.grey,
                      tabs: [
                        Tab(text: "Tab1"),
                        Tab(text: "Tab2"),
                      ],
                    ),
                    Expanded(
                      child: TabBarView(
                        controller: primaryTC,
                        children: <Widget>[
                           Text('This is tab one'),
                           Text('This is tab one'),
                        ],
                      ),
                    )
                  ],
                )

            ),
        )
    );

}

}

1voto

jainam Points 31

Une solution simple consisterait à donner une couleur de décoration à la tête de l'onglet.

par exemple

Container(
  decoration: BoxDecoration(
    color: Colors.white,
  ),
  child: tabBar,
);

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X