美文网首页
了解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