在SafeArea中获取小部件高度的正确方法

Eug*_*ene 9 flutter

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

I/flutter (19253): full height: 976.0
I/flutter (19253): safe height: 976.0
Run Code Online (Sandbox Code Playgroud)

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

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

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,
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

Khe*_*rel 69

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

var safePadding = MediaQuery.of(context).padding.top;
Run Code Online (Sandbox Code Playgroud)

  • 如果您还需要AppBar高度`AppBar().preferredSize.height` (5认同)
  • 如果您没有“context”,您可以使用“WidgetsBinding.instance.window.padding.top”。 (2认同)

pet*_*s J 14

颤振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;
Run Code Online (Sandbox Code Playgroud)

诀窍是,如果您的整个 main.app 子级都用 SafeArea 包装,则padding.toppadding.bottom将始终保持为 0,因为这就是 SafeArea 的工作原理 - 它使 padding 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
Run Code Online (Sandbox Code Playgroud)


Doc*_*Doc 13

您总是可以LayoutBuilder在这种情况下使用。

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

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


Ked*_*kar 11

颤振 1.7.4

将此添加到 Widget 的顶层...您可以获得确切的 SafeArea 高度。

final availableHeight = MediaQuery.of(context).size.height -
    AppBar().preferredSize.height -
    MediaQuery.of(context).padding.top -
    MediaQuery.of(context).padding.bottom;
Run Code Online (Sandbox Code Playgroud)


小智 7

要获取 的大小SafeArea,您需要封装在 a 内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,
        );
      },
    );
  }
}
Run Code Online (Sandbox Code Playgroud)