美文网首页Android开发Android技术知识Android知识
Flutter 例子1 - 创建一个简单的静态界面

Flutter 例子1 - 创建一个简单的静态界面

作者: AnRFDev | 来源:发表于2018-06-24 18:10 被阅读43次

    为方便起见,文中有些地方会把widget称作组件部件

    创建一个静态界面

    效果图
    参考教程 https://flutter.io/tutorials/layout/#approach

    添加了一张图片


    图片资源存放位置

    pubspec.yaml中添加assets

      # To add assets to your application, add an assets section, like this:
      assets:
        - images/android_1.jpg
    

    这个地方要注意缩进,否则AS可能会不允许编译。

    从效果图中可以看到,页面中有一张大图片,一个小标题栏,有3个按钮的横栏,以及下方的大段文字。
    整个视图用一个ListView包含了所需的所有widget。写这个界面的过程,就像是Android中写layout文件。

    approach_1.dart代码。项目中使用的是material design的图标。

    import 'package:flutter/material.dart';
    
    void main() => runApp(new MyApp());
    
    class MyApp extends StatelessWidget {
      // 应用的根widget
      @override
      Widget build(BuildContext context) {
        // 图片下方的小标题栏
        Widget titleSection = new Container(
          padding: const EdgeInsets.all(32.0),
          child: new Row(
            children: <Widget>[
              new Expanded(child:
              new Column(crossAxisAlignment: CrossAxisAlignment.start,
                children: <Widget>[
                  new Container(padding: const EdgeInsets.only(bottom: 8.0),
                    child: new Text('Android Device',
                      style: new TextStyle(fontWeight: FontWeight.bold),),),
                  new Text(
                    'Rust Fisher', style: new TextStyle(color: Colors.grey[500]),)
                ],
              )),
              new Icon(Icons.star, color: Colors.red,),
              new Text('42')
            ],
          ),
        );
    
        // 定义在方法里面的方法 nested function
        Column buildButtonColumn(IconData icon, String label) {
          Color color = Theme
              .of(context)
              .primaryColor;
    
          return new Column(
            mainAxisSize: MainAxisSize.min,
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              new Icon(icon, color: color),
              new Container(
                margin: const EdgeInsets.only(top: 8.0),
                child: new Text(
                  label,
                  style: new TextStyle(
                    fontSize: 12.0, fontWeight: FontWeight.w400, color: color,),
                ),
              ),
            ],
          );
        }
    
        Widget buttonSection = new Container(
          child: new Row(mainAxisAlignment: MainAxisAlignment.spaceEvenly,
            children: <Widget>[
              buildButtonColumn(Icons.call, '通话'),
              buildButtonColumn(Icons.near_me, '定位'),
              buildButtonColumn(Icons.share, '分享'),
            ],
          ),);
    
        Widget textSection = new Container(padding: const EdgeInsets.all(32.0),
          child: new Text(
            '''
    Flutter Tutorials
    
    The Flutter Tutorials teach you how to use the Flutter framework to build mobile applications for iOS and Android.
    
    Choose from the following:
    
    ·Building Layouts in Flutter
        How to build layouts using Flutter’s layout mechanism. Once you’ve learned basic principles, you’ll build the layout for a sample screenshot.
    ·Adding Interactivity to Your Flutter App
        You’ll extend the simple layout app created in “Building Layouts in Flutter” to make an icon tappable. Different ways of managing a widget’s state are also discussed.
    ·Animations in Flutter
        Explains the fundamental classes in the Flutter animation package (controllers, Animatable, curves, listeners, builders), as it guides you through a progression of tween animations using different aspects of the animation APIs.
    ·Internationalizing Flutter Apps
        Learn how to internationalize your Flutter application. A guide through the widgets and classes that enable apps to display their content using the user’s language and formatting conventions.
    '''
            , softWrap: true,),);
    
        return new MaterialApp(
          title: 'Flutter Demo',
          theme: new ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: new Scaffold(
            appBar: new AppBar(title: new Text('Flutter Approach 1'),),
            body: new ListView(children: <Widget>[
              new Image.asset(
                'images/android_1.jpg', width: 600.0,
                height: 240.0,
                fit: BoxFit.cover,),
              titleSection,
              buttonSection,
              textSection
            ],),),
        );
      }
    }
    

    因flutter的绘制特性,flutter是在自己的canvas上绘制界面。
    Android开发者选项中-显示布局边界功能对flutter绘制出的界面并没什么作用。

    此时可以用debugPaintSizeEnabled,查看widget边界

    import 'package:flutter/rendering.dart';
    
    void main() {
      debugPaintSizeEnabled = true; // 这个可以看到UI的边界
    //   runApp(new MyApp());
    }
    

    改变这个属性时,可能需要重新编译运行。

    Flutter layout的要点

    • Widget是用来建立UI的类
    • Widget用于layout和UI元素
    • 将简单的widget组合成复杂的widget
      Flutter layout核心机制是widget。几乎所有的东西都是widget。

    设计一个widget

    要点:

    • app本身也是一个widget。
    • 创建一个widget能简单地添加到layout widget中。
    • 要在设备上展示一个widget,将其添加到app widget上。
    • Scaffold是很容易使用的,它来自Material组件库;它提供了一个默认标题栏,背景颜色,拥有用于添加drawer、snack bar和bottom sheet的api。
    • 也可以仅使用widget库中的标准组件。

    一个非material design的例子

    非material design组件,没有AppBar,没有背景颜色,没有标题。这些东西都要自己设置。

    import 'package:flutter/material.dart';
    
    void main() {
      runApp(new MyApp());
    }
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return new Container(
          decoration: new BoxDecoration(color: Colors.white70),
          child: new Center(
            child: new Text('my home page', textDirection: TextDirection.ltr,
              style: new TextStyle(fontSize: 40.0, color: Colors.black26),),
          ),
        );
      }
    
    }
    

    在手机上运行效果如图


    device-2018-06-25-110221.png

    水平或竖直放置多个组件

    竖直或水平放置组件是常见的布局方式。可以用Row widget来水平放置组件,或用Column widget垂直放置组件。

    • Row和Column是最常用的2中布局方式
    • Row和Column均接受多个子widget
    • 子widget可以是Row、Column或者其他负责组件
    • 可以指定子widget的对齐方式(垂直和水平方式均可)
    • 可延展或约束子widget
    • 可以指定子widget使用父widget空余空间的方式

    Sizing widgets

    如果要一个widget和它的同级widget一样占用自身宽度的两倍区域。可以把它放进Expanded widget里面。认准Expanded
    Expanded widget有一个flex属性,一个int值决定widget占用的比例。默认是1。(有点就像LinearLayout里面的weight)

    下面是一个显示2张图片的例子

    import 'package:flutter/material.dart';
    import 'package:flutter/rendering.dart';
    
    void main() {
      debugPaintSizeEnabled = true; // 这个可以看到UI的边界
      runApp(new MyApp());
    }
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return new MaterialApp(
          title: '随便一个title',
          theme: new ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: new MyHomePage(title: 'Home Page'),
        );
      }
    }
    
    class MyHomePage extends StatefulWidget {
      MyHomePage({Key key, this.title}) : super(key: key);
    
      final String title;
    
      @override
      _MyHomePageState createState() => new _MyHomePageState();
    }
    
    class _MyHomePageState extends State<MyHomePage> {
      @override
      Widget build(BuildContext context) {
        return new Scaffold(
          appBar: new AppBar(
            title: new Text(widget.title),
          ),
          body: new Center(
            child: new Row(
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: [
                new Expanded(child: new Image.asset('images/p_box1.png')),
                new Expanded(
                    flex: 2, child: new Image.asset('images/pic_kotlin_s.jpg')),
              ],
            ),
          ),
        );
      }
    }
    
    Sizing widgets效果图

    Packing widgets

    默认情况下,一行或一列会占用尽可能多的空间。但如果想把子widget紧密排列,需要设置mainAxisSizeMainAxisSize.min
    下面的例子是把几个图标紧凑排列。

    Packing widgets效果图
    class _MyHomePageState extends State<MyHomePage> {
      @override
      Widget build(BuildContext context) {
        return new Scaffold(
          appBar: new AppBar(
            title: new Text(widget.title),
          ),
          body: new Center(
            child: new Row(
              mainAxisSize: MainAxisSize.min,
              children: [
                new Icon(Icons.star, color: Colors.green,),
                new Icon(Icons.star, color: Colors.green[400],),
                new Icon(Icons.star, color: Colors.green[300],),
                new Icon(Icons.star, color: Colors.green[200],),
                new Icon(Icons.star, color: Colors.green[100],),
              ],
      // 无尽的括号......
    }
    

    Nesting rows and columns

    可以把Row和Column混起来用,组合到widget里面。

    class _MyHomePageState extends State<MyHomePage> {
      @override
      Widget build(BuildContext context) {
        var ratings = new Container(
          padding: EdgeInsets.all(20.0),
          child: new Row(
            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
            children: <Widget>[
              new Row(mainAxisSize: MainAxisSize.min, children: <Widget>[
                new Icon(Icons.star, color: Colors.red,),
                new Icon(Icons.star, color: Colors.red[400],),
                new Icon(Icons.star, color: Colors.red[300],),
                new Icon(Icons.star, color: Colors.red[200],),
                new Icon(Icons.star, color: Colors.red[100],),
              ],),
              new Text('42 Read'),
            ],
          ),
        );
    
        return new Scaffold(
          appBar: new AppBar(
            title: new Text(widget.title),
          ),
          body: new Center(
              child: ratings
          ),
        );
      }
    // ......
    }
    
    Row和Column混起来用
    用变量ratings来表示比较复杂的widget,可以减缓一些缩进和括号问题。

    横屏的一个例子

    横屏的一个例子

    使用了Card这个widget。

    import 'package:flutter/material.dart';
    import 'package:flutter/rendering.dart';
    
    void main() {
    //  debugPaintSizeEnabled = true; // 这个可以看到UI的边界
      runApp(new MyApp());
    }
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return new MaterialApp(
          title: '随便一个title',
          theme: new ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: new MyHomePage(title: 'Home Page'),
        );
      }
    }
    
    class MyHomePage extends StatefulWidget {
      MyHomePage({Key key, this.title}) : super(key: key);
    
      final String title;
    
      @override
      _MyHomePageState createState() => new _MyHomePageState();
    }
    
    class _MyHomePageState extends State<MyHomePage> {
      @override
      Widget build(BuildContext context) {
        var ratings = new Container(
          padding: EdgeInsets.all(20.0),
          child: new Row(
            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
            children: <Widget>[
              new Row(mainAxisSize: MainAxisSize.min, children: <Widget>[
                new Icon(Icons.star, color: Colors.red,),
                new Icon(Icons.star, color: Colors.red[400],),
                new Icon(Icons.star, color: Colors.red[300],),
                new Icon(Icons.star, color: Colors.red[200],),
                new Icon(Icons.star, color: Colors.red[100],),
              ],),
              new Text('42 Read'),
            ],
          ),
        );
    
        var descTextStyle = new TextStyle(
          color: Colors.black,
          fontWeight: FontWeight.w800,
          fontFamily: 'Roboto',
          letterSpacing: 0.5,
          fontSize: 12.0,
          height: 2.0,
        );
        var iconList = DefaultTextStyle.merge(
          style: descTextStyle,
          child: new Container(
            padding: new EdgeInsets.all(2.0),
            child: new Row(
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: [
                new Column(
                  children: [
                    new Icon(Icons.kitchen, color: Colors.red[500]),
                    new Text('PREP:'),
                    new Text('25 min'),
                  ],
                ),
                new Column(
                  children: [
                    new Icon(Icons.timer, color: Colors.red[500]),
                    new Text('COOK:'),
                    new Text('1 hr'),
                  ],
                ),
                new Column(
                  children: [
                    new Icon(Icons.restaurant, color: Colors.red[500]),
                    new Text('FEEDS:'),
                    new Text('4-6'),
                  ],
                ),
              ],
            ),
          ),
        );
    
        var leftColumn = new Container(
          padding: new EdgeInsets.fromLTRB(20.0, 20.0, 20.0, 2.0),
          child: new Column(
            children: [
              ratings,
              iconList,
            ],
          ),
        );
    
        return new Scaffold(
          appBar: new AppBar(
            title: new Text(widget.title),
          ),
          body: new Center(
            child: new Container(
              margin: new EdgeInsets.fromLTRB(0.0, 40.0, 0.0, 30.0),
    //          height: 600.0,
              child: new Card(
                child: new Row(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: <Widget>[
                    new Container(
    //                  width: 440.0,
                      child: leftColumn,
                    ),
                    new Expanded(
                        child: new Image.asset('images/android_1.jpg'))
                  ],
                ),
              ),
            ),
          ),
        );
      }
    }
    

    相关文章

      网友评论

        本文标题:Flutter 例子1 - 创建一个简单的静态界面

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