首页 > 解决方案 > Flutter:删除/重新创建小部件时 UniqueKey 不起作用

问题描述

情况: 在我的应用程序中,我有输入卡(带有类似滑块),通过单击按钮显示/隐藏。

问题: 当我编辑滑块的值,然后再次隐藏和取消隐藏时,该值丢失。

我尝试使用 UniqueKey() 但它没有解决问题。

对我不起作用的解决方法是将值存储在其他地方并将其作为初始值传递给滑块。这是因为状态中的变量不仅仅是我必须保留的滑块值。

在 Dartpad 上运行

import 'package:flutter/material.dart';

final _someKey = UniqueKey();

void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) => MaterialApp(home: MyHomePage());
}
class MyHomePage extends StatefulWidget {
  MyHomePage();
  @override
  _MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) => Scaffold(
      appBar: AppBar(title: Text("Problem: UniqueKey not working")),
      body: ContentHider(
        child: Column(children: [
          // This Slider DOES change when hiding/unhiding
          // This Slider SHOULDN'T change
          CustomWidget(
            key: _someKey,
          ),
        ]),
      ));
}

// When pressing the button the "child" gets rendered / not rendered
class ContentHider extends StatefulWidget {
  final Widget child;
  ContentHider({this.child});
  @override
  _ContentHiderState createState() => _ContentHiderState();
}

class _ContentHiderState extends State<ContentHider> {
  bool hidden = false;
  @override
  Widget build(BuildContext context) => Center(
        child: Column(
          children: [
            RaisedButton(
              onPressed: () {
                if (hidden == false)
                  setState(() => hidden = true);
                else
                  setState(() => hidden = false);
              },
              child: Text("Hide/Unhide"),
            ),
            hidden ? Container() : widget.child
          ],
        ),
      );
}

// StatfulWidget which contains changable content -> Slider
class CustomWidget extends StatefulWidget {
  CustomWidget({Key key}) : super(key: key);
  @override
  _CustomWidgetState createState() => _CustomWidgetState();
}

class _CustomWidgetState extends State<CustomWidget> {
  double _currentSliderValue = 0.0;
  @override
  Widget build(BuildContext context) {
    return Card(
      color: Color(0xFFACFFBC),
      child: Slider(
      value: _currentSliderValue,
      min: 0,
      max: 100,
      label: _currentSliderValue.round().toString(),
      onChanged: (double value) {
        setState(() {
          _currentSliderValue = value;
        });
      },
      ),
    );
  }
}

标签: flutterdartstate

解决方案


您可以在下面复制粘贴运行完整代码
在这种情况下,您不需要密钥
您可以使用Visibility和设置maintainState: true
代码片段

Visibility(
            visible: hidden, maintainState: true, child: widget.child)

工作演示

在此处输入图像描述

完整代码

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) => MaterialApp(home: MyHomePage());
}

class MyHomePage extends StatefulWidget {
  MyHomePage();
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) => Scaffold(
      appBar: AppBar(title: Text("Problem: UniqueKey not working")),
      body: ContentHider(
        child: Column(children: [
          // This Slider DOES change when hiding/unhiding
          // This Slider SHOULDN'T change
          CustomWidget(),
        ]),
      ));
}

// When pressing the button the "child" gets rendered / not rendered
class ContentHider extends StatefulWidget {
  final Widget child;
  ContentHider({this.child});
  @override
  _ContentHiderState createState() => _ContentHiderState();
}

class _ContentHiderState extends State<ContentHider> {
  bool hidden = false;
  @override
  Widget build(BuildContext context) => Center(
        child: Column(
          children: [
            RaisedButton(
              onPressed: () {
                if (hidden == false)
                  setState(() => hidden = true);
                else
                  setState(() => hidden = false);
              },
              child: Text("Hide/Unhide"),
            ),
            Visibility(
                visible: hidden, maintainState: true, child: widget.child)
          ],
        ),
      );
}

// StatfulWidget which contains changable content -> Slider
class CustomWidget extends StatefulWidget {
  CustomWidget({Key key}) : super(key: key);
  @override
  _CustomWidgetState createState() => _CustomWidgetState();
}

class _CustomWidgetState extends State<CustomWidget> {
  double _currentSliderValue = 0.0;
  @override
  Widget build(BuildContext context) {
    return Card(
      color: Color(0xFFACFFBC),
      child: Slider(
        value: _currentSliderValue,
        min: 0,
        max: 100,
        label: _currentSliderValue.round().toString(),
        onChanged: (double value) {
          setState(() {
            _currentSliderValue = value;
          });
        },
      ),
    );
  }
}

推荐阅读