2017-04-19 8 views
5

Ich habe eine scrollbare ListView, wo die Anzahl der Elemente dynamisch ändern kann. Immer wenn ein neues Element am Ende der Liste hinzugefügt wird, möchte ich programmgesteuert die ListView bis zum Ende scrollen. (Zum Beispiel so etwas wie eine Chat-Nachricht Liste, wo neue Nachrichten können am Ende hinzugefügt werden)Programmgesteuertes Scrollen bis zum Ende einer ListView

Meine Vermutung ist, dass ich brauchen würde, ein ScrollController in meinem State Objekt erstellen und manuell an den ListView Konstruktor übergeben, so kann ich später Anruf animateTo()/jumpTo() Methode auf dem Controller. Da ich jedoch den maximalen Scroll-Offset nicht einfach bestimmen kann, scheint es unmöglich, einfach einen scrollToEnd() Operationstyp auszuführen (während ich 0.0 einfach passieren kann, damit er zur Anfangsposition scrollt).

Gibt es einen einfachen Weg, dies zu erreichen?

Die Verwendung von reverse: true ist keine perfekte Lösung für mich, weil ich möchte, dass die Elemente an der Spitze ausgerichtet werden, wenn nur eine kleine Anzahl von Elementen in das ListView Ansichtsfenster passen.

Antwort

5

Wenn Sie eine in Schrumpfverpackung ListView mit reverse: true verwenden, scrollen Sie bis 0,0, was Sie wollen.

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), 
     ); 
     } 
    ), 
    ); 
    } 
} 
+0

Dies hat den Trick gemacht. In meinem speziellen Fall musste ich verschachtelte Spalten verwenden, um die ListView in ein Expanded-Widget einzufügen, aber die Grundidee ist dieselbe. – yyoon

+0

Ich kam auf der Suche nach einer Lösung, wollte nur erwähnen, dass die andere Antwort ein besserer Weg, dies zu erreichen ist - https://stackoverflow.com/questions/44141148/how-to-get-full-size-of- a-scrollcontroller –

+1

Ich stimme zu, diese Antwort (die ich auch geschrieben habe) definitiv besser. –

Verwandte Themen