Flutter Drawer 灰色状态栏解决
2014 年 2 月 2 日
0x0 前言
在制作 Flutter App 新建一个抽屉的实例后,发现一个问题:打开抽屉发现状态栏是灰色的,主要抽屉头部我用图片展示,理想效果应该是抽屉头部图片偏移上面状态栏的高度。
0x1 思路
除了查看文档之外,更好的方法直接查看 Drawer
源码,看看它是如何实现的。由于头部灰色原因我想到可能发生在 Drawer
的第一个子级参数: DrawerHeader
,他的作用类似 容器展示 ,直接查看它的源码:
// Copyright 2015 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. import 'package:flutter/widgets.dart'; import 'debug.dart'; import 'divider.dart'; import 'theme.dart'; const double _kDrawerHeaderHeight = 160.0 + 1.0; // bottom edge /// The top-most region of a material design drawer. The header's [child] /// widget, if any, is placed inside a [Container] whose [decoration] can be /// passed as an argument, inset by the given [padding]. /// /// Part of the material design [Drawer]. /// /// Requires one of its ancestors to be a [Material] widget. This condition is /// satisfied by putting the [DrawerHeader] in a [Drawer]. /// /// See also: /// /// * [UserAccountsDrawerHeader], a variant of [DrawerHeader] that is /// specialized for showing user accounts. /// * class DrawerHeader extends StatelessWidget { /// Creates a material design drawer header. /// /// Requires one of its ancestors to be a [Material] widget. const DrawerHeader({ Key key, this.decoration, this.margin = const EdgeInsets.only(bottom: 8.0), this.padding = const EdgeInsets.fromLTRB(16.0, 16.0, 16.0, 8.0), this.duration = const Duration(milliseconds: 250), this.curve = Curves.fastOutSlowIn, @required this.child, }) : super(key: key); /// Decoration for the main drawer header [Container]; useful for applying /// backgrounds. /// /// This decoration will extend under the system status bar. /// /// If this is changed, it will be animated according to [duration] and [curve]. final Decoration decoration; /// The padding by which to inset [child]. /// /// The [DrawerHeader] additionally offsets the child by the height of the /// system status bar. /// /// If the child is null, the padding has no effect. final EdgeInsetsGeometry padding; /// The margin around the drawer header. final EdgeInsetsGeometry margin; /// The duration for animations of the [decoration]. final Duration duration; /// The curve for animations of the [decoration]. final Curve curve; /// A widget to be placed inside the drawer header, inset by the [padding]. /// /// This widget will be sized to the size of the header. To position the child /// precisely, consider using an [Align] or [Center] widget. /// /// {@macro flutter.widgets.child} final Widget child; @override Widget build(BuildContext context) { assert(debugCheckHasMaterial(context)); assert(debugCheckHasMediaQuery(context)); final ThemeData theme = Theme.of(context); final double statusBarHeight = MediaQuery.of(context).padding.top; return Container( height: statusBarHeight + _kDrawerHeaderHeight, margin: margin, decoration: BoxDecoration( border: Border( bottom: Divider.createBorderSide(context), ), ), child: AnimatedContainer( padding: padding.add(EdgeInsets.only(top: statusBarHeight)), decoration: decoration, duration: duration, curve: curve, child: child == null ? null : DefaultTextStyle( style: theme.textTheme.body2, child: MediaQuery.removePadding( context: context, removeTop: true, child: child, ), ), ), ); } }
在第 79 行指示出这边这边有个获取状态栏高度的方法,然后再加其他一些边距,这边逻辑走一通没什么问题,那应该问题不出现在这边,那么则判断父类容器的问题,直接修改成:
Drawer buildDrawer(BuildContext context, String currentRoute) { return new Drawer( child: new Text('test') ); }
发现不会出现灰色状态栏的问题,初步判断原因在这里面,继续查看 ListView
里面的源码:
@override List buildSlivers(BuildContext context) { Widget sliver = buildChildLayout(context); EdgeInsetsGeometry effectivePadding = padding; if (padding == null) { final MediaQueryData mediaQuery = MediaQuery.of(context, nullOk: true); if (mediaQuery != null) { // Automatically pad sliver with padding from MediaQuery. final EdgeInsets mediaQueryHorizontalPadding = mediaQuery.padding.copyWith(top: 0.0, bottom: 0.0); final EdgeInsets mediaQueryVerticalPadding = mediaQuery.padding.copyWith(left: 0.0, right: 0.0); // Consume the main axis padding with SliverPadding. effectivePadding = scrollDirection == Axis.vertical ? mediaQueryVerticalPadding : mediaQueryHorizontalPadding; // Leave behind the cross axis padding. sliver = MediaQuery( data: mediaQuery.copyWith( padding: scrollDirection == Axis.vertical ? mediaQueryHorizontalPadding : mediaQueryVerticalPadding, ), child: sliver, ); } } if (effectivePadding != null) sliver = SliverPadding(padding: effectivePadding, sliver: sliver); return [ sliver ]; }
- 当
ListView
的属性padding
为空时,获取MediaQueryData
的信息 - 因为
ListView
的滚动方向默认为垂直,会使用mediaQueryVerticalPadding
-
sliver
添加一层MediaQuery
,这个表明sliver
的子部件会使用该MediaQuery
的值,根据判断,子部件会使用mediaQueryHorizontalPadding
,而上面的两个复制:mediaQueryHorizontalPadding
=> 将原有的MediaQuery
的padding
复制为top
和bottom
都为0
,该值会被子部件使用,所以DrawerHeader
使用了该值,导致statusBarHeader
为0
mediaQueryVerticalPadding
=> 将原有的MediaQuery
的padding
复制为left
和right
都为0
所以添加 ListView
的 padding
属性即可:
new Drawer( child: ListView( padding: EdgeInsets.zero, children: [] ) )
安装Flutter环境
Flutter是谷歌的移动UI框架,可以快速在iOS和Android上构建高质量的原生用户界面。 Flutter可以与现有的代码一起工作。在全世界,Flutter正在被越来越多的开发者和组织使用,并且Flutter是完全免费、开源的。
淮城一只猫 淮城一只猫

编写第一个Flutter App
从编写这篇博文就有个写个App的计划,大概是Flutter功能展示方向的App,相信在Github有了一大堆轮子项目,且当对我来说是一个锻炼技术的项目吧,希望在这个项目过程中能够给自己带来App开发思考和设计理念。
淮城一只猫 淮城一只猫
