180 votes

Par programme de défilement à la fin d'une ListView

J'ai un défilement ListView lorsque le nombre d'éléments peuvent changer dynamiquement. Chaque fois qu'un nouvel élément est ajouté à la fin de la liste, je voudrais de programmation pour faire défiler l' ListView à la fin. (par exemple, quelque chose comme un message de discussion de la liste où les nouveaux messages peuvent être ajoutés à la fin)

Ma conjecture est que j'aurais besoin de créer un ScrollController mon State objet et le passer manuellement à l' ListView constructeur, donc je peut appeler plus tard animateTo() / jumpTo() méthode sur le contrôleur. Cependant, depuis que je ne peut pas facilement déterminer le maximum de défilement de décalage, il semble impossible de simplement effectuer une scrollToEnd() type d'opération (alors que je peux facilement passer 0.0 pour le faire défiler à la position initiale).

Est-il un moyen facile pour y parvenir?

À l'aide de reverse: true n'est pas une solution parfaite pour moi, parce que je voudrais les éléments pour être aligné en haut quand il ya seulement un petit nombre d'éléments qui s'inscrivent dans l' ListView fenêtre d'affichage.

212voto

CopsOnRoad Points 4705

Utiliser ScrollController.jumpTo() ou ScrollController.animateTo() méthode pour y parvenir.

Voici un extrait de code (Après 1 seconde, l' ListView seront faites défiler vers le bas)

class _HomePageState extends State<HomePage> {
  ScrollController _controller = ScrollController();

  @override
  Widget build(BuildContext context) {
    Timer(Duration(milliseconds: 1000), () => _controller.jumpTo(_controller.position.maxScrollExtent));

    return ListView.builder(
      controller: _controller,
        itemCount: 50,
        itemBuilder: (context, index) => ListTile(title: Text("ListTile"),));
  }
}

152voto

Collin Jackson Points 29995

Si vous utilisez un film rétractable ListView avec reverse: true, le défilement à 0.0 faire ce que vous souhaitez.

import 'dart:collection';

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Example',
      home: new MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => new _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  List<Widget> _messages = <Widget>[new Text('hello'), new Text('world')];
  ScrollController _scrollController = new ScrollController();

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      body: new Center(
        child: new Container(
          decoration: new BoxDecoration(backgroundColor: Colors.blueGrey.shade100),
          width: 100.0,
          height: 100.0,
          child: new Column(
            children: [
              new Flexible(
                child: new ListView(
                  controller: _scrollController,
                  reverse: true,
                  shrinkWrap: true,
                  children: new UnmodifiableListView(_messages),
                ),
              ),
            ],
          ),
        ),
      ),
      floatingActionButton: new FloatingActionButton(
        child: new Icon(Icons.add),
        onPressed: () {
          setState(() {
            _messages.insert(0, new Text("message ${_messages.length}"));
          });
          _scrollController.animateTo(
            0.0,
            curve: Curves.easeOut,
            duration: const Duration(milliseconds: 300),
          );
        }
      ),
    );
  }
}

2voto

winter Points 996

J'ai tellement de problème en essayant d'utiliser le contrôleur de défilement pour aller vers le bas de la liste que j'ai utiliser une autre approche.

Au lieu de créer un événement pour envoyer la liste vers le bas, je change ma logique d'utiliser une liste inversée.

Donc, chaque fois que j'ai un nouvel élément, j'ai simplement fait à insérer en haut de la liste.

// add new message at the begin of the list 
list.insert(0, message);
// ...

// pull items from the database
list = await bean.getAllReversed(); // basically a method that applies a descendent order

// I remove the scroll controller
new Flexible(
  child: new ListView.builder(
    reverse: true, 
    key: new Key(model.count().toString()),
    itemCount: model.count(),
    itemBuilder: (context, i) => ChatItem.displayMessage(model.getItem(i))
  ),
),

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