Flutter 入坑记

flutter 第二天

2019-05-29  本文已影响6人  雪纳瑞的哈士奇

今天主要搞页面布局 加油吧

上班一个半小时之后

先说说flutter和Android控件的对比
一. 开始
在Android中View是所有控件的基础, 在Flutter中与View对等的是Widget. 但Widget又不同于Android中的views. 在Flutter中你可以声明构造界面.
Flutter中的控件不能修改, 一直到它们需要改变. 当状态发生变更, Flutter的底层会重新创建一颗新的控件树实例. 而在Android中控件绘制一次就不再绘制, 直到invalidate被调用.
由于不可变性, Flutter的控件很轻量. 因为它们不是视图本身,也不是直接绘制任何东西,而是对UI及其语义的描述. 最终才会被构造成实际的试图对象.
二. Android控件
常用基础控件View, TextView, Button, ImageView, 其它控件如ProgressBar, SeekBar等.
这些控件都继承自View. 基础控件不够用时, 可继承这些控件实现自己想要的特性.
在android中存在5种基本布局

线性布局(LinearLayout)
相对布局(RelativeLayout)
表格布局(TableLayout)
帧布局(FrameLayout)
绝对布局(AbsoluteLayout)

TableLayout和AbsoluteLayout我基本没有用到. LinearLayout用于布局水平一行或者纵向一行.
FrameLayout用于布局有层次的界面, 可以简单设置居中. 更复杂控件间的相对关系使用RelativeLayout布局.
FrameLayout性能会好于RelativeLayout, 当FrameLayout无法解决的时候才用RelativeLayout
RelativeLayout通过相对关系也能布局出LinearLayout的界面, 但不如LinearLayout直观
列表可滑动滑动布局ScrollView/ListView/GridView/RecyclerView/ViewPager.
上述控件继承自ViewGroup, ViewGroup又继承于View 相对于继承View的控件, 前者内部可包含子控件, 而后者不行.前者一般会实现onLayout和onMeasure, 来控件子控件的布局和大小. 这些布局不够用时, 也可继承这些控件实现自己想要的特性.
上述所有控件都有的属性有

宽度(layout_width)
高度(layout_height)
背景(backgroud)
内间距(padding)
外间距(margin)
可见性(visibility)
位于父控件的位置(layout_gravity)
内部子控件的位置(gravity, 继承自ViewGroup的才有)
点击事件(onClick)
动画属性(alpha/rotation/scale)

三. Flutter控件
flutter中的控件非常多, 每一种布局只具备特定的特性. 功能划分的非常细. 最大的不同也正是这点, 基本控件不再拥有通用属性,比如背景, 点击事件等, 这些都被独立出来成为单独的控件.
举个简单例子如下
Android例子

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_gravity="center"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <TextView
        android:onClick="xxx"
        android:gravity="center"
        android:text="按钮"
        android:textSize="18sp"
        android:textColor="0xffffffff"
        android:layout_width="100dp"
        android:layout_height="40dp"
        android:background="0xff808080"/>
</LinearLayout>

Flutter例子

var layout = Column(
  children: <Widget>[
    GestureDetector(
      child: Container(
        width: 100.0,
        height: 40.0,
        color: Color(0xff808080),
        child: Center (
          child: Text(
            '按钮',
            style: TextStyle(
              color: Color(0xffffffff),
              fontSize: 18.0,
            ),
          ),
        )
      ),
      onTap: () {
        print('clicked');
      },
    ),
  ],
);

可以看出在Flutter中, 属性都被提取成一个控件了, GestureDetector负责处理点击事件, Container负责大小和背景, Center负责居中.Text仅仅只有文字相关的属性, 这样Android一个简单的控件在Flutter中需要嵌套很多层才能实现. 但好处就是划分的很细, 可以任意组合.
基本的显示控件有Text, Image, Icon, RaisedButton等.属性功能控件有Container, Padding, Center, Align, FittedBox等.这些都是Single-child控件. 就是child属性指向为Widget.
布局控件有Row, Column, Stack, IndexedStack, GridView, ListView等.这些都是Multi-child控件. 就是child属性指向为<Widget>[].
四. 实现自定义控件
在Android中通常是继承View或其它基于View的控件. 然后重写其中的方法, 来获取想要的行为.
在Flutter中, 你只需要组合各种小组件而不是继承. 某种程度上类似于实现Android中的一个自定义ViewGroup. 各种组件单元都已经存在, 你只是提供一种不同的行为, 比如, 重新定义布局逻辑.
举个例子: 你想实现一个在构造时获取文字的CustomButton. 你可以通过RaisedButton组合文字, 而不是继承RaisedButton.

class CustomButton extends StatelessWidget {
  final String label;

  CustomButton(this.label);

  @override
  Widget build(BuildContext context) {
    return RaisedButton(onPressed: () {}, child: Text(label));
  }
}

然后使用CustomButton就像跟其它Flutter组件一样:

@override
Widget build(BuildContext context) {
  return Center(
    child: CustomButton("Hello"),
  );
}

五. Android/Flutter映射表

Android|Flutter
---|---:
TextView|Text
ImageView|Image
Button|RaisedButton
LinearLayout|Row/Column
FrameLayout/RelativeLayout|Stack
ListView|ListView
GridView|GridView
ViewPager|PageView

上班两个小时后

