Flutter 12: 圖解圓形與權(quán)重/比例小嘗試

??????小菜今天搭建了一個(gè)很丑的【簽到】小頁(yè)面,頁(yè)面很簡(jiǎn)單,只有寥寥幾個(gè)控件,但小菜想通過(guò)這個(gè)簡(jiǎn)單的小頁(yè)面學(xué)習(xí)一下權(quán)重/比例的使用方式,順便也學(xué)習(xí)了一下如何繪制圓形效果。

繪制圓形

??????小菜為了頁(yè)面稍微美觀一點(diǎn),準(zhǔn)備用圓形來(lái)替換普通的按鈕,小菜發(fā)現(xiàn) Flutter 提供了很多便捷的繪制圓形的方式,比 Android 要方便很多。小菜測(cè)試時(shí)用到了如下兩種:

ClipOval

??????ClipOval 是一個(gè)很強(qiáng)大的裁剪子控件為橢圓或圓角的控件;子控件沒(méi)有特殊限制。同時(shí)衍生出其他幾種裁剪方式:

  1. CustomClipper:可以創(chuàng)建自定義裁剪方式;
  2. ClipRect:可以裁剪不同寬高比例,通過(guò) heightFactor 屬性來(lái)處理;
  3. ClipRRect:可以設(shè)置圓角矩形或圓形;
  4. ClipPath:可以為任意形狀的裁剪方式;
new ClipOval(
   child: new SizedBox(
      width: 100.0,
      height: 100.0,
      // 子控件為網(wǎng)絡(luò)圖片
      child: new Image.network(
         "https://...pic.jpg",
         fit: BoxFit.fill,
      ),
      // 子控件為 Container
//     child: new Container( color: Colors.redAccent, ),
   ),
),
// 圓角矩形
new ClipRRect(
  borderRadius: const BorderRadius.all(const Radius.circular(30.0)),
  child: new Container(
    width: 90.0,
    height: 90.0,
    color: Colors.red,
  ),
),),
// heightFactor 為高/寬比例
new ClipRect(
  child: new Align(
    alignment: Alignment.topCenter,
    heightFactor: 1.0,
    child: new Container(color: Colors.yellow,height:90.0,width: 90.0,),
  ),
)
CircleAvatar

??????小菜以為 CircleAvatar 是繪制正圓最方便的方式,Flutter 直接提供的繪制圓形的控件,可添加背景色及背景圖;且在加載網(wǎng)絡(luò)圖片時(shí),網(wǎng)絡(luò)狀態(tài)不佳或圖片有問(wèn)題時(shí)只顯示背景色,更人性化。

// 只有背景色
new CircleAvatar(
  backgroundColor: Colors.greenAccent,
  radius: 90.0,
),
// 添加背景圖
new Align(
   alignment: Alignment.center,
   child: new CircleAvatar(
      backgroundImage: new NetworkImage("https://...pic.jpg"),
      backgroundColor: Colors.greenAccent,
      radius: 90.0,
   ),
),

權(quán)重/比例

??????小菜在 Android 開(kāi)發(fā)過(guò)程中為了適配不同機(jī)型,常用到權(quán)重 android:weight,這樣在均分布局時(shí)起到重要作用;小菜尚在 Flutter 中沒(méi)有直接發(fā)現(xiàn) weight 的身影,Flutter 常用 RowColumn 來(lái)設(shè)置橫向和縱向布局。小菜發(fā)現(xiàn)可以通過(guò)如下方式來(lái)處理權(quán)重/比例。

Flexible

??????Flexible 默認(rèn)也是讓子控件占滿填充整個(gè)父類布局,Flexible 中的 flex 屬性可以調(diào)整,若兩個(gè) Flexible 控件 A/B,A 中 flex 設(shè)為 2,B 中 flex 設(shè)為 1,則整個(gè)布局中 A:B=2:1 整體占滿整個(gè)布局。

