Flutter實(shí)戰(zhàn) 變換(Transform)

2021-03-08 10:35 更新

Transform可以在其子組件繪制時(shí)對(duì)其應(yīng)用一些矩陣變換來實(shí)現(xiàn)一些特效。Matrix4是一個(gè) 4D 矩陣,通過它我們可以實(shí)現(xiàn)各種矩陣操作,下面是一個(gè)例子:

Container(
  color: Colors.black,
  child: new Transform(
    alignment: Alignment.topRight, //相對(duì)于坐標(biāo)系原點(diǎn)的對(duì)齊方式
    transform: new Matrix4.skewY(0.3), //沿Y軸傾斜0.3弧度
    child: new Container(
      padding: const EdgeInsets.all(8.0),
      color: Colors.deepOrange,
      child: const Text('Apartment for rent!'),
    ),
  ),
);

運(yùn)行效果如圖5-10所示:

圖5-10

關(guān)于矩陣變換的相關(guān)內(nèi)容屬于線性代數(shù)范疇,本書不做討論,讀者有興趣可以自行了解。本書中,我們把焦點(diǎn)放在 Flutter 中一些常見的變換效果上。另外,由于矩陣變化時(shí)發(fā)生在繪制時(shí),而無需重新布局和構(gòu)建等過程,所以性能很好。

#平移

Transform.translate接收一個(gè)offset參數(shù),可以在繪制時(shí)沿xy軸對(duì)子組件平移指定的距離。

DecoratedBox(
  decoration:BoxDecoration(color: Colors.red),
  //默認(rèn)原點(diǎn)為左上角,左移20像素,向上平移5像素  
  child: Transform.translate(
    offset: Offset(-20.0, -5.0),
    child: Text("Hello world"),
  ),
)

效果如圖5-11所示:

#旋轉(zhuǎn)

Transform.rotate可以對(duì)子組件進(jìn)行旋轉(zhuǎn)變換,如:

DecoratedBox(
  decoration:BoxDecoration(color: Colors.red),
  child: Transform.rotate(
    //旋轉(zhuǎn)90度
    angle:math.pi/2 ,
    child: Text("Hello world"),
  ),
);

注意:要使用math.pi需先進(jìn)行如下導(dǎo)包。

import 'dart:math' as math;  

效果如圖5-12所示:

#縮放

Transform.scale可以對(duì)子組件進(jìn)行縮小或放大,如:

DecoratedBox(
  decoration:BoxDecoration(color: Colors.red),
  child: Transform.scale(
      scale: 1.5, //放大到1.5倍
      child: Text("Hello world")
  )
);

效果如圖5-13所示:

#注意

  • Transform的變換是應(yīng)用在繪制階段,而并不是應(yīng)用在布局(layout)階段,所以無論對(duì)子組件應(yīng)用何種變化,其占用空間的大小和在屏幕上的位置都是固定不變的,因?yàn)檫@些是在布局階段就確定的。下面我們具體說明:

   Row(
    mainAxisAlignment: MainAxisAlignment.center,
    children: <Widget>[
      DecoratedBox(
        decoration:BoxDecoration(color: Colors.red),
        child: Transform.scale(scale: 1.5,
            child: Text("Hello world")
        )
      ),
      Text("你好", style: TextStyle(color: Colors.green, fontSize: 18.0),)
    ],
  )

運(yùn)行效果如圖5-14所示:

由于第一個(gè)Text應(yīng)用變換(放大)后,其在繪制時(shí)會(huì)放大,但其占用的空間依然為紅色部分,所以第二個(gè)Text會(huì)緊挨著紅色部分,最終就會(huì)出現(xiàn)文字重合。

  • 由于矩陣變化只會(huì)作用在繪制階段,所以在某些場(chǎng)景下,在 UI 需要變化時(shí),可以直接通過矩陣變化來達(dá)到視覺上的UI改變,而不需要去重新觸發(fā) build 流程,這樣會(huì)節(jié)省 layout 的開銷,所以性能會(huì)比較好。如之前介紹的Flow組件,它內(nèi)部就是用矩陣變換來更新 UI,除此之外,F(xiàn)lutter 的動(dòng)畫組件中也大量使用了Transform以提高性能。

思考題:使用Transform對(duì)其子組件先進(jìn)行平移然后再旋轉(zhuǎn)和先旋轉(zhuǎn)再平移,兩者最終的效果一樣嗎?為什么?

#RotatedBox

RotatedBoxTransform.rotate功能相似,它們都可以對(duì)子組件進(jìn)行旋轉(zhuǎn)變換,但是有一點(diǎn)不同:RotatedBox的變換是在 layout 階段,會(huì)影響在子組件的位置和大小。我們將上面介紹Transform.rotate時(shí)的示例改一下:

Row(
  mainAxisAlignment: MainAxisAlignment.center,
  children: <Widget>[
    DecoratedBox(
      decoration: BoxDecoration(color: Colors.red),
      //將Transform.rotate換成RotatedBox  
      child: RotatedBox(
        quarterTurns: 1, //旋轉(zhuǎn)90度(1/4圈)
        child: Text("Hello world"),
      ),
    ),
    Text("你好", style: TextStyle(color: Colors.green, fontSize: 18.0),)
  ],
),

效果如圖5-15所示:

由于RotatedBox是作用于 layout 階段,所以子組件會(huì)旋轉(zhuǎn)90度(而不只是繪制的內(nèi)容),decoration會(huì)作用到子組件所占用的實(shí)際空間上,所以最終就是上圖的效果,讀者可以和前面Transform.rotate示例對(duì)比理解。

以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)