【Flutter】開發之基礎Widget(三)

什麼是 Widget

Flutter 的核心設計思想即是一切即 Widget,在 Flutter 的世界裏,包括viewsviewcontrollerslayouts等在內的概念都創建在 Widget 之上,能夠理解成原生的Viewjava

lib/main.dart 是程序的主入口ios

//導包
import 'package:flutter/material.dart';
//程序入口
void main() => runApp(MyApp());
//至關於主頁面
class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue, 
      ),
      home: MyHomePage(title: 'Home Page'),
    );
  }
}
複製代碼

能夠看到,這個返回了一個MaterialAppWidget,做爲程序的主界面。數組

父級組件

Widget 介紹
StatelessWidget 無狀態widget,相似靜態頁面,不與用戶交互
StatefulWidget 有狀態widget,能夠改變,能夠與用戶交互

基礎組件

Widget 介紹
MaterialApp 通常用做APP頂層的主頁入口,可配置主題,多語言,路由等
Scaffold 通常用戶頁面的承載Widget,包含appbar、snackbar、drawer等material design的設定。
Appbar 通常用於Scaffold的appbar ,內有標題,二級頁面返回按鍵等,固然不止這些,tabbar等也會須要它
Text 顯示文本,相似於TextView
Image 顯示圖片,能夠加載本地資源、file、網絡圖片、內存圖片
TextField 輸入框,相似於EditText
  • Text
Text(
          //文本
          '我是Text我是Text我是Text我是Text我是Text我是Text我是Text我是Text我是Text我是Text',
          //超出屏幕 clip裁剪,fade漸隱,ellipsis省略號
          overflow: TextOverflow.ellipsis,
          //對齊方式
          textAlign: TextAlign.center,
          //文本方向
          textDirection: TextDirection.rtl,
          //樣式
          style: TextStyle(
            color: Colors.lightBlue,
            fontSize: 14,
            fontStyle: FontStyle.italic,
            backgroundColor: Colors.black87,
            //none無文字裝飾,lineThrough刪除線,overline文字上面顯示線,underline文字下面顯示線
            decoration: TextDecoration.lineThrough,
            //字母間隙
            letterSpacing: 10,
          ),
        )
複製代碼

image.png

  • Image
方法 做用
Image.assetImage(image: new AssetImage() 加載本地圖片
Image.fileImage(image: new FileImage() file
Image.memoryImage(image: new MemoryImage() 加載內存byte數組
Image.networkImage(image: new NetworkImage() 加載網絡圖片

其中,asset首先須要在根目錄下創建images文件夾,而後在pubspec.yaml文件中添加引用才能使用網絡

flutter:
  uses-material-design: true
  assets:
    - images/ic_launcher.png
複製代碼
Image.asset(
                'images/ic_launcher.png',
                width: 100,
                height: 100,
                fit: BoxFit.fitHeight,
              ),

              Image(
                image: new NetworkImage(
                    'http://n.sinaimg.cn/sports/2_img/upload/cf0d0fdd/107/w1024h683/20181128/pKtl-hphsupx4744393.jpg'),
                width: 100,
                height: 100,
                fit: BoxFit.cover,
              )
複製代碼

image.png

  • TextField
TextField(
            //鍵盤輸入方式
            keyboardType: TextInputType.number,
            decoration: InputDecoration(
              //提示文字
              hintText: '請輸入手機號',
              //內容邊距
              contentPadding: EdgeInsets.all(10),
              //提示文字樣式
              hintStyle:
                  TextStyle(color: Colors.deepOrangeAccent, fontSize: 18),
              //邊框
              border: OutlineInputBorder(
                //圓角
                borderRadius: BorderRadius.all(Radius.circular(4)),
                borderSide: BorderSide(color: Colors.deepOrange),
              ),
            ),
            //文字改變時調用
            onChanged: (String content) {
              print("content=" + content);
            },
            //光標顏色
            cursorColor: Colors.deepOrangeAccent,
            //光標圓角
            cursorRadius: Radius.circular(4),
            //光標寬度
            cursorWidth: 2,
          )
複製代碼

佈局型

Widget 多個子Widget 介紹
Container 默認充滿,包含了padding、margin、color、寬高、decoration 等配置
Padding 用於設置padding,對,你沒有猜錯,絕大部分Widget是沒有padding屬性的
Center 用於居中顯示
Column 垂直佈局,相似於LinearLayout 的orientation="vertical"
Row 水平佈局,相似於LinearLayout 的orientation="horizontal"
Stack 相似於relativeLayout 或者FrameLayout
ListView 相似於ListView或者RecyclerView
  • Container
  • Padding
  • Column
  • Row
class ContainerDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('ContainerDemo'),
      ),
      body: Container(
        margin: EdgeInsets.all(10),
        padding: EdgeInsets.only(left: 10, right: 20),
// color: Colors.orangeAccent,
        decoration: new BoxDecoration(
            //設置了decoration的color,就不能設置Container的color,不然會報錯
            color: Colors.white,
            borderRadius: BorderRadius.all(Radius.circular(10)),
            border: new Border.all(width: 10, color: Colors.blue)),
        child: Column(
          //Column 垂直方向,Row 水平方向
          mainAxisAlignment: MainAxisAlignment.center,
          //max至關於match_parent,min至關於wrap_content
          mainAxisSize: MainAxisSize.max,
          verticalDirection: VerticalDirection.up,
          children: <Widget>[
            Container(
              padding: EdgeInsets.all(10),
              margin: EdgeInsets.all(20),
              color: Colors.black54,
              child: Text(
                '1111111',
              ),
            ),
            Text(
              '111FFFFg',
              style: TextStyle(
                fontSize: 18,
                backgroundColor: Colors.black54,
              ),
            ),
            Text('222'),
            Text('333'),
          ],
        ),
      ),
    );
  }
}
複製代碼
  • Stack

