web-dev-qa-db-fra.com

Flutter - Masquer FloatingActionButton

Existe-t-il un moyen intégré dans Flutter pour masquer un FloatingActionButton sur ListView défilement vers le bas puis affichage sur défilement vers le haut?

16
Marcin Szałek
import 'package:flutter/material.Dart';
import 'package:flutter/rendering.Dart';

void main() {
  runApp(new MyApp());
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Flutter Demo',
      theme: new ThemeData(

        primarySwatch: Colors.blue,
      ),
      home: new MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
 }
class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => new _MyHomePageState();
 }

 class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;
  ScrollController _hideButtonController;
  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }
  var _isVisible;
  @override
  initState(){
    super.initState();
    _isVisible = true;
    _hideButtonController = new ScrollController();
    _hideButtonController.addListener((){
      if(_hideButtonController.position.userScrollDirection == ScrollDirection.reverse){
        if(_isVisible == true) {
            /* only set when the previous state is false
             * Less widget rebuilds 
             */
            print("**** ${_isVisible} up"); //Move IO away from setState
            setState((){
              _isVisible = false;
            });
        }
      } else {
        if(_hideButtonController.position.userScrollDirection == ScrollDirection.forward){
          if(_isVisible == false) {
              /* only set when the previous state is false
               * Less widget rebuilds 
               */
               print("**** ${_isVisible} down"); //Move IO away from setState
               setState((){
                 _isVisible = true;
               });
           }
        }
    }});
  }
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text(widget.title),
      ),
      body: new Center(
        child: new CustomScrollView(
          controller: _hideButtonController,
          shrinkWrap: true,
          slivers: <Widget>[
            new SliverPadding(
              padding: const EdgeInsets.all(20.0),
              sliver: new SliverList(
                delegate: new SliverChildListDelegate(
                  <Widget>[
                    const Text('I\'m dedicating every day to you'),
                    const Text('Domestic life was never quite my style'),
                    const Text('When you smile, you knock me out, I fall apart'),
                    const Text('And I thought I was so smart'),
                    const Text('And I thought I was so smart'),
                    const Text('And I thought I was so smart'),
                    const Text('And I thought I was so smart'),
                    const Text('And I thought I was so smart'),
                    const Text('And I thought I was so smart'),
                    const Text('And I thought I was so smart'),
                    const Text('And I thought I was so smart'),
                    const Text('And I thought I was so smart'),
                    const Text('And I thought I was so smart'),
                    const Text('And I thought I was so smart'),
                    const Text('And I thought I was so smart'),
                    const Text('And I thought I was so smart'),
                    const Text('And I thought I was so smart'),
                    const Text('And I thought I was so smart'),
                    const Text('And I thought I was so smart'),
                    const Text('And I thought I was so smart'),
                    const Text('And I thought I was so smart'),
                    const Text('And I thought I was so smart'),
                    const Text('And I thought I was so smart'),
                    const Text('And I thought I was so smart'),
                    const Text('And I thought I was so smart'),
                    const Text('And I thought I was so smart'),
                    const Text('And I thought I was so smart'),
                    const Text('And I thought I was so smart'),
                    const Text('And I thought I was so smart'),
                    const Text('And I thought I was so smart'),
                    const Text('And I thought I was so smart'),
                    const Text('And I thought I was so smart'),
                    const Text('And I thought I was so smart'),
                    const Text('And I thought I was so smart'),
                    const Text('And I thought I was so smart'),
                    const Text('And I thought I was so smart'),
                    const Text('And I thought I was so smart'),
                    const Text('And I thought I was so smart'),
                    const Text('I realize I am crazy'),   
                  ],
                ),
              ),
            ),
          ],
        )
      ),
      floatingActionButton: new Visibility( 
        visible: _isVisible,
        child: new FloatingActionButton(
          onPressed: _incrementCounter,
          tooltip: 'Increment',
          child: new Icon(Icons.add),
        ),     
      ),
    );
  }
}

Je m'excuse si je n'ai pas utilisé listview car je ne sais pas comment faire défiler avec listview. Je répondrai aux autres parties de votre question.

Vous devez d'abord créer un scrollcontroller qui écoutera scrollPostion événements

Si scrollcontroller parvient à trouver scrolldirection avant ou arrière. Vous ajoutez un état qui définit un état sur visible.

Lorsque vous dessinez le bouton, vous enveloppez le bouton dans une classe visibilité . Vous définissez l'indicateur visible et le widget doit ignorer les commandes d'entrée.

Edit: je n'arrive pas à ajouter des liens vers ScrollController, ScrollerPosition, ScrollDirection et Opacity. Je suppose que vous pouvez le rechercher vous-même ou quelqu'un d'autre le modifier dans les liens

Edit2: utilisez CopsonRoad ou utilisez un widget de visibilité, sauf si vous voulez un widget non peint dans l'arborescence de mise en page

Edit3: À la lumière des nouveaux arrivants utilisant le code tel quel, je voudrais mettre à jour le code pour encourager de meilleures pratiques. Utilisez la visibilité au lieu de l'opacité. Supprimez io de setState. testé sur Flutter 1.5.4-hotfix.2

24
user1462442

Il y a plusieurs façons de le remettre. Permettez-moi d'en énumérer quelques-uns ici.

  1. Vous pouvez utiliser Visibility pour masquer/afficher FAB.

    floatingActionButton: Visibility(
      child: FloatingActionButton(...),
      visible: false, // set it to false
    )
    
  2. Avec Dart 2.2, vous pouvez utiliser if condition comme ceci:

    floatingActionButton: Column(
      children: <Widget>[
        if (shouldShow) FloatingActionButton(...), // visible if showShould is true
      ],
    )
    
  3. Vous pouvez utiliser le widget Opacity.

    floatingActionButton: Opacity(
      opacity: shouldShow ? 1 : 0, // visible if showShould is true
      child: FloatingActionButton(...),
    )
    
9
CopsOnRoad

Vous pouvez utiliser le widget Visibility pour gérer le widget Visibilité de l'enfant

échantillon :

  floatingActionButton:
            Visibility(visible: _visibilityFlag , child: _buildFAB(context)),
5
Sibin

Un autre très bon moyen est AnimatedOpacity

AnimatedOpacity(
          opacity: isEnabled ? 0.0 : 1.0,
          duration: Duration(milliseconds: 1000),
          child: FloatingActionButton(
             onPressed: your_method,
             tooltip: 'Increment',
             child: new Icon(Icons.add),
          ),
        )
0
Álvaro Agüero