Как использовать FutureBuilder, который создает более высокий виджет в ListView?

#flutter #flutter-layout

#flutter #flutter-layout

Вопрос:

У меня есть ListView с серым полем высотой 200 пикселей, когда проходит 3 секунды, я хочу, чтобы это серое поле изменилось на синее поле высотой 500 пикселей. Я использовал FutureBuilder для этого, но есть ошибка в прокрутке, при прокрутке вниз и повторной прокрутке вверх происходит резкий скачок.

Шаги для воспроизведения:

  1. Просто создайте новое приложение Flutter

  2. Вставьте приведенный ниже код в main.dart

     import 'package:flutter/material.dart';
    
    void main() {
      runApp(MyApp());
    }
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Flutter Demo',
          theme: ThemeData(
            primarySwatch: Colors.blue,
            visualDensity: VisualDensity.adaptivePlatformDensity,
          ),
          home: Scaffold(
            body: ListView(
              children: <Widget>[
                FutureBuilder(
                  future: new Future.delayed(const Duration(seconds: 3), () => 'whatevs'),
                  builder: (context, snapshot) {
                    if (snapshot.hasData) {
                      return Container(width: 200, height: 500, color: Colors.blue);
                    } else {
                      return Container(width: 200, height: 200, color: Colors.grey);
                    }
                  },
                ),
                Container(width: 200, height: 500, color: Colors.green),
                Container(width: 200, height: 500, color: Colors.orange),
                Container(width: 200, height: 500, color: Colors.red),
              ],
            ),
          ),
        );
      }
    }
      
  3. Подождите 3 секунды

  4. Прокрутите вниз

  5. Прокрутите еще раз вверх и увидите переход в зеленом поле

Как я могу удалить этот нежелательный скачок и сделать прокрутку плавной?

Ответ №1:

Используйте init метод, а не Future в Build Widget . Виджет будет создаваться каждый раз, когда какое-либо событие, подобное вам, срабатывает при касании экрана. Это причина перехода.

 import 'package:flutter/material.dart';
    
    void main() {
      runApp(MyApp());
    }
    
    class MyApp extends StatefulWidget {
      @override
      _MyAppState createState() => _MyAppState();
    }
    
    class _MyAppState extends State<MyApp> {
      bool loaded = false;
    
      @override
      void initState() {
        // TODO: implement initState
        super.initState();
        Future.delayed(Duration(seconds: 3)).then((value) => {
              //Do more things
              setState(() {
                loaded = true;
              })
            });
      }
    
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Flutter Demo',
          theme: ThemeData(
            primarySwatch: Colors.blue,
            visualDensity: VisualDensity.adaptivePlatformDensity,
          ),
          home: Scaffold(
            body: ListView(
              children: <Widget>[
                loaded
                    ? Container(width: 200, height: 500, color: Colors.blue)
                    : Container(width: 200, height: 200, color: Colors.grey),
                Container(width: 200, height: 500, color: Colors.green),
                Container(width: 200, height: 500, color: Colors.orange),
                Container(width: 200, height: 500, color: Colors.red),
              ],
            ),
          ),
        );
      }
    }