Stack 相似於relativeLayout 或者FrameLayout,有2種定位方式app

1.alignment 做用因而所有的子Widgetless

class StackDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.white,
      child: Stack(
        textDirection: TextDirection.ltr,
        //以整個組件的中心爲座標原點,x、y 偏移量取值範圍爲 [-1,1],
        // 若是 x 的偏移量大於 0,則表示向右偏移,小於 0 則向左偏移;
        // 若是 y 軸的偏移量大於 0 則向下偏移,小於 0 則向上偏移。
// alignment: Alignment(0, 0),
        //AlignmentDirectional.topStart:垂直靠頂部水平靠左對齊
        //AlignmentDirectional.topCenter:垂直靠頂部水平居中對齊
        //AlignmentDirectional.topEnd:垂直靠頂部水平靠右對齊
        //AlignmentDirectional.centerStart:垂直居中水平靠左對齊
        //AlignmentDirectional.center:垂直和水平居中都對齊
        //AlignmentDirectional.centerEnd:垂直居中水平靠右對齊
        //AlignmentDirectional.bottomStart:垂直靠底部水平靠左對齊
        //AlignmentDirectional.bottomCenter:垂直靠底部水平居中對齊
        //AlignmentDirectional.bottomEnd:垂直靠底部水平靠右對齊
        alignment: AlignmentDirectional.centerEnd,
        children: <Widget>[
          Container(
            color: Colors.black54,
            child: Text(
              '1111111',
            ),
          ),
          Text('111FFFFg',
              style: TextStyle(fontSize: 18, backgroundColor: Colors.black54)),
          Text('22222222')
        ],
      ),
    );
  }
}
複製代碼

image.png
2. Positioned 只能控制單個 Widget,主要有 leftrighttopbottomwidthheight幾個屬性,分別表示距左、右、上、下的邊距,長度和寬度

注意:ide

1)leftright並存時,left生效;topbottom並存時,top生效佈局

2)leftrightwidth不能並存,topbottomheight不能並存,會報錯ui

class StackDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.white,
      child: Stack(
        textDirection: TextDirection.ltr,
       children: <Widget>[
          Container(
            color: Colors.black54,
            child: Text(
              '1111111',
            ),
          ),
          Positioned(
            top: 100,
            child: Text(
              '111FFFFg',
              style: TextStyle(
                fontSize: 18,
                backgroundColor: Colors.black54,
              ),
            ),
          ),
          Positioned(
            child: Text('22222222'),
            right: 10,
            top: 200,
          )
        ],
      ),
    );
  }
}
複製代碼

image.png

  • ListView

主要有3種構造方式 ListView.builder ListView.separated ListView.customspa

1.ListView.builder

使用自帶的item --ListTile

class ListViewDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('ListViewDemo'),
        centerTitle: true,
      ),
      body: Container(
        color: Colors.white,
        child: ListView.builder(
          //item
          itemBuilder: (context, index) {
            return ListTile(
              //前置圖標
              leading: new Icon(Icons.list),
              title: new Text('標題'),
              subtitle: new Text('副標題'),
              //後置圖標
              trailing: new Icon(Icons.arrow_forward_ios),
              //內容邊距
              contentPadding: EdgeInsets.all(10),
            );
          },
          //數量
          itemCount: 10,
          //內容適配
          shrinkWrap: true,
          //內邊距
          padding: EdgeInsets.only(left: 10),
          //是否倒敘
          reverse: false,
          //item 高度 讓item加載更加高效
          itemExtent: 50,

          //滑動方式
          //AlwaysScrollableScrollPhysics() 老是能夠滑動
          //NeverScrollableScrollPhysics禁止滾動
          //BouncingScrollPhysics 內容超過一屏 上拉有回彈效果
          //ClampingScrollPhysics 包裹內容 不會有回彈
          physics: BouncingScrollPhysics(),
          //預加載
          cacheExtent: 10,
        ),
      ),
    );
  }
}
複製代碼

