Flutter 实现钉钉侧边栏

Flutter framework 自带了很多好用的 Widget

实现一个侧边栏效果可以使用 Drawer Widget

实现步骤
  • 在 DTMainScreen 的 Scaffold 添加 drawer 属性,使用 Drawer widget来展示

  • Drawer 的 child 属性可以使用自定义 widget 来填充(ListView)

  • DTMessageScreen 添加点击事件,打开 Drawer

    1. onTap: () {
    2. Scaffold.of(context).openDrawer();
    3. },

修改 DTMainScreen
  • 添加 drawer 属性
    1. @override
    2. Widget build(BuildContext context) {
    3. ScreenUtil.init(context, width: 750, height: 1334);
    4. super.build(context);
    5. return Scaffold(
    6. drawer: Drawer(child: DTMainDrawerContent(),),
    7. body: _buildPageView(),
    8. ....

自定义 DTMainDrawerContent 组件
  1. class DTMainDrawerContent extends StatelessWidget {
  2. @override
  3. Widget build(BuildContext context) {
  4. return SafeArea(
  5. child: SingleChildScrollView(
  6. child: Container(
  7. margin: EdgeInsets.symmetric(horizontal: kSize36),
  8. child: Column(
  9. crossAxisAlignment: CrossAxisAlignment.start,
  10. children: <Widget>[
  11. DTDrawerUserInfoView(),
  12. DTDrawerWorkStatusView(),
  13. DTDrawerListContentView()
  14. ],
  15. ),
  16. ),
  17. ),
  18. );
  19. }
  20. }
  • SafeArea 使用安全区域,适配 iPhone X etc…
  • SingleChildScrollView 来包裹填充自组件

DTDrawerUserInfoView

image-20201215130023638

  1. class DTDrawerUserInfoView extends StatelessWidget {
  2. const DTDrawerUserInfoView({
  3. Key key,
  4. }) : super(key: key);
  5. @override
  6. Widget build(BuildContext context) {
  7. return Row(
  8. mainAxisAlignment: MainAxisAlignment.center,
  9. crossAxisAlignment: CrossAxisAlignment.center,
  10. children: <Widget>[
  11. Expanded(
  12. child: Column(
  13. crossAxisAlignment: CrossAxisAlignment.start,
  14. children: <Widget>[
  15. Text(
  16. "江景",
  17. style: TextStyle(fontSize: kSize40, fontWeight: FontWeight.bold),
  18. ),
  19. Padding(
  20. padding: EdgeInsets.only(top: kSize10),
  21. child: Text(
  22. "您所提出的问题,争取满意百分之百。",
  23. style: TextStyle(fontSize: kSize30, color: kColor33),
  24. overflow: TextOverflow.ellipsis,
  25. ),
  26. ),
  27. Padding(
  28. padding: EdgeInsets.symmetric(vertical: kSize20),
  29. child: Image.asset(
  30. 'assets/images/icon_org_auth_advance.png',
  31. width: kSize140,
  32. fit: BoxFit.cover,
  33. ),
  34. ),
  35. ],
  36. )),
  37. GestureDetector(
  38. child: CircleAvatar(
  39. backgroundColor: kPrimaryColor,
  40. radius: kSize40,
  41. child: Text(
  42. "江景",
  43. style: TextStyle(color: Colors.white),
  44. ),
  45. ),
  46. onTap: () {},
  47. )
  48. ],
  49. );
  50. }
  51. }

DTDrawerWorkStatusView

image-20201215130320590

  1. class DTDrawerWorkStatusView extends StatelessWidget {
  2. @override
  3. Widget build(BuildContext context) {
  4. return Container(
  5. margin: EdgeInsets.symmetric(vertical: kSize40),
  6. padding: EdgeInsets.symmetric(vertical: kSize16),
  7. decoration: BoxDecoration(
  8. color: kColorECEDED,
  9. borderRadius: BorderRadius.all(Radius.circular(kSize20))),
  10. width: double.infinity,
  11. child: Padding(
  12. padding: EdgeInsets.only(left: kSize26),
  13. child: Text(
  14. "编辑工作状态...",
  15. style: TextStyle(color: kColor99, fontSize: kSize26),
  16. ),
  17. ),
  18. );
  19. }
  20. }

DTDrawerListContentView

Flutter 钉钉侧边栏 - 图3

  • 因为放在 SingleChildScrollView 中,所以可以使用 Column 来展示 ListView 效果

  • 显示 Item 都是差不多,可以封装一个自定义 Widget,DTListContentItem

  1. class DTDrawerListContentView extends StatelessWidget {
  2. @override
  3. Widget build(BuildContext context) {
  4. return Column(
  5. children: <Widget>[
  6. DTListContentItem(
  7. leading: SvgPicture.asset('assets/icons/icon_qrcode.svg',
  8. width: kSize48, color: Colors.green),
  9. title: "二维码名片",
  10. trailing: SvgPicture.asset('assets/icons/icon_qrcode.svg',
  11. color: kColor99, width: kSize48),
  12. ),
  13. ....
  14. ],
  15. );
  16. }
  17. }

DTListContentItem
  1. class DTListContentItem extends StatelessWidget {
  2. final Widget leading;
  3. final Widget trailing;
  4. final String title;
  5. DTListContentItem({this.leading, this.title, this.trailing});
  6. @override
  7. Widget build(BuildContext context) {
  8. return Container(
  9. padding: EdgeInsets.symmetric(vertical: kSize30),
  10. child: Row(
  11. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  12. children: <Widget>[
  13. Row(
  14. mainAxisSize: MainAxisSize.min,
  15. children: <Widget>[
  16. leading ?? SizedBox(),
  17. title != null
  18. ? Padding(
  19. padding: EdgeInsets.only(left: kSize28),
  20. child: Text(
  21. title ?? "",
  22. style: TextStyle(color: kColor33, fontSize: kSize34),
  23. ),
  24. )
  25. : SizedBox(),
  26. ],
  27. ),
  28. Row(
  29. children: <Widget>[
  30. trailing ?? SizedBox(),
  31. SvgPicture.asset(
  32. 'assets/icons/icon_arrow_right.svg',
  33. width: kSize38,
  34. color: kColor99,
  35. ),
  36. ],
  37. )
  38. ],
  39. ),
  40. );
  41. }
  42. }

总结:在 Flutter 中,一切皆为 Widget,再复杂的 UI 显示,都可以使用一个个小的 Widget 来拼装组成。