在安全区域中获取小部件高度的正确方法



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

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

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

如果您只需要安全区域顶部填充,而不需要安全区域小部件子级的高度:

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

或(不带上下文对象(

final safePadding = WidgetsBinding.instance.window.padding.top;

如果您需要应用栏:

final appBarHeight = AppBar().preferredSize.height;

在这种情况下,您始终可以使用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

颤振 2.5

在小部件的顶层添加此内容...您可以获得准确的安全区域高度。

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

颤振 2.5

有类似的挑战。

艰难地学到了:

不要将 SafeArea 包装在 main.dart 应用程序中,而是使用 SafeArea Widget 包装您的脚手架(最好创建一个带有包装 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文档中找到此信息。

但是,如果您在不包装安全区域的情况下计算高度,您将获得顶部和底部的填充,从而可以在没有安全区域的情况下获得剩余高度

例:

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

要得到SafeArea的大小,你需要封装在一个LayoutBuilder中,并使用constraints.maxHeight

看看你自己修改的例子:

I/颤振 (20405(:全屏高度:683.4285714285714
I/颤振 (20405(: 屏幕高度: 683.4285714285714
I/颤振 (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,
        );
      },
    );
  }
}

根据颤振,"窗口"已被弃用,不应使用。通过View.of(context(从上下文中查找当前的FlutterView,或者直接咨询PlatformDispatcher。已弃用,为即将推出的多窗口支持做准备。此功能在 v3.7.0-32.0.pre 之后已弃用。

  final safepadding = WidgetsBinding.instance.window.padding.top ;

  final safepadding = WidgetsBinding.instance.platformDispatcher.implicitView!.padding.top;

相关内容

最新更新