image.png
2. ListView.separated

至關於原生中的多類型,核心是separatorBuilder,與itemBuilder是一同渲染的,能夠用它來實現分割線

ListView.separated(
          itemBuilder: (context, index) {
            return ListTile(
              //前置圖標
              leading: new Icon(Icons.list),
              title: new Text('標題'),
              subtitle: new Text('副標題'),
              //後置圖標
              trailing: new Icon(Icons.arrow_forward_ios),
              //內容邊距
              contentPadding: EdgeInsets.all(10),
            );
          },
          separatorBuilder: (context, index) {
            return Divider(
              color: Colors.black45,
              height: 10,
              //左邊縮進
              indent: 50,
            );
          },
          itemCount: 20,
        )
複製代碼

image.png
3. ListView.custom

前2種方式是此方式的快捷方式,雖然不經常使用,但仍是要了解下

ListView.custom(
          childrenDelegate: SliverChildBuilderDelegate((context, index) {
            return ListTile(
              //前置圖標
              leading: new Icon(Icons.list),
              title: new Text('標題 custom'),
              subtitle: new Text('副標題 custom'),
              //後置圖標
              trailing: new Icon(Icons.arrow_forward_ios),
              //內容邊距
              contentPadding: EdgeInsets.all(10),
            );
          }),
        )
複製代碼

效果同方式1

示例

模擬器上間隔線顯示有問題,真機正常

image.png
ListViewDemo相關代碼

class ListViewDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('ListViewDemo'),
        centerTitle: true,
      ),
      body: Container(
        color: Colors.white,
        child: ListView.separated(
          itemBuilder: ((context, index) {
            return MoveItem();
          }),
          separatorBuilder: (context, index) {
            return Divider(
              color: Colors.black45,
              height: 10,
            );
          },
          itemCount: 10,
        ),
      ),
    );
  }
}
複製代碼

MoveItem相關代碼

class MoveItem extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      margin: EdgeInsets.all(4),
      child: Row(
        children: <Widget>[
          ClipRRect(
            borderRadius: BorderRadius.circular(4),
            child: Image.network(
              'http://n.sinaimg.cn/sports/2_img/upload/cf0d0fdd/107/w1024h683/20181128/pKtl-hphsupx4744393.jpg',
              width: 100,
              height: 150,
              fit: BoxFit.fill,
            ),
          ),
          Padding(
            padding: EdgeInsets.only(left: 15),
          ),
          Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            mainAxisAlignment: MainAxisAlignment.spaceAround,
            children: <Widget>[
              Text(
                '狄仁傑之四大天王',
                style: TextStyle(fontSize: 22, fontWeight: FontWeight.bold),
              ),
              Text('豆瓣評分6.6'),
              Text('類型:動做、驚悚、冒險'),
              Text('導演:徐克'),
              Row(
                children: <Widget>[
                  Text('主演:'),
                  Padding(
                    padding: EdgeInsets.only(left: 10),
                  ),
                  Container(
                    width: 40,
                    height: 40,
                    child: CircleAvatar(
                      backgroundImage: NetworkImage(
                          'http://n.sinaimg.cn/sports/2_img/upload/cf0d0fdd/107/w1024h683/20181128/pKtl-hphsupx4744393.jpg'),
                    ),
                  ),
                  Container(
                    width: 40,
                    height: 40,
                    margin: EdgeInsets.only(left: 10),
                    child: CircleAvatar(
                      backgroundImage: NetworkImage(
                          'http://n.sinaimg.cn/sports/2_img/upload/cf0d0fdd/107/w1024h683/20181128/pKtl-hphsupx4744393.jpg'),
                    ),
                  ),
                  Container(
                    width: 40,
                    height: 40,
                    margin: EdgeInsets.only(left: 10),
                    child: CircleAvatar(
                      backgroundImage: NetworkImage(
                          'http://n.sinaimg.cn/sports/2_img/upload/cf0d0fdd/107/w1024h683/20181128/pKtl-hphsupx4744393.jpg'),
                    ),
                  ),
                ],
              ),
            ],
          ),
        ],
      ),
    );
  }
}
複製代碼

你的承認,是我堅持更新博客的動力,若是以爲有用,就請點個贊,謝謝

相關文章
相關標籤/搜索