如何在使用 ListView.builder 时动态更新特定列表视图项?

Gam*_*ads 6 listview dart flutter

我正在 Flutter 中制作列表视图。我想在长按项目时更新项目的属性。

以下是完整代码:

// main.dart
import 'package:LearnFlutter/MyList.dart';
import 'package:flutter/material.dart';
import 'MyList.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'List Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: MyHomePage(title: 'My list demo'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
  final String title;
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: MyList(),
    );
  }
}

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

class Item {
  Item(String name, bool selected, Color color) {
    _name = name;
    _selected = selected;
    _color = color;
  }

  String _name;
  bool _selected;
  Color _color;

  String getName() {
    return _name;
  }

  bool isSelected() {
    return _selected;
  }

  void toggleSelected() {
    _selected = !_selected;
  }

  void setColor(Color color) {
    _color = color;
  }

  Color getColor() {
    return _color;
  }
}

class MyList extends StatefulWidget {
  @override
  _CardyState createState() => new _CardyState();
}

class _CardyState extends State<MyList> {
  @override
  Widget build(BuildContext context) {
    var itemsList = [
      Item('My item1', false, Colors.grey[200]),
      Item('My item2', false, Colors.grey[200]),
      Item('My item3', false, Colors.grey[200]),
    ];

    return ListView.builder(
      itemCount: itemsList.length,
      itemBuilder: (context, index) {
        return Card(
          child: ListTile(
            leading: Icon(Icons.train),
            title: Text(itemsList[index].getName()),
            trailing: Icon(Icons.keyboard_arrow_right),
            tileColor: itemsList[index].getColor(),
            selected: itemsList[index].isSelected(),
            onLongPress: () {
              toggleSelection(itemsList[index]);
            },
          ),
        );
      },
    );
  }

  void toggleSelection(Item item) {
    print(item.getName() + ' long pressed');
    setState(() {
      item.toggleSelected();
      if (item.isSelected()) {
        item.setColor(Colors.blue[200]);
      } else {
        item.setColor(Colors.grey[200]);
      }
    });
  }
}
Run Code Online (Sandbox Code Playgroud)

问题:
在上面的代码中toggleSelection,长按事件被调用。但该项目的颜色没有更新。我究竟做错了什么?

Unb*_*ble 4

它无法正常运行的主要原因是您的班级没有状态Item,因此您没有重新构建/更新任何内容。如果您想在类中处理它,那么您需要将其扩展到ChangeNotifier. 您还需要使用ChangeNotifierProvider,请查看文档以获取帮助:https://flutter.dev/docs/development/data-and-backend/state-mgmt/simple

您将需要提供程序包: https: //pub.dev/packages/provider

类别项目

class Item extends ChangeNotifier {
  Item(String name, Color color) {
    _name = name;
    _color = color;
  }

  int selectedIndex; // to know active index
  String _name;
  Color _color;

  String getName() {
    return _name;
  }

  void toggleSelected(int index) {
    selectedIndex = index;

    notifyListeners(); // To rebuild the Widget
  }

  void setColor(Color color) {
    _color = color;

    notifyListeners();
  }

  Color getColor() {
    return _color;
  }
}
Run Code Online (Sandbox Code Playgroud)

小部件列表

class MyList extends StatefulWidget {
  @override
  _CardyState createState() => new _CardyState();
}

class _CardyState extends State<MyList> {
  @override
  Widget build(BuildContext context) {
    final items = Provider.of<Item>(context); // Accessing the provider

    bool selected = false; // default val. of bool

    var itemsList = [
      Item('My item1', Colors.grey[200]),
      Item('My item2', Colors.grey[200]),
      Item('My item3', Colors.grey[200]),
    ];

    return ListView.builder(
      itemCount: itemsList.length,
      itemBuilder: (context, index) {
        return Card(
          child: ListTile(
            leading: Icon(Icons.train),
            title: Text(itemsList[index].getName()),
            trailing: Icon(Icons.keyboard_arrow_right),
            tileColor: items.selectedIndex == index
                ? items.getColor()
                : Colors.grey[200],
            selected: items.selectedIndex == index ? true : false,
            onLongPress: () {
              setState(() => selected = !selected);

              items.toggleSelected(index);

              if (selected) {
                items.setColor(Colors.red);
              }
            },
          ),
        );
      },
    );
  }
}
Run Code Online (Sandbox Code Playgroud)