繁体   English   中英

Flutter Item ExpansionPanelList 不会改变状态

[英]Flutter Item ExpansionPanelList doesn't change state

我正在尝试从 API 检索数据,这很好用。

之后,我想在 ExpansionPanelList 中显示我的数据,该列表由一种方法构建:

class _CartaPageState extends State<CartaPage> {

  
  @override
  Widget build(BuildContext context) {
    // Nos suscribimos al provider
    final productoService = Provider.of<ProductoService>(context);
    final List<Producto> productos = productoService.productos; 
    _productosItems = productosToItem(productos);
    return Scaffold(
      body: Container(
        height: double.infinity,
        width: double.infinity,
        child: ListView(
          children: [
            ExpansionPanelList(
              animationDuration: Duration(milliseconds: 300),
              expansionCallback: (int index, bool isExpanded) {
                setState(() {
                  _productosItems[index].isExpanded = !isExpanded;
                  //productosItems[index].isExpanded = !productosItems[index].isExpanded;
                });
              },
              //children: productosToItem(productoService.entrantes).map<ExpansionPanel>((Item item) {
              children: _productosItems.map<ExpansionPanel>((Item item) {
                return ExpansionPanel(
                  headerBuilder: (context, isExpanded) {
                    return ListTile(
                      title: Text(item.headerValue),
                    );
                  },
      ................

数据显示完美,但状态在我的 ItemModel 上没有刷新,我认为问题是因为每次触摸面板列表时小部件都会重绘,从 API 检索(再次)数据并且永远不会改变状态。

我该如何解决?

先感谢您

编辑: CartaPage 被包装:

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MultiProvider(
      providers: [
        ChangeNotifierProvider(create: (_) => ProductoService()),
      ],
      child: MaterialApp(
        debugShowCheckedModeBanner: false,
        title: 'Material App',
        home: CartaPage()
      ),
    );
  }
}

编辑2:

我同意我正在失去状态,这是将Product转换为Item的方法:

List<Item> productosToItem(List<Producto> productos) {
  return List.generate(productos.length, (index) {
    return Item(
      headerValue: productos[index].tipo,
      expandedValue: productos[index].nombre,
    );
  });
}

ExpansionPanel是否将其isExpanded设置为item.isExpanded

您可以从productosToItem()生成的任何内容中获得isExpanded状态。

当您调用setState时,您将一个新构建setState队列,它将再次调用productosToItem() 在不知道该方法的作用的情况下,我无能为力。

我建议您查看productosToItem以及为什么它没有将isExpanded设置为正确的值。

如果_productosItems[index].isExpanded不是一个二传手,我想你正在失去状态。

编辑 1:

您可以创建一个内部状态列表来保持扩展状态:

class Item {
  Item({
    this.expandedValue,
    this.headerValue,
    this.producto,
    this.isExpanded = false,
  });

  String expandedValue;
  String headerValue;
  Producto producto; // <------------- ADDED
  bool isExpanded;
}

class _CartaPageState extends State<CartaPage> {
  Map<Producto, bool> expanded = {}; // <------------- ADDED

  @override
  Widget build(BuildContext context) {
    // Nos suscribimos al provider
    final productoService = Provider.of<ProductoService>(context);
    final List<Producto> productos = productoService.productos;
    // NOTE: ----------- converted to a local variable
    final _productosItems = productosToItem(productos);
    return Scaffold(
      body: Container(
        height: double.infinity,
        width: double.infinity,
        child: ListView(
          children: [
            ExpansionPanelList(
              key: ValueKey(productos.length),  // <------------- ADDED
              animationDuration: Duration(milliseconds: 300),
              expansionCallback: (int index, bool isExpanded) {
                // NOTE: ----------- updated
                final producto = productos[index];
                setState(() {
                  expanded[producto] = !isExpanded;
                });
              },
              children: _productosItems.map<ExpansionPanel>((Item item) {
                return ExpansionPanel(
                  isExpanded: expanded[item.producto], // <------------- ADDED
                  canTapOnHeader: true,
                  headerBuilder: (context, isExpanded) {
                    return ListTile(
                      title: Text(item.headerValue),
                    );
                  },
                  body: ListTile(
                    title: Text(item.expandedValue),
                  ),
                );
              }).toList(),
            ),
          ],
        ),
      ),
    );
  }

  List<Item> productosToItem(List<Producto> productos) {
    // keep a list of previous map
    final toRemove = Map<Producto, bool>.from(expanded);
    final items = List.generate(productos.length, (index) {
      final producto = productos[index];
      // set initial expanded state
      expanded.putIfAbsent(producto, () => false);
      // the item will be retained
      toRemove.remove(producto);
      return Item(
        headerValue: producto.tipo,
        expandedValue: producto.nombre,
        producto: producto,
        isExpanded: expanded[producto],
      );
    });
    if (toRemove.isNotEmpty) {
      // cleanup unused items
      expanded.removeWhere((key, _) => toRemove.containsKey(key));
    }
    return items;
  }
}

key: ValueKey(productos.length),是必需的,因为ExpansionPanelList对神奇地出现或消失的项目表现key: ValueKey(productos.length),奇怪。

暂无
暂无

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

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