Widget

1.1:Widget的狀態(tài)
  • Widget的本身沒有可變狀態(tài)(所有字段都必須是final)括蝠。

  • 如果您希望將一個widget擁有可變狀態(tài)没龙,請考慮使用 StatefulWidget憎瘸,每當(dāng)它被加載為元素并合并到渲染樹中時虫碉,會創(chuàng)建State對象(通過StatefulWidget.createState)寓免。

  • StatefulWidget和State苞俘,用于可以在其生命周期內(nèi)多次構(gòu)建的widget盹沈。

  • StatelessWidget,用于在給定配置和環(huán)境的狀態(tài)的下始終以相同方式構(gòu)建的widget吃谣。

1.2: StatelessWidget 無狀態(tài)組件

該類的本身非常簡潔,由于Widget有一個createElement抽象方法乞封,
StatelessWidget類中通過StatelessElement對象完成了該抽象方法,
所以StatelessWidget只需要關(guān)注build這個抽象方法即可。


Stateless.png

初始項目中,MyApp是繼承了StatelessWidget岗憋,它的任務(wù)在于重寫build方法肃晚。

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}
1.3:StatefulWidget有狀態(tài)組件
Stateful.png
class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

//State對象中有一個泛型,從源碼中來看仔戈,該泛型值接受StatefulWidget关串,
//即有狀態(tài)組件類拧廊。State作為一個抽象類,存在一個build抽象方法來返回一個Widget對象
class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),//widget屬性其實就是MyHomePage
      ),
     //略...
    );
  }
}
Icon源碼

Icon類中主要做了四件事:
構(gòu)造函數(shù)--> 聲明屬性字段--> 實現(xiàn)build方法晋修,返回Widget對象-->debugFillProperties

class Icon extends StatelessWidget {
  const Icon(
    this.icon, {
    Key key,
    this.size,
    this.color,
    this.semanticLabel,
    this.textDirection,
  }) : super(key: key);

  final IconData icon;
  final double size;
  final Color color;
  final String semanticLabel;
  final TextDirection textDirection;

  @override
  Widget build(BuildContext context) {
    //暫略...
  }

  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    //暫略...
  }
}

可以看出吧碾,構(gòu)造函數(shù)中有一個必須的參數(shù)icon,從定義中來看是一個IconData對象

注意:構(gòu)造函數(shù)用const關(guān)鍵字修飾,字段全被修飾為final飞蚓,這就意味著字段不可再修改滤港。

這也是被稱為無狀態(tài)的原因,一旦對象構(gòu)建完成趴拧,它就樣子就無法再被改變溅漾。

CheckBox源碼簡析
class Checkbox extends StatefulWidget {
  const Checkbox({
    Key key,
    @required this.value,
    this.tristate = false,
    @required this.onChanged,
    this.activeColor,
    this.checkColor,
    this.materialTapTargetSize,
  }) : assert(tristate != null),
       assert(tristate || value != null),
       super(key: key);

  final bool value;//是否選中
  final ValueChanged<bool> onChanged;//點擊回調(diào)
  final Color activeColor;//激活態(tài)框顏色
  final Color checkColor;//激活態(tài)對勾顏色
  final bool tristate;//三態(tài)
  final MaterialTapTargetSize materialTapTargetSize;
  static const double width = 18.0;

  @override
  _CheckboxState createState() => _CheckboxState();
}
  • 1.構(gòu)造函數(shù)用const修飾,每行寫一個屬性
  • 2.必須的屬性用@required注解
  • 3.非空的屬性用assert斷言
  • 4.字段全是final類型

_CheckboxState中的build方法返回_CheckboxRenderObjectWidget對象
CheckBox具體繪制邏輯及狀態(tài)改變,在_RenderCheckbox中實現(xiàn)

---->[flutter/packages/flutter/lib/src/material/checkbox.dart:140]----
class _CheckboxState extends State<Checkbox> with TickerProviderStateMixin {
  @override
  Widget build(BuildContext context) {
        //略...
    }
    return _CheckboxRenderObjectWidget(
      //略...
    );
  }
}

---->[flutter/packages/flutter/lib/src/material/checkbox.dart:168]----
class _CheckboxRenderObjectWidget extends LeafRenderObjectWidget {
    //略...
  @override
  _RenderCheckbox createRenderObject(BuildContext context) => _RenderCheckbox(
    //略...
  );

  @override
  void updateRenderObject(BuildContext context, _RenderCheckbox renderObject) {
    //略...
  }

_RenderCheckbox繼承自RenderToggleable著榴,可以重寫paint方法
這邊簡單看一下主要的邊框和對勾的繪制方法

