簡體   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