image.png

就这一个图片里面的布局 我布局了半个小时 (0_0)
太特喵的尴尬了(没办法 刚开始学习 继续加油吧)
布局代码如下

 Widget message = new Container(
      margin: const EdgeInsets.only(left: 20,top: 30,right: 20),
      child: new Row(
        crossAxisAlignment: CrossAxisAlignment.center,
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        children: <Widget>[
          new Row(
            crossAxisAlignment: CrossAxisAlignment.center,
            children: <Widget>[
              new Image.network("https://upload.jianshu.io/users/upload_avatars/3753079/ae1e9a5b-1c4f-43c1-83d3-bbc9fcb2f734.jpg?imageMogr2/auto-orient/strip|imageView2/1/w/96/h/96",
                width:75,height: 75,fit: BoxFit.cover,),
              new Container(
                margin: const EdgeInsets.only(left: 15.0),
                child: new Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: <Widget>[
                    new Text("这里是名字"),
                    new Container(margin:const EdgeInsets.only(top: 8),
                      child: new Text("这里是信息"),
                    )
                  ],
                ),
              ),
            ],
          ),
          new Container(child: new Image.asset("images/jiantou.png",width: 5,height: 9,),
            alignment: Alignment.bottomCenter,
          )
        ],
      ),
    );

又半个小时之后

image.png
 Column thirdButton(String path,String label){
      Color color = Colors.black;
      return new Column(
        mainAxisSize: MainAxisSize.min,
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          new Image.asset(path,width: 21,height: 21,),
          new Container(
            margin: const EdgeInsets.only(top: 8.0),
            child: new Text(label,
              style: new TextStyle(
                  fontSize: 10,
                  fontWeight: FontWeight.w400,
                  color: color
              ),
            ),
          )
        ],
      );
    }
    
    Widget button = new Container(
      margin: const EdgeInsets.only(top: 30),
      child: new Row(
        mainAxisAlignment: MainAxisAlignment.spaceAround  ,
        children: <Widget>[
          thirdButton("images/email.png", "支部书记信箱"),
          thirdButton("images/follower.png", "收藏"),
          thirdButton("images/hoat_line.png", "在线交流")
        ],
      )
    );

又过了很长时间0.0 都忘记了要写简书了

这会儿写的也没什么 就是一个列表 然后用了不同的形式写出来了
就是吧本来组合到一起的控件拆分出来了 然后使用值判断是否显示某个控件 我把代码贴出来就好了

 /**
     * isShow  是否显示分割线
     */
    Container creatList(String label,bool isShow){
      Widget w =  new Container(
        margin: const EdgeInsets.only(top: 15,bottom: 15),
        child: new Text(label,
          style: new TextStyle(
              fontSize: 13.0
          ),

        ),
      );
      Widget d =  new Container(
        padding: const EdgeInsets.only(top: 1),
        color: value.defultColor,
      );
      List<Widget> ws = new List();
      ws.add(w);
      if(isShow) ws.add(d);
      Container container = new Container(
        margin: const EdgeInsets.only(left: 20),
        child: new Column(
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.start,
          children: ws
        )
      );
      return container;
    }

    Widget list = new Container(
      margin: const EdgeInsets.only(top: 16),
      color: Colors.white,
      child: new Column(
        children: <Widget>[
          creatList("我的信息", true),
          creatList("平台反馈", true),
          creatList("密码修改", true)
        ],
      ),
    );

上午用到的参数和函数(也有没有用的但是有关联的)

Row,Column->MainAxisAlignment
MainAxisAlignment.spaceBetween  //假设有1-2-3三个图片,居中,左边到1的间距,3到右边的间距为0,1-2,2-3之间间距相同

MainAxisAlignment.spaceAround  //假设有1-2-3三个图片,居中,1-2,2-3之间间距相同,且左边到1的间距,3到右边的间距的一半

MainAxisAlignment.spaceEvenly   //假设有1-2-3三个图片,居中,图片间距等值分配

MainAxisAlignment.start       //假设有1-2-3三个图片,居中及靠左,图片间距为0

MainAxisAlignment.end       //假设有1-2-3三个图片,居中及靠右,图片间距为0

MainAxisAlignment.center   //假设有1-2-3三个图片,居中,图片间距为0

new Center(
  child: new Column(
    mainAxisAlignment: MainAxisAlignment.center,  //需要依赖外层的Center,否则不生效
    children: <Widget>[
    new Text("you click:"),
    new Text('$count'),
  ],),
),

垂直方向
Row,Column->CrossAxisAlignment
CrossAxisAlignment.start       //假设有1-2-3三个图片,靠左及顶部,图片间距为0

CrossAxisAlignment.end       //假设有1-2-3三个图片,靠左及底部,图片间距为0

CrossAxisAlignment.center   //假设有1-2-3三个图片,居中及靠左,图片间距为0

水平方向
Container—–>alignment (对齐方式)
Alignment.topLeft   //假设一张图片,在一个比图大的布局里,则在布局里,靠左及顶部排列
Alignment.topCenter   //假设一张图片,在一个比图大的布局里,则在布局里,居中及顶部排列
Alignment.topRight   //假设一张图片,在一个比图大的布局里,则在布局里,靠右及顶部排列

上一篇 ---------------------------------------------下一篇

上一篇下一篇

猜你喜欢

热点阅读