美文网首页
flutter布局详解(重要)(原理和Android XML布局

flutter布局详解(重要)(原理和Android XML布局

作者: 禄子_c79b | 来源:发表于2022-04-19 09:33 被阅读0次

核心:这里是参照Android xml布局对比学习(web,ios也类似)
具体布局详情可以参照flutter官方
Flutter 布局控件完结篇
Flutter学习指南:UI布局和控件

  • 基础布局组件:Container(容器布局),Center(居中布局),Padding(填充布局),Align(对齐布局),Colum(垂直布局),Row(水平布局),Expanded(配合Colum,Row使用),FittedBox(缩放布局),Stack(堆叠布局),overflowBox(溢出父视图容器)。
  • 宽高尺寸处理:SizedBox(设置具体尺寸),ConstrainedBox(限定最大最小宽高布局),LimitedBox(限定最大宽高布局),AspectRatio(调整宽高比),FractionallySizedBox(百分比布局)
  • 列表和表格处理:ListView(列表),GridView(网格),Table(表格)
  • 其它布局处理:Transform(矩阵转换),Baseline(基准线布局),Offstage(控制是否显示组件),Wrap(按宽高自动换行布局)


    image.png

整个过程,基本上按照拆解、组件封装、具体布局这三步来

拆解

image.png
整体拆解
根据设计图,可以看出整体时分行展示的,因此最外层是一个Column元素
  • 第一行为标题,涉及到不对称的布局,可以用一个Stack或者Row来进行,用Row的话,则需要右边填上一个空白的widget占位。也可能会使用AppBar,将底部阴影去掉也能实现相同效果;
  • 第二行可以看作一个Row,分两块布局。右边部分,涉及到叠加,会考虑Stack;
  • 第三行比较复杂,整体看,也是一行一行进行展示的,因此最外层时一个Column。中间的文本部分需要根据个数自动换行,因此考虑使用Wrap。预习这个地方涉及到叠加,考虑Stack实现;
  • 第四行可以看作一个Row,分三块进行布局;
  • 第五行可以看作一个Row,分两块布局。

每一行之间的间隔,则可以考虑用Padding或者Container来设置。
通过上面这样一步一步的分析后,基本上对大致的布局有了一个了解,最外层的控件大致选对(只要能实现的话,就是复杂度以及效率的问题),然后一步一步的拆解每一行的元素,如果有重复的或者觉得可以封装出来的部分,则进行下一步。

import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';

import 'LoginPageState.dart';

class SamplePagebujuchaijie extends  State<MyApp1> {
  // const SamplePagebujuchaijie();

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      /// Line 1
      appBar: new AppBar(
        backgroundColor: Colors.white,
        elevation: 0.0,
        centerTitle: true,
        title: new Text(
          "发布成功",
          style: new TextStyle(
              color: Colors.black,
              fontSize: 18.0,
              fontWeight: FontWeight.normal),
        ),
        leading: IconButton(
            icon: new Image.asset("assets/images/nav_close.png"),
            onPressed: () {
              Navigator.maybePop(context);
            }),
      ),

      /// Line 2-5
      body: new SamplePageContent(),
    );
  }
}

