Code前端首页关于Code前端联系我们

如何在Flutter中构建漂亮的UI布局小部件

terry 2年前 (2023-09-23) 阅读数 83 #移动小程序

通过一个简单的例子,逐步向大家介绍如何在Flutter中构建漂亮的布局。通过本文您将了解以下几点:

  • Flutter中的布局机制是如何工作的
  • 如何在垂直和水平方向上布局Widget
  • ❿Flutter❿ Widget 布局

本文档主要介绍如何在Flutter中进行布局。您最终将构建一个如下所示的页面: 如何在Flutter中构建漂亮的UI布局WidgetThe 完成的应用程序

本文将带您逐步构建一个如上所示的 A 页面。 ?运行效果如下图: 如何在Flutter中构建漂亮的UI布局Widgetimage-20190610130957545

第一步:分析页面布局逻辑

第一步将整个页面布局分解为以下基本元素,主要是点

  • 识别布局中的行 (Row) 和列 (Column) ❀erer )?
  • Widget 之间是否有重叠?
  • 整个 UI 布局是否需要tab 列? 按照区域(对齐)、内边距(内边距)和框架(边框边框边框)页面-页​​页面:栏目元素

    可以看到,整个页面的主要组成部分就是红框标注的4个部分。这 4 个部分分别放置在同一列()中:1 个图像、2 个❓ 和行和❿1 个 Sms。

    我们来深入分析一下每一行(Row):

    • 第1行,也就是标题部分(TitleSection),有3列:1由文本Column(列)行组成,1行星号图标,1 个数字:
      如何在Flutter中构建漂亮的UI布局Widget标题部分

      您可以看到,由于第一列()占据了整行的大部分空间,因此应该用 包裹起来扩展小部件。

    • 第二行是按钮列(按钮部分),也包含3个子元素。每个子元素为一行,该行的内容为图标和1个文字
      如何在Flutter中构建漂亮的UI布局Widget按钮部分
    • 第三行没有:一个很复杂的组成,它是一个简单的文本块。

    经过上面的分析,我们将一个复杂的页面划分为几个简单的组件,这样可以简化整个页面的实现。为了避免布局代码中的混乱,我们应该使用变量和函数来构建布局的子部分。 ,我将在下面的代码中演示。

    第2步:实现第一行(标题行)

    直接提供代码。具体解释见代码注释。注意注释:

    Widget titleSection = Container(
      //为整个Widget(即这一行)的所有所有方向设置32px的填充
      padding: const EdgeInsets.all(32),
      child: Row(
        children: [
          Expanded(
            /**
            将Column放置在Expanded中,由于Expanded会默认占据所有当前Row的空闲可用空间,所以这个Column也会自然被拉伸的占据完所有当前Row可用的空闲空间。
            */
            child: Column(
              /**将Column的crossAxisAlignment属性设置为CrossAxisAlignment.start以保证这个列中的元素(即children属性中的Widget)在水平方向上排列在当前Column的起始位置
              */
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                /**
                将这个Text放在Container中的目的是通过Container来添加填充(padding)
                            */
                Container(
                  padding: const EdgeInsets.only(bottom: 8),
                  child: Text(
                    'Oeschinen Lake Campground',
                    style: TextStyle(
                      fontWeight: FontWeight.bold,
                    ),
                  ),
                ),
                Text(
                  'Kandersteg, Switzerland',
                  style: TextStyle(
                    color: Colors.grey[500],
                  ),
                ),
              ],
            ),
          ),
          /**
          最后的2个元素分别是1个Icon和1个Text,分别用来显示星星和数字
          */
          Icon(
            Icons.star,
            color: Colors.red[500],
          ),
          Text('41'),
        ],
      ),
    );
    

    直接编辑上面的变量titleSection只需将放在app文本中:注意这里使用了标题:代码所以不会因为MaterialApp(..)中的代码太长且令人困惑。​​如运行的效果如下图所示: 如何在Flutter中构建漂亮的UI布局Widget图片-20190610133211088

    步骤3:实现按钮栏(按钮部分

    )第1列由1个圆锥体组成,每列:I,1 文本。该行中的列都是均匀间隔的,并且由于构建每列的代码几乎相同,因此创建一个名为 buildbuttoncolumn() 的私有方法,该方法接收颜色 ( Color ) 参数、一个图标 (Icon) 参数和 1 个文本 (Text) 参数,并返回一个带有 和 ❓ 的小部件❿给定'n的列(Column),代码如下:

    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        // ···
      }
    
      Column _buildButtonColumn(Color color, IconData icon, String label) {
        return Column(
          mainAxisSize: MainAxisSize.min,
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Icon(icon, color: color),
            Container(
              margin: const EdgeInsets.only(top: 8),
              child: Text(
                label,
                style: TextStyle(
                  fontSize: 12,
                  fontWeight: FontWeight.w400,
                  color: color,
                ),
              ),
            ),
          ],
        );
      }
    }
    

    _buildButtonColumn()方法将Iconn直接添加到nn 。 和 文本先用Container包裹,然后将Container添加到列。这样做的目的是使用 Container设置顶部填充 (padding) 到 Textt so 和 icon 相距不太远近。

    完成函数_buildButtonColumn()后,我们只需要在需要构建列时调用该函数(Column

Column)传入相应的参数即可。我们需要的列:

Color color = Theme.of(context).primaryColor;

