高度更新时 Flutter Wrap 小部件渲染出现故障

问题描述 投票:0回答:2

我正在 Flutter 中创建一个表单(不使用

Form
小部件),用户可以在其中添加任意数量的项目(处理),这些项目在
InputChip
小部件中呈现为
Wrap
小部件列表。

该表单使用一个按钮(

AddButton
小部件)来打开一个表单对话框,该对话框本身返回添加到 selectedItems:

的新创建的项目(处理)
class TreatmentsWidget extends StatefulWidget {
  const TreatmentsWidget({super.key, required this.selectedItems});

  final List<Treatment> selectedItems;

  @override
  State<TreatmentsWidget> createState() => _TreatmentsWidgetState();
}

class _TreatmentsWidgetState extends State<TreatmentsWidget> {
  @override
  Widget build(BuildContext context) {
    var chips = widget.selectedItems.map(
      (item) {
        return InputChip(
          label: Text('${item.name} - ${item.frequency}/${item.frequencyUnit.name})',
        );
      },
    ).toList();

    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Wrap(
          children: chips,
        ),
        AddButton(onPressed: () {
          showDialog(
              context: context,
              builder: (BuildContext context) {
                return const TreatmentDialog();
              }).then((value) {
            if (value != null) {
              Treatment item = value;
              setState(() {
                widget.selectedItems.add(item);
              });
            }
          });
        }),
      ],
    );
  }
}

由于某种原因,当将新项目添加到 selectedItem 并且该项目溢出当前行时,不会重新计算布局,从而导致

Wrap
小部件溢出按钮:

但是,一旦用户滚动(整个屏幕内容都在

SingleChildScrollView
内),布局就会重新计算,并且
Wrap
会占用正确的空间量:

添加新项目时如何强制重画以防止出现此故障?

flutter visual-glitch
2个回答
0
投票

问题似乎是,当

Column
的一个子尺寸发生变化时,它不会在当前帧上重新计算其尺寸。

每当

Column
发生变化时,我最终都会强制使用
ValueKey
重建
chips.length

class _TreatmentsWidgetState extends State<TreatmentsWidget> {
  @override
  Widget build(BuildContext context) {
    var chips = ...;

    return Column(
      key: ValueKey(chips.length),
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Wrap(
          children: chips,
        ),
        AddButton(...),
      ],
    );
  }
}

我仍然对更清洁的解决方案感兴趣(如果存在)。对于这种情况,使用提供商似乎有些过分了。


0
投票

我遇到了与您的问题中描述的类似的问题,它源于 Ink 小部件。我无法调查为什么会出现这种行为。您遇到此问题是否可能是因为 Wrap 内代码中的某处存在 Ink 小部件?

我的代码结构示例

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        OtherWidget(),
        Expanded(
          child: SingleChildScrollView(
            child: Wrap(
              spacing: 8 * 2,
              runSpacing: 8 * 2,
              clipBehavior: Clip.antiAlias,
              children: [
                Ink(),
                Ink(),
                Ink(),
                Ink(),
                Ink(),
                Ink(),
                Ink(),
                Ink(),
                Ink(),
              ],
            ),
          ),
        ),
        SomeOtherWidget(),
      ],
    );
  }
}

解决方案

我刚刚用 Container() 替换了 Ink()。

PD:希望这有帮助

© www.soinside.com 2019 - 2024. All rights reserved.