如何在Flutter中呈现一个空的视图?

wn9m85ua  于 2022-12-05  发布在  Flutter
关注(0)|答案(9)|浏览(329)

如何在flutter中显示一个空视图,因为Widget.build不能返回null来指示没有要呈现的内容。

7qhs6swi

7qhs6swi1#

对于像我这样想知道什么是“正确的方式”来显示一个空的小部件的人来说,官方的Material代码库使用了这样的方法:

Widget build(BuildContext context) {
  return SizedBox.shrink();
}

SizedBox.shrink()是一个与ContainerMaterial不同的小部件,它没有背景或任何装饰。如果不受父约束的影响,它会将自己的大小调整到尽可能小的区域。

cnh2zyt3

cnh2zyt32#

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(

    );
  }
}

您也可以直接返回一个空的Container,完全避免使用Scaffold。但是如果这是您应用中唯一的主部件,这会导致黑屏。如果您想防止黑屏,可以设置Containercolor属性。
示例:

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.white // This is optional
    );
  }
}
8wigbo56

8wigbo563#

有很多可能的解决方案。比如
1.

Widget build(context) => SizedBox();
Widget build(context) => Container();
Widget build(context) => Scaffold();
sirbozc5

sirbozc54#

性能

容器= 166,173毫秒
尺寸箱收缩= 164,523毫秒
自己动手

main() async {
  testWidgets('test', (WidgetTester tester) async {
    await tester.pumpWidget( Container());
    final Stopwatch timer = new Stopwatch()..start();
    for (int index = 0; index < 5000000; index += 1) {
      await tester.pump();
    }
    timer.stop();
    debugPrint('Time taken: ${timer.elapsedMilliseconds}ms');
  });
}
epfja78i

epfja78i5#

这可能太晚了,但所有这些解决方案都不适合某些场景,如玩PopupMenuItems或影响UI渲染!

空安全更新

[
    .
    .
    .
    if(condition)...[//Conditionally widget(s) here
      Something(...),
    ],
    .
    .
    .
],

解决方案是在传递给呈现组件之前删除null项:

Column(
  children: [
    Text('Title'),
    name != '' 
      ? Text(name) //show name
      : null // just pass a null we will filter it in next line!
  ].where((e) => e != null).toList()// Filter list and make it List again!
)

这样,我们可以有很多null,UI不会受到任何空Widget影响。
PopupMenuButton示例***无法传递SizedBox***:

PopupMenuButton(
    icon: Icon(Icons.add),
    itemBuilder: (context) => [
        PopupMenuItem(
            child: Row(children:[ Icon(Icons.folder), Text('So something')]),
            value: 'do.something',
        ),
        1 > 2 //⚠️ A false condition
        ? PopupMenuItem(
           child: Row(children: [ Icon(Icons.file_upload), Text('⚠️No way to display 😎')]),
            'no.way.to.display',
          )
        : null,// ⚠️ Passing null
        PopupMenuItem(
           child: Row(children: [ Icon(Icons.file_upload), Text('Do something else')]),
            'do.something.else',
        )
    ].where((e) => e != null).toList(),//ℹ️ Removing null items  
    onSelected: (item) {}
)

这可以用作extension的API:

extension NotNulls on List {
  ///Returns items that are not null, for UI Widgets/PopupMenuItems etc.
  notNulls() {
    return where((e) => e != null).toList();
  }
}

//Usage:
PopupMenuButton(
    icon: Icon(Icons.add),
    itemBuilder: (context) => [
        PopupMenuItem(
            child: Row(children:[ Icon(Icons.folder), Text('So something')]),
            value: 'do.something',
        ),
        1 > 2 //⚠️ A false condition
        ? PopupMenuItem(
           child: Row(children: [ Icon(Icons.file_upload), Text('⚠️No way to display 😎')]),
            'no.way.to.display',
          )
        : null,// ⚠️ Passing null
        PopupMenuItem(
           child: Row(children: [ Icon(Icons.file_upload), Text('Do something else')]),
            'do.something.else',
        )
    ].notNulls(),//ℹ️ Removing null items  
    onSelected: (item) {}
)
qvtsj1bj

qvtsj1bj6#

当构建函数返回null时,flutter的错误消息是:
构建函数绝不能返回null。要返回使构建小部件填满可用空间的空白空间,请返回“new Container()"。要返回占用尽可能少空间的空白空间,请返回“new Container(width:0.0,高度:0.0)"的值。

sbtkgmzw

sbtkgmzw7#

建议使用SizedBox来显示任何内容。

SizedBox(
  width: 200.0,
  height: 300.0,
)
rjjhvcjd

rjjhvcjd8#

我的问题非常相似,但我发现ContainerSizedBox.shrink仍然影响UI(令人沮丧)。
我得到的最好的解决方案是使用一个命名的构造函数和初始化器列表来构建它。

class MyWidget extends StatelessWidget {
    final String name = 'Default';
    final bool hasThing = true;

    MyWidget({this.name});

    MyWidget.withoutThing({this.name}) : hasThing = false;

    @override
    Widget build(BuildContext context) {
        //define widgets they have in common here (as many as possible)
        if (hasThing) {
            return Widget(child: Thing(this.name));
        } else {
            return Widget(child: WithoutThing(this.name));
        }
    }
}

使用方法:

Center(child: MyWidget.withoutThing(name: 'Foo'),)//don't show thing

Center(child: MyWidget(name: 'Foo'),)

根据您的需求。
有关初始值设定项列表的详细信息:Colon after Constructor in dart

ztyzrc3y

ztyzrc3y9#

Column内部,我正在使用SizedBox(height: 0.01)

Column(
  children: [
    Text('Title'),
    name == ''
    ? SizedBox(height: 0.01) // show nothing
    : Text(name) // show name
  ]
)

相关问题