Widget buttonSection = Container(
  child: Row(
    mainAxisAlignment: MainAxisAlignment.spaceEvenly,
    children: [
      _buildButtonColumn(color, Icons.call, 'CALL'),
      _buildButtonColumn(color, Icons.near_me, 'ROUTE'),
      _buildButtonColumn(color, Icons.share, 'SHARE'),
    ],
  ),
);

请注意,此处设置的 mainAxisAlignment 属性值是 MainAxisAlignment.spaceEvenly❀❀,❓ 中列均匀地填充行的整个可用空间。

然后在app body中设置变量buttonSection

 return MaterialApp(
        title: 'Flutter layout demo',
        debugShowCheckedModeBanner: false,
        home: Scaffold(
            appBar: AppBar(
              title: Text('Flutter layout demo'),
            ),
            body: Column(
              children: [titleSection, buttonSection],
            )));

运行效果图如下所示 4053003 8

第4步:实现正文部分

Text 部分定义为变量,然后将 Text 放入 ❀♿ create♿ 容器 Container 设置 padding属性:

Widget textSection = Container(
  padding: const EdgeInsets.all(32),
  child: Text(
    'Lake Oeschinen lies at the foot of the Blüemlisalp in the Bernese '
        'Alps. Situated 1,578 meters above sea level, it is one of the '
        'larger Alpine Lakes. A gondola ride from Kandersteg, followed by a '
        'half-hour walk through pastures and pine forest, leads you to the '
        'lake, which warms to 20 degrees Celsius in the summer. Activities '
        'enjoyed here include rowing, and riding the summer toboggan run.',
    softWrap: true,
  ),
);

注意这里设置 softwrap 属性值是

Widget textSection = Container(
  padding: const EdgeInsets.all(32),
  child: Text(
    'Lake Oeschinen lies at the foot of the Blüemlisalp in the Bernese '
        'Alps. Situated 1,578 meters above sea level, it is one of the '
        'larger Alpine Lakes. A gondola ride from Kandersteg, followed by a '
        'half-hour walk through pastures and pine forest, leads you to the '
        'lake, which warms to 20 degrees Celsius in the summer. Activities '
        'enjoyed here include rowing, and riding the summer toboggan run.',
    softWrap: true,
  ),
);

注意,这里设置 softwrap 属性值是❀♿,它可以在单词边界换行,而不是在单词中间换行单词。 。

然后将上面的textSection变量放入app body中:

 return MaterialApp(
        title: 'Flutter layout demo',
        debugShowCheckedModeBanner: false,
        home: Scaffold(
            appBar: AppBar(
              title: Text('Flutter layout demo'),
            ),
            body: Column(
              children: [titleSection, buttonSection, textSection],
            )));

运行效果图如下所示 410091 30

Step 5 :实现图像部分

到目前为止,我们已经实现了 4 行中的 3 行,只有图像行尚未实现。这一步,我们实现图片的显示:

  • 在项目A的顶层文件夹中创建images文件夹
  • 将以下图片放在刚才的❿图片文件夹下创建并命名为 lake.jpg
    如何在Flutter中构建漂亮的UI布局Widgetimg
  • updatepubspec.yaml 文件,添加 Assets 标签,配置图像路径,以便您可以访问代码中保存的图片:
    flutter:            
                  uses-material-design: true            
                assets:            
                  - images/lake.jpg
    

然后我们可以参考代码中的图片:

return MaterialApp(
        title: 'Flutter layout demo',
        debugShowCheckedModeBanner: false,
        home: Scaffold(
            appBar: AppBar(
              title: Text('Flutter layout demo'),
            ),
            body: Column(
              children: [
                Image.asset(
                  'images/lake.jpg',
                  width: 600,
                  height: 240,
                  fit: BoxFit.cover,
                ),
                titleSection,
                buttonSection,
                textSection
              ],
            )));

驱动效果如下:如何在Flutter中构建漂亮的UI布局Widgetimage-20190610144829576❀第6步:我们来看看完成前几个步骤后的最终代码:

return MaterialApp(
        title: 'Flutter layout demo',
        debugShowCheckedModeBanner: false,
        home: Scaffold(
            appBar: AppBar(
              title: Text('Flutter layout demo'),
            ),
            body: Column(
              children: [
                Image.asset(
                  'images/lake.jpg',
                  width: 600,
                  height: 240,
                  fit: BoxFit.cover,
                ),
                titleSection,
                buttonSection,
                textSection
              ],
            )));

注意,我们想要将属Body性的属性值设置为❓column,然后我们在Column中实现了一些小部件,现在我们改变使用方式,使用它,使用它,使用它,使用它,使用它,使用它,使用它。 ListView来替换这个Column

return MaterialApp(
        title: 'Flutter layout demo',
        debugShowCheckedModeBanner: false,
        home: Scaffold(
            appBar: AppBar(
              title: Text('Flutter layout demo'),
            ),
            body: ListView(
              children: [
                Image.asset(
                  'images/lake.jpg',
                  width: 600,
                  height: 240,
                  fit: BoxFit.cover,
                ),
                titleSection,
                buttonSection,
                textSection
              ],
            )));

效果如下:如何在Flutter中构建漂亮的UI布局Widget6114906-210561 可以使用查看 并使用 ListView的静态视觉效果是一样的,那么我们应该使用Column还是ListView❀呢?两者有什么区别?答案就在于“动态”。两者在动态条件下的效果是不同的。更具体地说,使用 Column 构建的 Widget 不支持滚动,即不支持滚动。上下或左右滚动事件,使用ListView支持滚动事件如下:如何在Flutter中构建漂亮的UI布局Widget

版权声明

本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

热门