 // 可以看出畫筆的顏色是checkColor添履,以線條的形式
 void _initStrokePaint(Paint paint) {
   paint
     ..color = checkColor
     ..style = PaintingStyle.stroke
     ..strokeWidth = _kStrokeWidth;
 }
 
//繪制邊線
void _drawBorder(Canvas canvas, RRect outer, double t, Paint paint) {
  assert(t >= 0.0 && t <= 0.5);
  final double size = outer.width;
  // 當(dāng)t從0.0到1.0時,逐漸填充外部矩形脑又。
  final RRect inner = outer.deflate(math.min(size / 2.0, _kStrokeWidth + size * t));
  canvas.drawDRRect(outer, inner, paint);
}

//繪制對勾
void _drawCheck(Canvas canvas, Offset origin, double t, Paint paint) {
  assert(t >= 0.0 && t <= 1.0);
  final Path path = Path();
  const Offset start = Offset(_kEdgeSize * 0.15, _kEdgeSize * 0.45);//起始偏移點
  const Offset mid = Offset(_kEdgeSize * 0.4, _kEdgeSize * 0.7);//中間偏移點
  const Offset end = Offset(_kEdgeSize * 0.85, _kEdgeSize * 0.25);//終止偏移點
  if (t < 0.5) {//t<0.5時暮胧,繪制短邊
    final double strokeT = t * 2.0;
    final Offset drawMid = Offset.lerp(start, mid, strokeT);
    path.moveTo(origin.dx + start.dx, origin.dy + start.dy);
    path.lineTo(origin.dx + drawMid.dx, origin.dy + drawMid.dy);
  } else {//t>0.5時,繪制長邊
    final double strokeT = (t - 0.5) * 2.0;
    final Offset drawEnd = Offset.lerp(mid, end, strokeT);
    path.moveTo(origin.dx + start.dx, origin.dy + start.dy);
    path.lineTo(origin.dx + mid.dx, origin.dy + mid.dy);
    path.lineTo(origin.dx + drawEnd.dx, origin.dy + drawEnd.dy);
  }
  canvas.drawPath(path, paint);
}

參考鏈接:https://juejin.im/post/5d22752c6fb9a07f04206a18

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末问麸,一起剝皮案震驚了整個濱河市往衷,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌严卖,老刑警劉巖席舍,帶你破解...
    沈念sama閱讀 223,207評論 6 521
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異哮笆,居然都是意外死亡来颤,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,455評論 3 400
  • 文/潘曉璐 我一進(jìn)店門稠肘,熙熙樓的掌柜王于貴愁眉苦臉地迎上來福铅,“玉大人,你說我怎么就攤上這事项阴』” “怎么了?”我有些...
    開封第一講書人閱讀 170,031評論 0 366
  • 文/不壞的土叔 我叫張陵环揽,是天一觀的道長拷沸。 經(jīng)常有香客問我,道長薯演,這世上最難降的妖魔是什么撞芍? 我笑而不...
    開封第一講書人閱讀 60,334評論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮跨扮,結(jié)果婚禮上序无,老公的妹妹穿的比我還像新娘验毡。我一直安慰自己,他們只是感情好帝嗡,可當(dāng)我...
    茶點故事閱讀 69,322評論 6 398
  • 文/花漫 我一把揭開白布晶通。 她就那樣靜靜地躺著,像睡著了一般哟玷。 火紅的嫁衣襯著肌膚如雪狮辽。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,895評論 1 314
  • 那天巢寡,我揣著相機(jī)與錄音喉脖,去河邊找鬼。 笑死抑月,一個胖子當(dāng)著我的面吹牛树叽,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播谦絮,決...
    沈念sama閱讀 41,300評論 3 424
  • 文/蒼蘭香墨 我猛地睜開眼题诵,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了层皱?” 一聲冷哼從身側(cè)響起性锭,我...
    開封第一講書人閱讀 40,264評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎叫胖,沒想到半個月后草冈,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,784評論 1 321
  • 正文 獨居荒郊野嶺守林人離奇死亡臭家,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,870評論 3 343
  • 正文 我和宋清朗相戀三年疲陕,在試婚紗的時候發(fā)現(xiàn)自己被綠了方淤。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片钉赁。...
    茶點故事閱讀 40,989評論 1 354
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖携茂,靈堂內(nèi)的尸體忽然破棺而出你踩,到底是詐尸還是另有隱情,我是刑警寧澤讳苦,帶...
    沈念sama閱讀 36,649評論 5 351
  • 正文 年R本政府宣布带膜,位于F島的核電站,受9級特大地震影響鸳谜,放射性物質(zhì)發(fā)生泄漏膝藕。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,331評論 3 336
  • 文/蒙蒙 一咐扭、第九天 我趴在偏房一處隱蔽的房頂上張望芭挽。 院中可真熱鬧滑废,春花似錦、人聲如沸袜爪。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,814評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽辛馆。三九已至俺陋,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間昙篙,已是汗流浹背腊状。 一陣腳步聲響...
    開封第一講書人閱讀 33,940評論 1 275
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留瓢对,地道東北人寿酌。 一個月前我還...
    沈念sama閱讀 49,452評論 3 379
  • 正文 我出身青樓,卻偏偏與公主長得像硕蛹,于是被迫代替她去往敵國和親醇疼。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,995評論 2 361

推薦閱讀更多精彩內(nèi)容