【问题标题】:How to update a single item of a SliverList in Flutter?如何在 Flutter 中更新 SliverList 的单个项目?
【发布时间】:2021-10-14 22:14:59
【问题描述】:

你们知道如何在不调用 setState() 的情况下更新 sliver 列表的单个项目吗?

在我的情况下,我有一个 SliverList,我想单击一个项目并更改它的颜色,使用 setState() 的问题是它以一种不流畅的方式重建整个 UI,并且还弄乱了自定义滚动位置。

有趣的是,这种 SliverList 行为在使用普通 ListView 时不会发生,当在 ListView 上使用 setState() 时,加载是平滑的,并且不会破坏滚动状态。看起来 ListView 可以比 SliverList 更好地隐式处理状态。

但由于我有一个自定义滚动,我不能使用 ListVew 它必须是 SliverList

有什么选择吗?提供者?通知者?溪流 ?集团?

【问题讨论】:

  • 您当前是否在使用任何状态管理库?您可能有一个在您的状态管理方法中工作的实现。另外,请分享您的代码以及您迄今为止尝试过的内容。
  • 如果你想在 UI 上反映变化,你可以调用 setState 或 stateManagement 属性,全局键也用于改变值。
  • setState() 不是 SliverList 的选项,因为屏幕的重新加载不流畅并且会弄乱 CustomScrollView 的位置。关于 UI 状态管理到目前为止我使用的是 ChangeNotifier 结合 AnimatedBuilder(非常简单的方法并且工作正常),但是,使用 Sliver List 看起来我不能这样做,我会尝试提供一些代码

标签: flutter


【解决方案1】:

好吧,毕竟,我可以在 SliverList 的每个项目中使用一个简单的 ChangeNotifier 和一个 AnimatedBuilder 来解决我的需求,我将发布一些解决方案的高级代码 - 它可以满足我的需要!

class ChangeColorSliverListItemNotifier  extends ChangeNotifier {

  int index;
  Color current_label_color;



  ChangeColorSliverListItemNotifier()
  {
    this.current_label_color = Colors.white;
  }


  void onTap(int selected_index)
  {
        index = selected_index;
        
        this.current_label_color = Colors.yellow;
        notifyListeners();
  }



}



// code block inside SliverList items binding- changing only the color of the selected Widget

SliverList(
delegate: SliverChildBuilderDelegate((context, index)
{

return GestureDetector(
onTap:() {

  changeColorSliverListItemNotifier.onTap(index);

},
child:AnimatedBuilder(
    animation: changeColorSliverListItemNotifier,
    builder: (_, __) =>
        Row(children:[

            Container(
                margin: EdgeInsets.only(right:8),
                child: Icon(Icons.edit,color:changeColorSliverListItemNotifier.index==index?changeColorSliverListItemNotifier.current_label_color:default_color,size: 20,)
      ),
      ])
    )
)   

....

【讨论】:

    【解决方案2】:

    以防万一你想使用Riverpod state management library,我做了以下。

    
    class SliverScreen extends StatelessWidget {
      const SliverScreen({Key? key}) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: CustomScrollView(
            physics: const BouncingScrollPhysics(),
            slivers: [
              _appBar(),
              _list(),
            ],
          ),
        );
      }
    
      SliverFixedExtentList _list() {
        return SliverFixedExtentList(
          delegate: SliverChildBuilderDelegate(
            (context, index) => ListItem(index: index),
          ),
          itemExtent: 100,
        );
      }
    
      SliverAppBar _appBar() {
        return SliverAppBar(
          title: Text("Slivering..."),
          backgroundColor: Colors.teal[900],
          expandedHeight: 200,
          pinned: true,
          stretch: true,
          flexibleSpace: FlexibleSpaceBar(
            background: Container(
              decoration: BoxDecoration(
                gradient: LinearGradient(
                  colors: [
                    Colors.teal[100]!,
                    Colors.teal[600]!,
                  ],
                ),
              ),
            ),
          ),
        );
      }
    }
    
    final colorStateProvider = StateProvider.family<Color, int>((ref, key) {
      return Colors.blue[100]!;
    });
    
    class ListItem extends HookConsumerWidget {
      final int index;
      const ListItem({Key? key, required this.index}) : super(key: key);
    
      @override
      Widget build(BuildContext context, WidgetRef ref) {
        final colorState = ref.watch(colorStateProvider(index));
        return InkWell(
          onTap: () => colorState.state = Colors.blue,
          child: Container(
            color: colorState.state,
            child: Center(
              child: Text("Item $index"),
            ),
          ),
        );
      }
    }
    

    如果您单击一个项目,它会更新颜色而不重建整个列表,只重建项目本身。

    【讨论】:

      猜你喜欢
      • 2019-05-27
      • 2020-06-17
      • 2020-07-10
      • 2021-06-02
      • 2020-12-18
      • 1970-01-01
      • 2023-04-01
      • 2020-06-27
      • 2021-06-29
      相关资源
      最近更新 更多