原始组件

  1. UserAccountsDrawerHeader(
  2. accountName: FutureBuilder(
  3. future: _getUserData(),
  4. builder: (context, snapshot) {
  5. if (snapshot.hasData) {
  6. String time = snapshot.data["date_create"];
  7. DateTime thatTime = DateTime.parse(time);
  8. DateTime nowTime = DateTime.now();
  9. var difference = nowTime.difference(thatTime);
  10. String days = difference.inDays.toString();
  11. return Text(
  12. " " +
  13. snapshot.data["truename"] +
  14. " 加入家园的第 $days 天",
  15. style: TextStyle(fontWeight: FontWeight.bold),
  16. );
  17. } else {
  18. return Text("喵喵喵",
  19. style: TextStyle(fontWeight: FontWeight.bold));
  20. }
  21. }),
  22. currentAccountPicture: FutureBuilder(
  23. future: _getUserData(),
  24. builder: (context, snapshot) {
  25. if (snapshot.hasData) {
  26. return CircleAvatar(
  27. backgroundImage: NetworkImage(snapshot.data["photo"],
  28. headers: {"authorization": snapshot.data["token"]}),
  29. );
  30. }
  31. }),
  32. decoration: BoxDecoration(
  33. color: Colors.yellow[400],
  34. image: DecorationImage(
  35. image: NetworkImage(
  36. 'https://resources.ninghao.org/images/childhood-in-a-picture.jpg'),
  37. fit: BoxFit.cover,
  38. colorFilter: ColorFilter.mode(
  39. Colors.yellow[400].withOpacity(0.6), BlendMode.hardLight),
  40. ),
  41. ),
  42. ),

image.png

自定义header

摘自 https://www.jianshu.com/p/956bb41bb524
最近还看到一种实现:https://www.jianshu.com/p/19502981607e
Flutter有DrawerHeader,我们对其进行自定义。

  • DrawerHeader设置padding为0,充满整个顶部
  • DrawerHeader的child使用Stack,目的是放置背景图片
  • Stack偏左下的位置放置头像和用户名
    • 先用Align确定对齐方式为FractionalOffset.bottomLeft
    • Align的child为Container,并设定一个具体高度
    • 头像与文字的Container仿照ListTile的风格,左边是一个头像,右边是文字;使用Row来分隔头像和文字
    • 文字部分先用Container的margin做出间隔,再放入一个Column来存放Text
    • 文字Column设置水平方向左对齐与竖直方向居中
      1. Widget header = DrawerHeader(
      2. padding: EdgeInsets.zero, /* padding置为0 */
      3. child: new Stack(children: <Widget>[ /* 用stack来放背景图片 */
      4. new Image.asset(
      5. 'images/p_h_r_600.png', fit: BoxFit.fill, width: double.infinity,),
      6. new Align(/* 先放置对齐 */
      7. alignment: FractionalOffset.bottomLeft,
      8. child: Container(
      9. height: 70.0,
      10. margin: EdgeInsets.only(left: 12.0, bottom: 12.0),
      11. child: new Row(
      12. mainAxisSize: MainAxisSize.min, /* 宽度只用包住子组件即可 */
      13. crossAxisAlignment: CrossAxisAlignment.start,
      14. mainAxisAlignment: MainAxisAlignment.start,
      15. children: <Widget>[
      16. new CircleAvatar(
      17. backgroundImage: AssetImage('images/pic1.jpg'),
      18. radius: 35.0,),
      19. new Container(
      20. margin: EdgeInsets.only(left: 6.0),
      21. child: new Column(
      22. crossAxisAlignment: CrossAxisAlignment.start, // 水平方向左对齐
      23. mainAxisAlignment: MainAxisAlignment.center, // 竖直方向居中
      24. children: <Widget>[
      25. new Text("Tom", style: new TextStyle(
      26. fontSize: 20.0,
      27. fontWeight: FontWeight.w400,
      28. color: Colors.white),),
      29. new Text("What's up", style: new TextStyle(
      30. fontSize: 14.0, color: Colors.white),),
      31. ],
      32. ),
      33. ),
      34. ],),
      35. ),
      36. ),
      37. ]),);
      自定义header的效果图
      image.png

自定义header的效果图
在自定义header的过程中,我们组合使用了多种widget;
有层叠的Stack,用于对齐的Align,设定具体尺寸和margin的Container,水平放置的Row以及竖直放置的Column
这些widget的各有特点,根据具体情况来组合使用。同一个UI效果,做法也不止一种。

在设置背景图的时候

这两种会达到相似的效果

  1. child: new Image.network(
  2. 'https://resources.ninghao.org/images/childhood-in-a-picture.jpg',
  3. fit: BoxFit.fill,
  4. width: double.infinity,
  5. ),
  6. // decoration: BoxDecoration(
  7. // color: Colors.yellow[400],
  8. // image: DecorationImage(
  9. // image: NetworkImage(
  10. // 'https://resources.ninghao.org/images/childhood-in-a-picture.jpg'),
  11. // fit: BoxFit.cover,
  12. // colorFilter: ColorFilter.mode(
  13. // Colors.yellow[400].withOpacity(0.6),
  14. // BlendMode.hardLight),
  15. // ),
  16. // ),
  17. ),

适配刘海屏

关于顶部半透明状态的效果,可以通过DrawerHeader的熟悉达到
https://www.jianshu.com/p/647b047d8d83
https://blog.csdn.net/u011272795/article/details/82795477

  1. final double topPadding = MediaQuery.of(context).padding.top;
  2. final double bottomPadding = MediaQuery.of(context).padding.bottom;

padding: EdgeInsets.only(top: -24),
top: -topPadding
image.png