class SamplePageContent extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new Container(
      color: Colors.white,
      padding: const EdgeInsets.only(top: 42.0),
      child: new Column(
        children: <Widget>[
          /// Line 2
          new Row(
            children: <Widget>[
              new Container(
                width: 52.0,
                height: 52.0,
                margin: const EdgeInsets.only(left: 16.0),
                child: new CircleAvatar(
                  backgroundImage: new AssetImage("assets/images/avatar2.png"),
                ),
              ),
              new Container(
                margin: const EdgeInsets.only(left: 7.0, right: 15.0),
                height: 48.0,
                child: new Stack(
                  children: <Widget>[
                    new Image.asset("assets/images/publish_chat_box.png"),
                    new Positioned(
                        left: 25.0,
                        top: 14.0,
                        child: new Text(
                          "张老师发布了一个任务,请接收~",
                          style: new TextStyle(
                            fontSize: 14.0,
                            color: Colors.black,
                          ),
                        )),
                  ],
                ),
              )
            ],
          ),

          /// Line 3
          new Container(
            margin: const EdgeInsets.fromLTRB(6.0, 24.0, 6.0, 30.0),
            child: new RoundInnerSquareBox(
              child: new Container(
                padding: const EdgeInsets.fromLTRB(24.0, 28.0, 24.0, 12.0),
                width: double.infinity,
                child: new Column(
                  mainAxisAlignment: MainAxisAlignment.start,
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: <Widget>[
                    new Text(
                      "Unit 1 Lesson 3 About animal",
                      style: new TextStyle(
                        fontSize: 20.0,
                        fontFamily: "Round",
                        color: Colors.white,
                      ),
                    ),
                    new Container(
                      margin: const EdgeInsets.only(top: 5.0, bottom: 13.0),
                      child: new Image.asset(
                          "assets/images/publish_work_line.png"),
                    ),
                    new Wrap(
                      alignment: WrapAlignment.start,
                      children: <Widget>[
                        new WorkTotalItem(
                          title: "课文跟读 12",
                        ),
                        new WorkTotalItem(
                          title: "课文跟读 12",
                        ),
                        new WorkTotalItem(
                          title: "课文跟读 12",
                        ),
                        new WorkTotalItem(
                          title: "课文跟读 12",
                        ),
                      ],
                    ),
                    new Container(
                      margin: const EdgeInsets.only(left: 178.0),
                      child: new Stack(
                        children: <Widget>[
                          new Image.asset(
                              "assets/images/publish_work_sign.png"),
                          new Positioned(
                            left: 4.0,
                            top: 4.0,
                            child: new Text(
                              "预习",
                              style: new TextStyle(
                                  fontSize: 14.0, color: Colors.white),
                            ),
                          )
                        ],
                      ),
                    ),
                    new Container(
                      alignment: Alignment.topRight,
                      child: new Text(
                        "明天12:00截止",
                        style: new TextStyle(
                            fontSize: 12.0, color: const Color(0xFFFFC1C1)),
                      ),
                    ),
                  ],
                ),
              ),
            ),
          ),

          /// Line 4
          new LineTips(
            title: new Text(
              "给家长发个通知吧",
              style:
              new TextStyle(fontSize: 14.0, color: const Color(0xFF757085)),
            ),
          ),

          /// Line 5
          new Container(
            margin: const EdgeInsets.only(top: 32.0),
            height: 60.0,
            child: new Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                new IconButton(
                    padding: EdgeInsets.zero,
                    iconSize: 60.0,
                    icon: new Image.asset("assets/images/share_wechat.png"),
                    onPressed: () {
                      print("share to wechat");
                    }),
                new Container(
                  margin: const EdgeInsets.only(left: 32.0),
                  child: new IconButton(
                      padding: EdgeInsets.zero,
                      iconSize: 60.0,
                      icon: new Image.asset("assets/images/share_qq.png"),
                      onPressed: () {
                        print("share to qq");
                      }),
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }
}

class RoundInnerSquareBox extends StatelessWidget {
  static const double gap = 12.0;

  RoundInnerSquareBox({
    required this.child,
  });

  final Widget child;

  @override
  Widget build(BuildContext context) {
    return new ClipRRect(
      borderRadius: const BorderRadius.all(const Radius.circular(16.0)),
      child: new Container(
        color: const Color(0xFFF0D5A9),
        padding: const EdgeInsets.all(gap),
        child: new Container(
          child: new Container(
            color: const Color(0xFF3C594E),
            child: child,
          ),
        ),
      ),
    );
  }
}

class LineTips extends StatelessWidget {
  static const defaultMargin = const EdgeInsets.only(left: 15.0, right: 15.0);

  LineTips({
    required this.title,
    this.margin = defaultMargin,
  });

  final Widget title;
  final EdgeInsetsGeometry margin;

  @override
  Widget build(BuildContext context) {
    return new Padding(
      padding: defaultMargin,
      child: new Row(
        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
        children: <Widget>[
          new Expanded(
            child: new Container(
              margin: const EdgeInsets.only(
                right: 10.0,
              ),
              color: const Color(0xFFD4CFE4),
              height: 1.0,
            ),
          ),
          title,
          new Expanded(
            child: new Container(
              margin: const EdgeInsets.only(
                left: 10.0,
              ),
              color: const Color(0xFFD4CFE4),
              height: 1.0,
            ),
          ),
        ],
      ),
    );
  }
}

class WorkTotalItem extends StatelessWidget {
  WorkTotalItem({
    required this.title,
  });

  final String title;

  @override
  Widget build(BuildContext context) {
    return new Container(
      padding: const EdgeInsets.all(6.0),
      child: new Text(
        "$title",
        style: new TextStyle(
          fontSize: 14.0,
          color: Colors.white,
        ),
      ),
    );
  }
}

注明:所有dart代码层级嵌套和Android均保持一致
原文参照:

相关文章

网友评论

      本文标题:flutter布局详解(重要)(原理和Android XML布局

      本文链接:https://www.haomeiwen.com/subject/giedertx.html