颤振问题:滚动时ListView重建项目 [英] Flutter issue: listview rebuilding items when scrolled

查看:63
本文介绍了颤振问题:滚动时ListView重建项目的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我滚动到列表视图的底部时,将重新构建底部的项目.当我滚动到顶部时,我的第一个项目被重建.第一项是带有可选筹码的卡,这种筹码在发生这种情况时会被取消选择.并且入口"动画也会重播.我该如何阻止呢?

When i scroll to the bottom of my listview, the bottom item gets rebuilt. The same when i scroll to the top, my first item gets rebuilt. The first item is a card with selectable chips that get unselected when this happens. And the "entrance" animation replays as well. How can i stop this?

这是基本代码(它使用了simple_animations包,我似乎无法重现芯片的问题,但我仍然遇到动画问题):

Here's the basic code (it uses the simple_animations package and I can't seem to reproduce the problem with the chips, but I still have problems with the animations):

import 'package:flutter/material.dart';
import 'package:simple_animations/simple_animations.dart';

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

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

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

class _MyHomePageState extends State<MyHomePage> {
  final List _chips = ['Hello', 'World'];

  List _selected = [];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Issue demo'),
      ),
      body: ListView(
        children: <Widget>[
          FadeIn(
            1,
            Card(
              child: Wrap(
                spacing: 10,
                children: List<Widget>.generate(
                  _chips.length,
                  (int index) => InputChip(
                      label: Text(_chips[index]),
                      selected: _selected.contains(_chips[index]),
                      onSelected: (selected) {
                        setState(() {
                          if (selected) {
                            _selected.add(_chips[index]);
                          } else {
                            _selected.remove(_chips[index]);
                          }
                        });
                      }),
                ),
              ),
            ),
          ),
          FadeIn(1.5, Text('A', style: Theme.of(context).textTheme.display4)),
          FadeIn(2, Text('Very', style: Theme.of(context).textTheme.display4)),
          FadeIn(2.5, Text('Big', style: Theme.of(context).textTheme.display4)),
          FadeIn(3, Text('Scroll', style: Theme.of(context).textTheme.display4)),
          FadeIn(3.5, Text('View', style: Theme.of(context).textTheme.display4)),
          FadeIn(4, Text('With', style: Theme.of(context).textTheme.display4)),
          FadeIn(4.5, Text('Lots', style: Theme.of(context).textTheme.display4)),
          FadeIn(5, Text('Of', style: Theme.of(context).textTheme.display4)),
          FadeIn(5.5,Text('Items', style: Theme.of(context).textTheme.display4)),
          FadeIn(
            6,
            Card(
              child: Text('Last item',
                  style: Theme.of(context).textTheme.display2),
            ),
          ),
        ],
      ),
    );
  }
}

class FadeIn extends StatelessWidget {
  final double delay;
  final Widget child;

  FadeIn(this.delay, this.child);

  @override
  Widget build(BuildContext context) {
    final tween = MultiTrackTween([
      Track("opacity")
          .add(Duration(milliseconds: 500), Tween(begin: 0.0, end: 1.0)),
      Track("translateX").add(
          Duration(milliseconds: 500), Tween(begin: 130.0, end: 0.0),
          curve: Curves.easeOut)
    ]);

    return ControlledAnimation(
      delay: Duration(milliseconds: (300 * delay).round()),
      duration: tween.duration,
      tween: tween,
      child: child,
      builderWithChild: (context, child, animation) => Opacity(
        opacity: animation["opacity"],
        child: Transform.translate(
            offset: Offset(animation["translateX"], 0), child: child),
      ),
    );
  }
}

您应该自己运行此程序以完全了解问题

You should run this yourself to fully understand the issue

推荐答案

要使ListView中的元素保持活动状态(向后滚动时不重新渲染),您应该使用参数 addAutomaticKeepAlives:true .并且ListView中的每个元素都必须是带有AutomaticKeepAliveClientMixin的StatefulWidget.

To keep elements in ListView alive (not re-render when scrolling back), you should user parameter addAutomaticKeepAlives: true . And every element in ListView have to be StatefulWidget with AutomaticKeepAliveClientMixin.

这是我为您编辑的代码

import 'package:flutter/material.dart';
import 'package:simple_animations/simple_animations.dart';

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

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

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

class _MyHomePageState extends State<MyHomePage> {
  final List _chips = ['Hello', 'World'];

  List _selected = [];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Issue demo'),
      ),
      body: ListView(
        addAutomaticKeepAlives: true,
        children: <Widget>[
          FadeIn(
            1,
            Card(
              child: Wrap(
                spacing: 10,
                children: List<Widget>.generate(
                  _chips.length,
                  (int index) => InputChip(
                      label: Text(_chips[index]),
                      selected: _selected.contains(_chips[index]),
                      onSelected: (selected) {
                        setState(() {
                          if (selected) {
                            _selected.add(_chips[index]);
                          } else {
                            _selected.remove(_chips[index]);
                          }
                        });
                      }),
                ),
              ),
            ),
          ),
          FadeIn(1.5, Text('A', style: Theme.of(context).textTheme.display4)),
          FadeIn(2, Text('Very', style: Theme.of(context).textTheme.display4)),
          FadeIn(2.5, Text('Big', style: Theme.of(context).textTheme.display4)),
          FadeIn(3, Text('Scroll', style: Theme.of(context).textTheme.display4)),
          FadeIn(3.5, Text('View', style: Theme.of(context).textTheme.display4)),
          FadeIn(4, Text('With', style: Theme.of(context).textTheme.display4)),
          FadeIn(4.5, Text('Lots', style: Theme.of(context).textTheme.display4)),
          FadeIn(5, Text('Of', style: Theme.of(context).textTheme.display4)),
          FadeIn(5.5,Text('Items', style: Theme.of(context).textTheme.display4)),
          FadeIn(
            6,
            Card(
              child: Text('Last item',
                  style: Theme.of(context).textTheme.display2),
            ),
          ),
        ],
      ),
    );
  }
}

class FadeIn extends StatefulWidget {
  final double delay;
  final Widget child;
  FadeIn(this.delay, this.child);
  _FadeInState createState() => _FadeInState();
}

class _FadeInState extends State<FadeIn> with AutomaticKeepAliveClientMixin {

  @override
  Widget build(BuildContext context) {
    final tween = MultiTrackTween([
      Track("opacity")
          .add(Duration(milliseconds: 500), Tween(begin: 0.0, end: 1.0)),
      Track("translateX").add(
          Duration(milliseconds: 500), Tween(begin: 130.0, end: 0.0),
          curve: Curves.easeOut)
    ]);

    return ControlledAnimation(
      delay: Duration(milliseconds: (300 * widget.delay).round()),
      duration: tween.duration,
      tween: tween,
      child: widget.child,
      builderWithChild: (context, child, animation) => Opacity(
        opacity: animation["opacity"],
        child: Transform.translate(
            offset: Offset(animation["translateX"], 0), child: child),
      ),
    );
  }

  @override
  // TODO: implement wantKeepAlive
  bool get wantKeepAlive => true;
}

这篇关于颤振问题:滚动时ListView重建项目的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