new Row(
  children: <Widget>[
    new Flexible(
      child: new Container(
        color: Colors.redAccent,
        height: 40.0,
      ),
      flex: 1,
    ),
    new Flexible(
      child: new Container(
        color: Colors.blueAccent,
        height: 40.0,
      ),
      flex: 2,
    ),
  ],
),
Expanded

??????Expanded 默認(rèn)讓子控件占滿填充整個(gè)父類布局,Expanded 中的 flex 屬性為1,而 Expanded 繼承的是 Flexible;Flexible 支持的分割布局權(quán)重的方式 Expanded 也一樣,而與 Flexible 不同的是默認(rèn)會(huì)將子控件充滿布局。

new Row(
  children: <Widget>[
    new Expanded(
      child: new Container(
        color: Colors.redAccent,
        height: 40.0,
      ),
      flex: 2,
    ),
    new Expanded(
      child: new Container(
        color: Colors.blueAccent,
        height: 40.0,
      ),
      flex: 1,
    ),
  ],
),

??????無(wú)論時(shí) Expanded 還是 Flexible 小菜都建議依靠 RowColumn 共同使用。小菜測(cè)試,兩者一起使用也不會(huì)太大影響。

主要源碼

class ItemSignPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new Container(
      child: new Column(
        children: <Widget>[
          new Container(
            height: 10.0,
          ),
          new Flexible(
            child: new Container(
              child: new Row(children: <Widget>[
                new Flexible(
                  child: new Container(),
                  flex: 1,
                ),
                new Container(
                  width: 16.0,
                  height: 1.0,
                ),
                new Container(
                  width: 1.0,
                  color: Colors.blueAccent,
                ),
                new Container(
                  width: 16.0,
                  height: 1.0,
                  color: Colors.blueAccent,
                ),
                new Flexible(
                  child: new Container(
                    child: buildListData(
                        context, Color.fromARGB(40, 50, 40, 80), '上班簽到'),
                  ),
                  flex: 1,
                ),
              ]),
            ),
            flex: 1,
          ),
          new Flexible(
            child: new Container(
              child: new Row(children: <Widget>[
                new Flexible(
                  child: new Container(
                    child: buildListData(context, Colors.greenAccent, '下班簽退'),
                  ),
                  flex: 1,
                ),
                new Container(
                  width: 16.0,
                  height: 1.0,
                  color: Colors.blueAccent,
                ),
                new Container(
                  width: 1.0,
                  color: Colors.blueAccent,
                ),
                new Container(
                  width: 16.0,
                  height: 1.0,
                ),
                new Flexible(
                  child: new Container(),
                  flex: 1,
                ),
              ]),
            ),
            flex: 1,
          ),
          new Container(
            height: 60.0,
            child: new Center(
              child: new Text(
                '請(qǐng)及時(shí)簽到哦~',
                style: new TextStyle(color: Colors.blue, fontSize: 16.0),
              ),
            ),
          ),
        ],
      ),
    );
  }

  Widget buildListData(BuildContext context, Color color, String text) {
    return new Center(
      child: new GestureDetector(
        child: new CircleAvatar(
          backgroundColor: color,
          radius: 72.0,
          child: new Text(
            text,
            style: new TextStyle(color: Colors.blue, fontSize: 18.0),
          ),
        ),
        onTap: () {
          showDialog(
            context: context,
            builder: (BuildContext context) {
              return new AlertDialog(
                title: new Text(
                  '溫馨提示',
                  style: new TextStyle(
                    color: Colors.black54,
                    fontSize: 18.0,
                  ),
                ),
                content: new Text('您點(diǎn)擊的item內(nèi)容為:$text'),
              );
            },
          );
        },
      ),
    );
  }
}

??????小菜剛接觸 Flutter 時(shí)間不長(zhǎng),還有很多不清楚和不理解的地方,如果又不對(duì)的地方還希望多多指出。

來(lái)源:阿策小和尚

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容