繁体   English   中英

颤振问题:滚动时ListView重建项目

[英]Flutter issue: listview rebuilding items when scrolled

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

这是基本代码(它使用了simple_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),
      ),
    );
  }
}

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

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

这是我为您编辑的代码

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;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM