0

我正在MyButton通过编写ElevatedButton将包含一个Text小部件作为子部件来创建一个自定义按钮小部件。它有一个布尔isLoading属性,用于配置要构建的 Button 的类型。当isLoading = true它将返回一个宽度与此加载按钮构建之前提供的文本宽度相同的灰色加载按钮时。我的问题是如何在 setState 调用或再次调用 build 方法之前获取widthText小部件,以便我可以使用它width来创建相同大小的加载按钮?

在使用子小部件构建默认按钮后,将始终调用加载按钮Text。(即isLoading仅当小部件不是最初重建时才为真)。

这是代码:


class MyButton extends StatefulWidget {
  final String text;
  final bool isLoading;
  final VoidCallback onPressed;
  MyButton({Key key, @required this.text, @required this.isLoading, this.onPressed}) : super(key: key);
  @override
  State<StatefulWidget> createState() => _MyButtonState();
}

class _MyButtonState extends State<MyButton> {
  double _width; // Width of the [Text] child widget that will be used to get the [Container] of same width for loading button

  @override
  void initState() {
    super.initState();
    _width = 150;
  }

  @override
  void didUpdateWidget(covariant MyButton oldWidget) {
    super.didUpdateWidget(oldWidget);
    /*
    Calculate the width....
     */
  }

  @override
  Widget build(BuildContext context) {
    // I want to get the width of this child
    Widget child = Text(
      widget.text,
      style: TextStyle(color: Colors.black),
    );
    if (widget.isLoading) {
      child = Container(
        height: 60,
        width: _width, // this should be same as [Text] width
        color: Colors.grey,
      );
    }
    return ElevatedButton(
      child: child,
      onPressed: !widget.isLoading ? widget.onPressed : null,
      style: ButtonStyle(
        backgroundColor: MaterialStateProperty.all<Color>(
          !widget.isLoading ? Colors.red : Colors.grey,
        ),
      ),
    );
  }
}

这是我想做的演示,但按钮的大小isLoading = true现在是绝对的。

我检查了其他帖子和问题,但找不到有用的方法来解决我的用例。使用GlobalKey是一种解决方案,但不是推荐的方法,使用RenderObject我无法解决这个问题,因为在这种情况下,我们只能获得父级的固有高度和宽度。

我认为除了使用 GlobalKey 和 RenderObject 之外,可能还有其他方法可以做到这一点。

4

2 回答 2

1

而不是为此创建一个容器,我更希望您只是隐藏文本,以便按钮的大小与以前的大小相同。试试下面的代码:

Widget build(BuildContext context) {
    return ElevatedButton(
      child: Opacity(
        opacity: !widget.isLoading ? 1 : 0,
        child: Text(
          widget.text,
          style: TextStyle(color: Colors.black),
        ),
      ),
      onPressed: !widget.isLoading ? widget.onPressed : null,
      style: ButtonStyle(
        backgroundColor: MaterialStateProperty.all<Color>(
          !widget.isLoading ? Colors.red : Colors.grey,
        ),
      ),
    );
  }
于 2021-12-30T17:43:41.047 回答
0

我们可以使用 add postFrameCallbackto WidgetBinding 实例从上下文中获取小部件的大小postFrameCallback

注意:这可能不是有效的方法。

这是在我的案例中有效的代码。


  @override
  void initState() {
    super.initState();
    getWidth();
    _width = _width ?? 150;
  }

  void getWidth() {
    WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
      if (context?.size is Size) {
        _width = context.size.width;
        print(context.size.toString());
      }
    });
  }

  @override
  void didUpdateWidget(covariant MyButton oldWidget) {
    getWidth();
    super.didUpdateWidget(oldWidget);
  }
于 2021-12-30T17:54:12.200 回答