【问题标题】:proper way to get widget height in SafeArea在 SafeArea 中获取小部件高度的正确方法
【发布时间】:2019-08-31 19:19:52
【问题描述】:

我正在尝试获取小部件的高度,但它打印的值相同

I/flutter (19253): full height: 976.0
I/flutter (19253): safe height: 976.0

我猜第二个值应该更小,因为 Container 放置在状态栏下方。我做错了什么? 我需要高度,因为在这个容器中将是 Wrap 小部件(实际上是 ReorderableWrap https://pub.dartlang.org/packages/reorderables#-readme-tab-),有 36 张卡片,3 行 x 12 张卡片,卡片高度必须是其容器的 1/3。

我没有找到好的可重排网格。但无论如何,我的问题是为什么安全区域中的 Container 与填满整个屏幕的 Container 具有相同的高度?

import 'package:flutter/material.dart';

void main() {
  runApp(_MyApp());
}

class _MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Scaffold(body: _Body()),
    );
  }
}

class _Body extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    print('full height: ${MediaQuery.of(context).size.height}');
    return Container(
      constraints: BoxConstraints.expand(),
      decoration: BoxDecoration(color: Colors.red),
      child: SafeArea(
        child: _SafeHeightWidget(),
      ),
    );
  }
}

class _SafeHeightWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    print('safe height: ${MediaQuery.of(context).size.height}');
    return Container(
      color: Colors.lightBlue,
    );
  }
}

【问题讨论】:

    标签: flutter flutter-layout


    【解决方案1】:

    我知道有正确的答案,但也许有人在寻找安全区域高度,而不是安全区域小部件子项的高度,而只是安全区域顶部填充:

    var safePadding = MediaQuery.of(context).padding.top;
    

    【讨论】:

    • 如果你还需要AppBar高度AppBar().preferredSize.height
    • 如果你没有context,你可以使用WidgetsBinding.instance.window.padding.top
    • @OvidiuUşvat 这对于了解如何在上下文之外访问大小非常有价值
    【解决方案2】:

    对于这种情况,您始终可以使用LayoutBuilder

    child: SafeArea(
            child: new LayoutBuilder(
                builder: (BuildContext context, BoxConstraints constraints) {
                  // constraints variable has the size info
                  return Container();
                }
            ),
          ),
    

    更多信息:https://www.youtube.com/watch?v=IYDVcriKjsw

    【讨论】:

      【解决方案3】:

      颤振 2.5

      在 Widget 的顶层添加它...您可以获得准确的 SafeArea 高度。

      final availableHeight = MediaQuery.of(context).size.height -
          AppBar().preferredSize.height -
          MediaQuery.of(context).padding.top -
          MediaQuery.of(context).padding.bottom;
      

      【讨论】:

        【解决方案4】:

        要获得SafeArea的大小,需要封装在LayoutBuilder中,并使用constraints.maxHeight

        看看你自己修改的例子:

        I/flutter (20405):全屏高度:683.4285714285714
        I/flutter (20405):屏幕高度:683.4285714285714
        I/flutter (20405):真实安全高度:659.4285714285714

        class _MyApp extends StatelessWidget {
          @override
          Widget build(BuildContext context) {
            return MaterialApp(
              debugShowCheckedModeBanner: false,
              home: Scaffold(body: _Body()),
            );
          }
        }
        
        class _Body extends StatelessWidget {
          @override
          Widget build(BuildContext context) {
            print('full Screen height: ${MediaQuery.of(context).size.height}');
            return Container(
              constraints: BoxConstraints.expand(),
              decoration: BoxDecoration(color: Colors.red),
              child: SafeArea(
                child: _SafeHeightWidget(),
              ),
            );
          }
        }
        
        class _SafeHeightWidget extends StatelessWidget {
          @override
          Widget build(BuildContext context) {
            return LayoutBuilder(
              builder: (context, constraints) {
                print('Screen height: ${MediaQuery.of(context).size.height}');
                print('Real safe height: ${constraints.maxHeight}');
                return Container(
                  color: Colors.lightBlue,
                );
              },
            );
          }
        }
        

        【讨论】:

          【解决方案5】:

          颤振 2.5

          遇到过类似的挑战。

          艰难地学习:

          不要将 SafeArea 包裹在 main.dart 应用程序中, 而是使用 SafeArea Widget 包裹您的 Scaffold(甚至更好地创建带有包裹 SafeArea 的 ReusableScaffold),然后您可以使用 SafeArea 下面的代码提取 MediaQuery 高度:

          var availableHeight = MediaQuery.of(context).size.height -
              AppBar().preferredSize.height -
              MediaQuery.of(context).padding.top -
              MediaQuery.of(context).padding.bottom;
          

          诀窍是,如果您的整个 main.app 子项都使用 SafeArea 包裹,则 padding.toppadding.bottom 将始终保持为 0,因为这就是 SafeArea 的工作方式 - 它填充 EdgeInsets.zero - 您可以在 SafeArea 文档中找到此信息。

          但是,如果您计算高度而不包裹 safeArea,您将获得顶部和底部的填充,这允许在不使用 SafeArea 的情况下获得剩余高度

          示例:

          I/flutter (12472): full height 712.0 -> full height
          I/flutter (12472): available height 618.5 -> remaining height minus safeArea & appBar
          I/flutter (12472): MediaQuery.of(context).padding.top 37.5 -> safeArea height
          I/flutter (12472): MediaQuery.of(context).padding.bottom 0.0 -> Im using android with 720 height, on iPhone X it would not zero
          I/flutter (12472): viewPadding EdgeInsets(0.0, 37.5, 0.0, 0.0) -> shows all padding insets
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2023-04-03
            • 2021-12-25
            • 2020-11-02
            • 2014-09-07
            • 2013-10-13
            • 1970-01-01
            • 2022-09-30
            • 1970-01-01
            相关资源
            最近更新 更多