【问题标题】:Flutter Slider not rebuilding inside of ExpansionPanelFlutter Slider 未在 ExpansionPanel 内部重建
【发布时间】:2020-04-08 04:30:10
【问题描述】:

我正在尝试在 ExpansionPanelList 中使用多个 ExpansionPanels 创建一个表单。
我最初使用initState 在页面中设置表单。

现在我遇到的主要问题是将Slider 小部件实现到ExpansionPanel 之一。 Slider 按钮 UI 不会在更改时更新,但滑块的值 _colorValue 是。

我认为问题在于 ExpansionPanel body 在重建时没有更新,但我不确定如何解决它。 我已经在没有真正帮助的情况下阅读了文档。

这是我的代码:

import ...

/// stores ExpansionPanel state information
class Panel {
  Panel({
    this.expandedValue,
    this.headerValue,
    this.isExpanded = false,
  });

  Widget expandedValue;
  String headerValue;
  bool isExpanded;
}

class AddReviewScreen extends StatefulWidget {
  static const String route = 'add_review_screen';
  @override
  _AddReviewScreenState createState() => _AddReviewScreenState();
}

class _AddReviewScreenState extends State<AddReviewScreen> {
  final _formKey = GlobalKey<FormState>();
  double _colorValue = 1.0;
  List<Panel> _panels;

  @override
  void initState() {
    super.initState();
    _panels = _getPanels();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        centerTitle: true,
        title: Text('Add Review', style: Theme.of(context).textTheme.display4),
        backgroundColor: kAppBarBackgroundColor,
      ),
      backgroundColor: kScaffoldBackgroundColor,
      body: SafeArea(
        child: SingleChildScrollView(
          child: Container(
            padding: EdgeInsets.all(8.0),
            child: Form(
              key: _formKey,
              child: _buildForm(),
            ),
          ),
        ),
      ),
    );
  }

  List<Panel> _getPanels() {
    return [
      Panel(...),
      Panel(
        headerValue: 'Sensory Features',
        expandedValue: Column(
          children: <Widget>[
            Slider(
              value: _colorValue,
              min: 0.0,
              max: 2.0,
              divisions: 20,
              onChanged: (double newValue) {
                setState(() {
                  _colorValue = newValue;
                  print(_colorValue);
                });
              },
            ),
            TextFormField(...),
            TextFormField(...),
            TextFormField(...),
          ],
        ),
      ),
    ];
  }

  Widget _buildForm() {
    return ExpansionPanelList(
      expansionCallback: (int index, bool isExpanded) {
        setState(() {
          _panels[index].isExpanded = !isExpanded;
        });
      },
      children: _panels.map<ExpansionPanel>((Panel panel) {
        return ExpansionPanel(
          headerBuilder: (BuildContext context, bool isExpanded) {
            return ListTile(
              title: Text(panel.headerValue),
            );
          },
          body: panel.expandedValue,
          isExpanded: panel.isExpanded,
        );
      }).toList(),
    );
  }
}

任何帮助将不胜感激!
如果有任何问题,请告诉我,我会尽力解答。

【问题讨论】:

    标签: flutter dart material-design


    【解决方案1】:

    问题和我想的一样,在body: panel.expandedValue 行。每当触发重建时,面板就会从 _panels 列表中重新绘制,因此会返回到它们的初始状态。

    我如何设法解决它是首先从_getPanels 的面板中提取每个expandedValue 到它们自己的单独函数中。然后,我将 ExpansionPanelList 的子项从动态 Map/List 重构为 ExpansionPanels 的静态列表,因为我知道列表的大小将来不会改变,因此没有理由动态功能。

    因此,基本上现在无论何时发生重建,UI 都不会回退到其初始状态。相反,它会更新提取的 Widget 函数中的“脏”值。

    这是我的解决方案:

      /// Construct the initial List of Panels.
      List<Panel> _getPanels() {
        return [
          Panel(
            headerValue: 'Panel 1',
            expandedValue: _panel1(),
            isExpanded: true,
          ),
          Panel(
            headerValue: 'Panel 2',
            expandedValue: _panel2(),
          ),
        ];
      }
    
      Function _expansionPanelHeaderBuilderCallback(String title) {
        return (BuildContext context, bool isExpanded) {
          return ListTile(
            title: Text(title),
          );
        };
      }
    
      Widget _buildForm() {
        return ExpansionPanelList(
          expansionCallback: (int index, bool isExpanded) {
            setState(() {
              _panels[index].isExpanded = !isExpanded;
            });
          },
          children: [
            ExpansionPanel(
              headerBuilder: _expansionPanelHeaderBuilderCallback(_panels[0].headerValue),
              body: _panel1(),
              isExpanded: _panels[0].isExpanded,
              canTapOnHeader: true,
            ),
            ExpansionPanel(
              headerBuilder:
                  _expansionPanelHeaderBuilderCallback(_panels[1].headerValue),
              body: _panel2(),
              isExpanded: _panels[1].isExpanded,
              canTapOnHeader: true,
            ),
          ],
        );
      }
    
      Widget _panel1() {
        return Padding(...);
      }
    
      Widget _panel2() {
        return Column(...);
      }
    
    

    如果找到更好的解决方案(我确信有),请在此处发布,我会将其标记为正确答案。

    【讨论】:

      猜你喜欢
      • 2020-10-23
      • 2019-12-15
      • 2018-12-21
      • 2019-11-25
      • 2021-11-19
      • 2020-07-25
      • 2020-06-17
      • 1970-01-01
      • 2020-03-28
      相关资源
      最近更新 更多