首页 > 解决方案 > Flutter Stack Widget:将层的大小绑定到底层的大小

问题描述

所以我有一张带有列的卡片(动态大小)。我想在整个卡片上显示一个覆盖(半透明+图标),而不改变卡片的大小。

我使用 Stack 小部件编写了一个示例。在 DartPad 上运行

问题是,叠加层应该适应下层内容的大小。但是 Overlay 是如何知道另一层的大小的呢?

double.infinity不行,因为卡片的大小不固定也不能固定,因为内容有动态大小。

Card(
      child: Stack(
        children: [
          // Content
          Padding(
            padding: EdgeInsets.all(10),
            child: Column(mainAxisSize: MainAxisSize.min, children: [
              // Content of dynamic size
              Text("q23123"),
              Text("q23123"),
              Text("q23123"),
              RaisedButton(
                child: Text("Display Overlay"),
                onPressed: (() {
                  if (_showOverlay == false) {
                    setState(() {
                      _showOverlay = true;
                    });
                  }
                }),
              ),
            ]),
          ),
          // Overlay
          _showOverlay == true
              ? Container(
                  height: double.infinity, // Overlay is too big -> should adabt to
                  width: double.infinity, // the size of the layer underneath
                  decoration: BoxDecoration(
                    gradient: LinearGradient(
                      begin: Alignment.centerLeft,
                      end: Alignment.centerRight,
                      colors: [Colors.transparent, Colors.red],
                    ),
                  ),
                )
              : Container( // Overlay deactivated
                  height: 0,
                  width: 0,
                ),
        ],
      ),
      color: Colors.blue,
    ))

标签: flutterdartflutter-layout

解决方案


您可以在下面复制粘贴运行完整代码
在这种情况下,您可以使用GlobalKey获取yourRenderBox.size
代码片段

class _MyHomePageState extends State<MyHomePage> {
  bool _showOverlay = false;
  GlobalKey _key = GlobalKey();

  Size _getSizes() {
    final RenderBox yourRenderBox = _key.currentContext.findRenderObject();
    return yourRenderBox.size;
  }

  @override
  Widget build(BuildContext context) {
   ...
          Padding(
            key: _key,
          ...
          // Overlay
          _showOverlay == true
              ? Container(
                  height: _getSizes().height,
                  width: _getSizes().width,

工作演示

在此处输入图像描述

完整代码

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Problem'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  bool _showOverlay = false;
  GlobalKey _key = GlobalKey();

  Size _getSizes() {
    final RenderBox yourRenderBox = _key.currentContext.findRenderObject();
    return yourRenderBox.size;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: Center(
            child: Card(
      child: Stack(
        children: [
          // Content
          Padding(
            key: _key,
            padding: EdgeInsets.all(10),
            child: Column(mainAxisSize: MainAxisSize.min, children: [
              // Content of dynamic size
              Text("q23123"),
              Text("q23123"),
              Text("q23123"),
              RaisedButton(
                child: Text("Display Overlay"),
                onPressed: (() {
                  if (_showOverlay == false) {
                    setState(() {
                      _showOverlay = true;
                    });
                  }
                }),
              ),
            ]),
          ),
          // Overlay
          _showOverlay == true
              ? Container(
                  height: _getSizes().height,
                  width: _getSizes().width,
                  decoration: BoxDecoration(
                    gradient: LinearGradient(
                      begin: Alignment.centerLeft,
                      end: Alignment.centerRight,
                      colors: [Colors.transparent, Colors.red],
                    ),
                  ),
                )
              : Container(
                  // Overlay deactivated
                  height: 0,
                  width: 0,
                ),
        ],
      ),
      color: Colors.blue,
    )));
  }
}

推荐阅读