美文网首页
了解Flutter 组件#1 Container, Stack

了解Flutter 组件#1 Container, Stack

作者: 渣渣曦 | 来源:发表于2020-07-02 19:12 被阅读0次

本文章分别介绍Container,Stack,Positioned三个组件各自用途,然后组合在一个框架中实现一个简单案例。


image.png

首先创建Flutter应用

flutter create my_widget

打开文件lib/main.dart并将其修改为

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text("组件"),
        ),
        body: Container(
          margin: EdgeInsets.all(10),
          color: Colors.pinkAccent,
        )
      ),
    );
  }
}

上述代码中,我们通过调整颜色并提供margin来使用Container创建对象。EdgeInsets.all()这意味着要在(左,上、右、下)留出空间。

image.png
进一步修改main.dart文件
import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text("组件"),
        ),
        body: Container(
          margin: EdgeInsets.all(10),
          padding: EdgeInsets.all(15),
          color: Colors.pinkAccent,
          child: Container(
            decoration: BoxDecoration(
              color: Colors.lightGreen,
              gradient: LinearGradient(
                begin: Alignment.topCenter,
                end: Alignment.bottomCenter,
                colors: [Colors.lightGreen, Colors.limeAccent],
              ),
              borderRadius: BorderRadius.circular(30),
              boxShadow: <BoxShadow>[
                BoxShadow(blurRadius: 10),
              ],
            ),
          ),
        )
      ),
    );
  }
}

容器中放置容器,上面代码制作了一个大的粉红色盒子,盒子里放置一个源变色的盒子。通过BoxDecorationborderRadius制作盒子的圆角。注:decoration还有很多属性进行自定义的容器样式设置。

image.png

Stack & Positioned

Stack的children下可放置多个组件,Positioned可以指定组件放置位置。
修改lib/main.dart

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text("组件"),
        ),
        body: Stack(
          children: <Widget>[
            Container(
              color: Colors.orangeAccent,
              height: 250,
            ),
            Positioned(
              top: 195,
              left: 155,
              child: Container(
                height: 50,
                width: 250,
                color: Colors.black38,
                child: Center(
                  child: Text(
                    "Stack & Positioned",
                    style: TextStyle(
                      color: Colors.white,
                      fontWeight: FontWeight.bold,
                      fontSize: 20,
                    ),
                  ),
                ),
              ),
            )
          ],
        ),
      ),
    );
  }
}

创建用户界面

首先通过borderRadius对粉红色的容器做底部弯曲。第二是一个白色背景的容器通过positioned定位在上面。最后通过Card实现收支历史记录(今后会使用ListView替代)。
打开lib/main.dart并将其修改为

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: HomePage()
    );
  }
}

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final double screenWidth = MediaQuery.of(context).size.width;
    return Scaffold(
      appBar: AppBar(
        title: Text("AppBar"),
        backgroundColor: Colors.transparent, //透明化
        elevation: 0.0, //去除阴影效果
      ),
      extendBodyBehindAppBar: true, //扩展body的高度到AppBar下面
      body: Container(
        //子组件里包含Stack标题和Card历史记录
        child: Column(
          children: <Widget>[
            Stack(
              overflow: Overflow.visible,
              children: <Widget>[backgroundHeader(), summaryCash(screenWidth)],
            ),
            SizedBox(height: 55),
            //展示收支历史记录
            cardDetail('午餐', '肯德基', '10.000', 'out'),
            cardDetail('现金收入', '获取项目奖金', '500.000', 'in'),
            cardDetail('买衣服', '办公T恤', '250.000', 'out'),
          ],
        ),
      ),
    );
  }
}

Widget backgroundHeader() {
  //标题显示
}

Widget summaryCash(double screenWidth) {
  //汇总数据显示
}

Widget cardDetail(title, description, price, type) {
  //历史记录
}

上述代码把“标题”、“摘要”和“卡片”部分拆分,以使代码解耦
接下来首先处理标题,函数修改如下:

Widget backgroundHeader() {
  //高300的容器,底部圆角
  return Container(
    height: 220,
    width: double.infinity,
    decoration: BoxDecoration(
      color: Colors.pinkAccent,
      borderRadius: BorderRadius.only(
        bottomLeft: Radius.circular(30),
        bottomRight: Radius.circular(30),
      ),
    ),
    //使用Padding填充页面
    child: Padding(
      //顶部显示信息
      padding: const EdgeInsets.only(top: 80, left: 20),
      //使用Column显示多个组件
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: <Widget>[
          Text(
            "刘裕",
            style: TextStyle(
                fontSize: 25, color: Colors.white, fontWeight: FontWeight.bold),
          ),
          Text(
            "1869999999",
            style: TextStyle(
              fontSize: 15,
              color: Colors.white,
            ),
          ),
        ],
      ),
    ),
  );
}

运行上述代码,则会显示一个粉红色背示的标题,其中包含2个文本。接下来是在标题上方放置一个摘要,修改函数summaryCash()如下:

Widget summaryCash(double screenWidth) {
  return Positioned(
    top: 160,
    left: 20,
    child:Opacity(
          opacity: 0.9,
    child: Container(
      width: screenWidth * 0.9,
      height: 120,
      decoration: BoxDecoration(
        color: Colors.white,
        borderRadius: BorderRadius.circular(30),
        boxShadow: [
          BoxShadow(
            color: Colors.grey,
            offset: Offset(0.0, 1.0), //(x,y)
            blurRadius: 6.0,
          ),
        ],
      ),
      //设置容器内部填充布局
      child: Padding(
        padding: const EdgeInsets.only(top: 30.0),
        //使用Row()对两列数据进行放置
        child: Row(
          //通过行对列数据进行布局
          mainAxisAlignment: MainAxisAlignment.spaceAround,
          crossAxisAlignment: CrossAxisAlignment.start,
          children: <Widget>[
            //在同一行内垂直排放两列数据
            Column(
              children: <Widget>[
                Text("收入"),
                Divider(),
                Text(
                  "RMB 500.00",
                  style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
                ),
              ],
            ),
            Column(
              children: <Widget>[
                Text("支出"),
                Divider(),
                Text(
                  "RMB 260.00",
                  style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
                ),
              ],
            ),
          ],
        ),
      ),
    ),
    ),
  );
}

最后一部分是制做card历史记录,修改函数cardDetail()如下:

//封装可重用的Card,需提供title, description, price, type
Widget cardDetail(title, description, price, type) {
  return Card(
    //定制Card边距
    margin: EdgeInsets.only(top: 15, left: 15, right: 15),
    //阴影度为8
    elevation: 8,
    child: ListTile(
      leading: Icon(
        type == 'out'
            ? Icons.subdirectory_arrow_left
            : Icons.subdirectory_arrow_right,
        color: type == 'out' ? Colors.redAccent : Colors.lightGreen,
      ),
      title: Text(
        title,
        style: TextStyle(fontWeight: FontWeight.bold),
      ),
      subtitle: Text(description),
      trailing: Text(
        "RMB " + price,
        style: TextStyle(
            color: type == 'out' ? Colors.redAccent : Colors.lightGreen),
      ),
    ),
  );
}

保存并运行程序,结果如最初附图一致,此例中仅使用了Container,Stack和Positioned制作一个简单的UI。

相关文章

网友评论

      本文标题:了解Flutter 组件#1 Container, Stack

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