ex_widget.dart 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835
  1. import 'package:flutter/gestures.dart';
  2. import 'package:flutter/material.dart';
  3. import 'package:flutter/semantics.dart';
  4. import 'package:shared/utils/ext_dart.dart';
  5. /// 手势 tap
  6. typedef GestureOnTapChangeCallback = void Function<T>(T val);
  7. //点击防抖类型
  8. enum ClickType { none, throttle, debounce }
  9. extension WidgetPaddingX on Widget {
  10. Widget paddingAll(double padding) =>
  11. Padding(padding: EdgeInsets.all(padding), child: this);
  12. Widget paddingSymmetric({double horizontal = 0.0, double vertical = 0.0}) =>
  13. Padding(
  14. padding:
  15. EdgeInsets.symmetric(horizontal: horizontal, vertical: vertical),
  16. child: this);
  17. Widget paddingOnly({
  18. double left = 0.0,
  19. double top = 0.0,
  20. double right = 0.0,
  21. double bottom = 0.0,
  22. }) =>
  23. Padding(
  24. padding: EdgeInsets.only(
  25. top: top, left: left, right: right, bottom: bottom),
  26. child: this);
  27. Widget get paddingZero => Padding(padding: EdgeInsets.zero, child: this);
  28. }
  29. /// Add margin property to widget
  30. extension WidgetMarginX on Widget {
  31. Widget marginAll(double margin) =>
  32. Container(margin: EdgeInsets.all(margin), child: this);
  33. Widget marginSymmetric({double horizontal = 0.0, double vertical = 0.0}) =>
  34. Container(
  35. margin:
  36. EdgeInsets.symmetric(horizontal: horizontal, vertical: vertical),
  37. child: this);
  38. Widget marginOnly({
  39. double left = 0.0,
  40. double top = 0.0,
  41. double right = 0.0,
  42. double bottom = 0.0,
  43. }) =>
  44. Container(
  45. margin: EdgeInsets.only(
  46. top: top, left: left, right: right, bottom: bottom),
  47. child: this);
  48. Widget get marginZero => Container(margin: EdgeInsets.zero, child: this);
  49. }
  50. /// 扩展 Widget
  51. extension ExWidget on Widget {
  52. /// 对齐
  53. Widget align(
  54. AlignmentGeometry alignment, {
  55. Key? key,
  56. }) =>
  57. Align(
  58. key: key,
  59. alignment: alignment,
  60. child: this,
  61. );
  62. /// 对齐 中间
  63. Widget alignCenter() => align(Alignment.center);
  64. /// 对齐 左边
  65. Widget alignLeft() => align(Alignment.centerLeft);
  66. /// 对齐 右边
  67. Widget alignRight() => align(Alignment.centerRight);
  68. /// 对齐 顶部
  69. Widget alignTop() => align(Alignment.topCenter);
  70. /// 对齐 底部
  71. Widget alignBottom() => align(Alignment.bottomCenter);
  72. // 比例布局
  73. Widget aspectRatio({
  74. Key? key,
  75. required double aspectRatio,
  76. }) =>
  77. AspectRatio(
  78. key: key,
  79. aspectRatio: aspectRatio,
  80. child: this,
  81. );
  82. /// 背景颜色
  83. Widget backgroundColor(
  84. Color? color, {
  85. Key? key,
  86. }) =>
  87. DecoratedBox(
  88. key: key,
  89. child: this,
  90. decoration: BoxDecoration(color: color),
  91. );
  92. /// 背景图片
  93. Widget backgroundImage(
  94. DecorationImage image, {
  95. Key? key,
  96. }) =>
  97. DecoratedBox(
  98. key: key,
  99. child: this,
  100. decoration: BoxDecoration(image: image),
  101. );
  102. /// 边框
  103. Widget border({
  104. Key? key,
  105. double? all,
  106. double? left,
  107. double? right,
  108. double? top,
  109. double? bottom,
  110. Color color = const Color(0xFF000000),
  111. BorderStyle style = BorderStyle.solid,
  112. }) {
  113. BoxDecoration decoration = BoxDecoration(
  114. border: Border(
  115. left: (left ?? all) == null ? BorderSide.none : BorderSide(color: color, width: left ?? all ?? 0, style: style),
  116. right: (right ?? all) == null ? BorderSide.none : BorderSide(color: color, width: right ?? all ?? 0, style: style),
  117. top: (top ?? all) == null ? BorderSide.none : BorderSide(color: color, width: top ?? all ?? 0, style: style),
  118. bottom: (bottom ?? all) == null ? BorderSide.none : BorderSide(color: color, width: bottom ?? all ?? 0, style: style),
  119. ),
  120. );
  121. return DecoratedBox(
  122. key: key,
  123. child: this,
  124. decoration: decoration,
  125. );
  126. }
  127. /// 圆角
  128. Widget borderRadius({
  129. Key? key,
  130. double? all,
  131. double? topLeft,
  132. double? topRight,
  133. double? bottomLeft,
  134. double? bottomRight,
  135. }) {
  136. BoxDecoration decoration = BoxDecoration(
  137. borderRadius: BorderRadius.only(
  138. topLeft: Radius.circular(topLeft ?? all ?? 0.0),
  139. topRight: Radius.circular(topRight ?? all ?? 0.0),
  140. bottomLeft: Radius.circular(bottomLeft ?? all ?? 0.0),
  141. bottomRight: Radius.circular(bottomRight ?? all ?? 0.0),
  142. ),
  143. );
  144. return DecoratedBox(
  145. key: key,
  146. child: this,
  147. decoration: decoration,
  148. );
  149. }
  150. /// 阴影
  151. Widget boxShadow({
  152. Key? key,
  153. Color color = const Color(0xFF000000),
  154. Offset offset = Offset.zero,
  155. double blurRadius = 0.0,
  156. double spreadRadius = 0.0,
  157. }) {
  158. BoxDecoration decoration = BoxDecoration(
  159. boxShadow: [
  160. BoxShadow(
  161. color: color,
  162. blurRadius: blurRadius,
  163. spreadRadius: spreadRadius,
  164. offset: offset,
  165. ),
  166. ],
  167. );
  168. return DecoratedBox(
  169. key: key,
  170. child: this,
  171. decoration: decoration,
  172. );
  173. }
  174. /// 卡片
  175. Widget card({
  176. Key? key,
  177. Color? color,
  178. double? elevation,
  179. ShapeBorder? shape,
  180. bool borderOnForeground = true,
  181. EdgeInsetsGeometry? margin,
  182. Clip? clipBehavior,
  183. bool semanticContainer = true,
  184. }) =>
  185. Card(
  186. key: key,
  187. color: color,
  188. elevation: elevation,
  189. shape: shape,
  190. borderOnForeground: borderOnForeground,
  191. margin: margin,
  192. clipBehavior: clipBehavior,
  193. semanticContainer: semanticContainer,
  194. child: this,
  195. );
  196. // 居中
  197. Widget center({
  198. Key? key,
  199. double? widthFactor,
  200. double? heightFactor,
  201. }) =>
  202. Center(
  203. key: key,
  204. widthFactor: widthFactor,
  205. heightFactor: heightFactor,
  206. child: this,
  207. );
  208. /// 裁剪 oval
  209. Widget clipOval({Key? key}) => ClipOval(
  210. key: key,
  211. child: this,
  212. );
  213. /// 裁剪 rect
  214. Widget clipRect({
  215. Key? key,
  216. CustomClipper<Rect>? clipper,
  217. Clip clipBehavior = Clip.hardEdge,
  218. }) =>
  219. ClipRect(
  220. key: key,
  221. clipper: clipper,
  222. clipBehavior: clipBehavior,
  223. child: this,
  224. );
  225. /// 裁剪圆角
  226. Widget clipRRect({
  227. Key? key,
  228. double? all,
  229. double? topLeft,
  230. double? topRight,
  231. double? bottomLeft,
  232. double? bottomRight,
  233. CustomClipper<RRect>? clipper,
  234. Clip clipBehavior = Clip.antiAlias,
  235. }) =>
  236. ClipRRect(
  237. key: key,
  238. child: this,
  239. clipper: clipper,
  240. clipBehavior: clipBehavior,
  241. borderRadius: BorderRadius.only(
  242. topLeft: Radius.circular(topLeft ?? all ?? 0.0),
  243. topRight: Radius.circular(topRight ?? all ?? 0.0),
  244. bottomLeft: Radius.circular(bottomLeft ?? all ?? 0.0),
  245. bottomRight: Radius.circular(bottomRight ?? all ?? 0.0),
  246. ),
  247. );
  248. /// 约束
  249. Widget constrained({
  250. Key? key,
  251. double? width,
  252. double? height,
  253. double minWidth = 0.0,
  254. double maxWidth = double.infinity,
  255. double minHeight = 0.0,
  256. double maxHeight = double.infinity,
  257. }) {
  258. BoxConstraints constraints = BoxConstraints(
  259. minWidth: minWidth,
  260. maxWidth: maxWidth,
  261. minHeight: minHeight,
  262. maxHeight: maxHeight,
  263. );
  264. constraints = (width != null || height != null) ? constraints.tighten(width: width, height: height) : constraints;
  265. return ConstrainedBox(
  266. key: key,
  267. child: this,
  268. constraints: constraints,
  269. );
  270. }
  271. /// 盒子装饰器
  272. Widget decorated({
  273. Key? key,
  274. Color? color,
  275. DecorationImage? image,
  276. BoxBorder? border,
  277. BorderRadius? borderRadius,
  278. List<BoxShadow>? boxShadow,
  279. Gradient? gradient,
  280. BlendMode? backgroundBlendMode,
  281. BoxShape shape = BoxShape.rectangle,
  282. DecorationPosition position = DecorationPosition.background,
  283. }) {
  284. BoxDecoration decoration = BoxDecoration(
  285. color: color,
  286. image: image,
  287. border: border,
  288. borderRadius: borderRadius,
  289. boxShadow: boxShadow,
  290. gradient: gradient,
  291. backgroundBlendMode: backgroundBlendMode,
  292. shape: shape,
  293. );
  294. return DecoratedBox(
  295. key: key,
  296. child: this,
  297. decoration: decoration,
  298. position: position,
  299. );
  300. }
  301. /// elevation
  302. Widget elevation(
  303. double elevation, {
  304. Key? key,
  305. BorderRadiusGeometry borderRadius = BorderRadius.zero,
  306. Color shadowColor = const Color(0xFF000000),
  307. }) =>
  308. Material(
  309. key: key,
  310. child: this,
  311. color: Colors.transparent,
  312. elevation: elevation,
  313. borderRadius: borderRadius,
  314. shadowColor: shadowColor,
  315. );
  316. /// expanded 撑满,用于线性布局
  317. Widget expanded({
  318. Key? key,
  319. int flex = 1,
  320. }) =>
  321. Expanded(
  322. key: key,
  323. child: this,
  324. flex: flex,
  325. );
  326. /// 调整子控件大小与位置
  327. Widget fittedBox({
  328. Key? key,
  329. BoxFit fit = BoxFit.contain,
  330. AlignmentGeometry alignment = Alignment.center,
  331. }) =>
  332. FittedBox(
  333. key: key,
  334. fit: fit,
  335. alignment: alignment,
  336. child: this,
  337. );
  338. /// 弹性布局 flexible,用于线性布局
  339. Widget flexible({
  340. Key? key,
  341. int flex = 1,
  342. FlexFit fit = FlexFit.loose,
  343. }) =>
  344. Flexible(
  345. key: key,
  346. child: this,
  347. flex: flex,
  348. fit: fit,
  349. );
  350. Widget fractionallySizedBox({
  351. Key? key,
  352. AlignmentGeometry alignment = Alignment.center,
  353. double? widthFactor,
  354. double? heightFactor,
  355. }) =>
  356. FractionallySizedBox(
  357. key: key,
  358. alignment: alignment,
  359. widthFactor: widthFactor,
  360. heightFactor: heightFactor,
  361. child: this,
  362. );
  363. /// 手势
  364. Widget gestures({
  365. Key? key,
  366. GestureOnTapChangeCallback? onTapChange,
  367. GestureTapDownCallback? onTapDown,
  368. GestureTapUpCallback? onTapUp,
  369. GestureTapCallback? onTap,
  370. GestureTapCancelCallback? onTapCancel,
  371. GestureTapDownCallback? onSecondaryTapDown,
  372. GestureTapUpCallback? onSecondaryTapUp,
  373. GestureTapCancelCallback? onSecondaryTapCancel,
  374. GestureTapCallback? onDoubleTap,
  375. GestureLongPressCallback? onLongPress,
  376. GestureLongPressStartCallback? onLongPressStart,
  377. GestureLongPressMoveUpdateCallback? onLongPressMoveUpdate,
  378. GestureLongPressUpCallback? onLongPressUp,
  379. GestureLongPressEndCallback? onLongPressEnd,
  380. GestureDragDownCallback? onVerticalDragDown,
  381. GestureDragStartCallback? onVerticalDragStart,
  382. GestureDragUpdateCallback? onVerticalDragUpdate,
  383. GestureDragEndCallback? onVerticalDragEnd,
  384. GestureDragCancelCallback? onVerticalDragCancel,
  385. GestureDragDownCallback? onHorizontalDragDown,
  386. GestureDragStartCallback? onHorizontalDragStart,
  387. GestureDragUpdateCallback? onHorizontalDragUpdate,
  388. GestureDragEndCallback? onHorizontalDragEnd,
  389. GestureDragCancelCallback? onHorizontalDragCancel,
  390. GestureDragDownCallback? onPanDown,
  391. GestureDragStartCallback? onPanStart,
  392. GestureDragUpdateCallback? onPanUpdate,
  393. GestureDragEndCallback? onPanEnd,
  394. GestureDragCancelCallback? onPanCancel,
  395. GestureScaleStartCallback? onScaleStart,
  396. GestureScaleUpdateCallback? onScaleUpdate,
  397. GestureScaleEndCallback? onScaleEnd,
  398. GestureForcePressStartCallback? onForcePressStart,
  399. GestureForcePressPeakCallback? onForcePressPeak,
  400. GestureForcePressUpdateCallback? onForcePressUpdate,
  401. GestureForcePressEndCallback? onForcePressEnd,
  402. HitTestBehavior? behavior,
  403. bool excludeFromSemantics = false,
  404. DragStartBehavior dragStartBehavior = DragStartBehavior.start,
  405. }) =>
  406. GestureDetector(
  407. key: key,
  408. onTapDown: (TapDownDetails tapDownDetails) {
  409. if (onTapDown != null) onTapDown(tapDownDetails);
  410. if (onTapChange != null) onTapChange(true);
  411. },
  412. onTapCancel: () {
  413. if (onTapCancel != null) onTapCancel();
  414. if (onTapChange != null) onTapChange(false);
  415. },
  416. onTap: () {
  417. if (onTap != null) onTap();
  418. if (onTapChange != null) onTapChange(false);
  419. },
  420. onTapUp: onTapUp,
  421. onDoubleTap: onDoubleTap,
  422. onLongPress: onLongPress,
  423. onLongPressStart: onLongPressStart,
  424. onLongPressEnd: onLongPressEnd,
  425. onLongPressMoveUpdate: onLongPressMoveUpdate,
  426. onLongPressUp: onLongPressUp,
  427. onVerticalDragStart: onVerticalDragStart,
  428. onVerticalDragEnd: onVerticalDragEnd,
  429. onVerticalDragDown: onVerticalDragDown,
  430. onVerticalDragCancel: onVerticalDragCancel,
  431. onVerticalDragUpdate: onVerticalDragUpdate,
  432. onHorizontalDragStart: onHorizontalDragStart,
  433. onHorizontalDragEnd: onHorizontalDragEnd,
  434. onHorizontalDragCancel: onHorizontalDragCancel,
  435. onHorizontalDragUpdate: onHorizontalDragUpdate,
  436. onHorizontalDragDown: onHorizontalDragDown,
  437. onForcePressStart: onForcePressStart,
  438. onForcePressEnd: onForcePressEnd,
  439. onForcePressPeak: onForcePressPeak,
  440. onForcePressUpdate: onForcePressUpdate,
  441. onPanStart: onPanStart,
  442. onPanEnd: onPanEnd,
  443. onPanCancel: onPanCancel,
  444. onPanDown: onPanDown,
  445. onPanUpdate: onPanUpdate,
  446. onScaleStart: onScaleStart,
  447. onScaleEnd: onScaleEnd,
  448. onScaleUpdate: onScaleUpdate,
  449. behavior: behavior ?? HitTestBehavior.opaque,
  450. excludeFromSemantics: excludeFromSemantics,
  451. dragStartBehavior: dragStartBehavior,
  452. child: this,
  453. );
  454. /// 手势
  455. Widget onTap(
  456. GestureTapCallback onTap, {
  457. Key? key,
  458. HitTestBehavior? behavior,
  459. ClickType type = ClickType.none, //默认没有点击类型
  460. int milliseconds = 500, //点击类型的时间戳(毫秒)
  461. bool excludeFromSemantics = false,
  462. DragStartBehavior dragStartBehavior = DragStartBehavior.start,
  463. }) =>
  464. GestureDetector(
  465. key: key,
  466. onTap: type == ClickType.debounce
  467. ? onTap.debounce(milliseconds)
  468. : type == ClickType.throttle
  469. ? onTap.throttle(milliseconds)
  470. : onTap,
  471. behavior: behavior ?? HitTestBehavior.opaque,
  472. excludeFromSemantics: excludeFromSemantics,
  473. dragStartBehavior: dragStartBehavior,
  474. child: this,
  475. );
  476. /// 长按手势
  477. Widget onLongPress(
  478. GestureTapCallback onLongPress, {
  479. Key? key,
  480. HitTestBehavior? behavior,
  481. bool excludeFromSemantics = false,
  482. DragStartBehavior dragStartBehavior = DragStartBehavior.start,
  483. }) =>
  484. GestureDetector(
  485. key: key,
  486. onLongPress: onLongPress,
  487. behavior: behavior ?? HitTestBehavior.opaque,
  488. excludeFromSemantics: excludeFromSemantics,
  489. dragStartBehavior: dragStartBehavior,
  490. child: this,
  491. );
  492. /// 约束 高度
  493. Widget height(
  494. double height, {
  495. Key? key,
  496. }) =>
  497. ConstrainedBox(
  498. key: key,
  499. child: this,
  500. constraints: BoxConstraints.tightFor(height: height),
  501. );
  502. /// 限制盒子 最大宽高
  503. Widget limitedBox({
  504. Key? key,
  505. double maxWidth = double.infinity,
  506. double maxHeight = double.infinity,
  507. }) =>
  508. LimitedBox(
  509. key: key,
  510. maxWidth: maxWidth,
  511. maxHeight: maxHeight,
  512. child: this,
  513. );
  514. /// 偏移
  515. Widget offstage({
  516. Key? key,
  517. bool offstage = true,
  518. }) =>
  519. Offstage(
  520. key: key,
  521. offstage: offstage,
  522. child: this,
  523. );
  524. /// 透明度
  525. Widget opacity(
  526. double opacity, {
  527. Key? key,
  528. bool alwaysIncludeSemantics = false,
  529. }) =>
  530. Opacity(
  531. key: key,
  532. opacity: opacity,
  533. alwaysIncludeSemantics: alwaysIncludeSemantics,
  534. child: this,
  535. );
  536. /// 溢出
  537. Widget overflow({
  538. Key? key,
  539. AlignmentGeometry alignment = Alignment.center,
  540. double? minWidth,
  541. double? maxWidth,
  542. double? minHeight,
  543. double? maxHeight,
  544. }) =>
  545. OverflowBox(
  546. key: key,
  547. alignment: alignment,
  548. minWidth: minWidth,
  549. maxWidth: minWidth,
  550. minHeight: minHeight,
  551. maxHeight: maxHeight,
  552. child: this,
  553. );
  554. /// 内间距
  555. Widget padding({
  556. Key? key,
  557. EdgeInsetsGeometry? value,
  558. double? all,
  559. double? horizontal,
  560. double? vertical,
  561. double? top,
  562. double? bottom,
  563. double? left,
  564. double? right,
  565. }) =>
  566. Padding(
  567. key: key,
  568. padding: value ??
  569. EdgeInsets.only(
  570. top: top ?? vertical ?? all ?? 0.0,
  571. bottom: bottom ?? vertical ?? all ?? 0.0,
  572. left: left ?? horizontal ?? all ?? 0.0,
  573. right: right ?? horizontal ?? all ?? 0.0,
  574. ),
  575. child: this,
  576. );
  577. /// 内间距 下
  578. Widget paddingBottom(double val) => padding(bottom: val);
  579. /// 内间距 横向
  580. Widget paddingHorizontal(double val) => padding(horizontal: val);
  581. /// 内间距 左
  582. Widget paddingLeft(double val) => padding(left: val);
  583. /// 内间距 右
  584. Widget paddingRight(double val) => padding(right: val);
  585. /// 内间距 上
  586. Widget paddingTop(double val) => padding(top: val);
  587. /// 内间距 纵向
  588. Widget paddingVertical(double val) => padding(vertical: val);
  589. /// stack布局 位置
  590. Widget positioned({
  591. Key? key,
  592. double? left,
  593. double? top,
  594. double? right,
  595. double? bottom,
  596. double? width,
  597. double? height,
  598. }) =>
  599. Positioned(
  600. key: key,
  601. child: this,
  602. left: left,
  603. top: top,
  604. right: right,
  605. bottom: bottom,
  606. width: width,
  607. height: height,
  608. );
  609. /// 涟漪
  610. Widget ripple({
  611. Key? key,
  612. Color? bgColor,
  613. Color? focusColor,
  614. Color? hoverColor,
  615. Color? highlightColor,
  616. Color? splashColor,
  617. InteractiveInkFeatureFactory? splashFactory,
  618. double? radius,
  619. ShapeBorder? customBorder,
  620. bool enableFeedback = true,
  621. bool excludeFromSemantics = false,
  622. FocusNode? focusNode,
  623. bool canRequestFocus = true,
  624. bool autoFocus = false,
  625. bool enable = true,
  626. }) =>
  627. enable
  628. ? Builder(
  629. key: key,
  630. builder: (BuildContext context) {
  631. GestureDetector? gestures = context.findAncestorWidgetOfExactType<GestureDetector>();
  632. return Material(
  633. color: bgColor ?? Colors.transparent,
  634. child: InkWell(
  635. focusColor: focusColor,
  636. hoverColor: hoverColor,
  637. highlightColor: highlightColor,
  638. splashColor: splashColor,
  639. splashFactory: splashFactory,
  640. radius: radius,
  641. customBorder: customBorder,
  642. enableFeedback: enableFeedback,
  643. excludeFromSemantics: excludeFromSemantics,
  644. focusNode: focusNode,
  645. canRequestFocus: canRequestFocus,
  646. autofocus: autoFocus,
  647. onTap: gestures?.onTap,
  648. child: this,
  649. ),
  650. );
  651. },
  652. )
  653. : Builder(
  654. key: key,
  655. builder: (context) => this,
  656. );
  657. // 刘海屏 特殊屏幕 留白
  658. Widget safeArea({
  659. Key? key,
  660. bool top = true,
  661. bool bottom = true,
  662. bool left = true,
  663. bool right = true,
  664. }) =>
  665. SafeArea(
  666. key: key,
  667. top: top,
  668. bottom: bottom,
  669. left: left,
  670. right: right,
  671. child: this,
  672. );
  673. /// 比例缩放
  674. Widget scale({
  675. Key? key,
  676. double? all,
  677. double? x,
  678. double? y,
  679. Offset? origin,
  680. AlignmentGeometry alignment = Alignment.center,
  681. bool transformHitTests = true,
  682. }) =>
  683. Transform(
  684. key: key,
  685. transform: Matrix4.diagonal3Values(x ?? all ?? 0, y ?? all ?? 0, 1.0),
  686. alignment: alignment,
  687. child: this,
  688. origin: origin,
  689. transformHitTests: transformHitTests,
  690. );
  691. /// 滚动视图
  692. Widget scrollable({
  693. Key? key,
  694. Axis scrollDirection = Axis.vertical,
  695. bool reverse = false,
  696. bool? primary,
  697. ScrollPhysics? physics,
  698. ScrollController? controller,
  699. DragStartBehavior dragStartBehavior = DragStartBehavior.start,
  700. EdgeInsetsGeometry? padding,
  701. }) =>
  702. SingleChildScrollView(
  703. key: key,
  704. child: this,
  705. scrollDirection: scrollDirection,
  706. reverse: reverse,
  707. primary: primary,
  708. physics: physics,
  709. controller: controller,
  710. dragStartBehavior: dragStartBehavior,
  711. padding: padding,
  712. );
  713. /// 语义调试
  714. /// MaterialApp.showSemanticsDebugger: true,
  715. Widget semanticsLabel(
  716. String label, {
  717. Key? key,
  718. }) =>
  719. Semantics.fromProperties(
  720. key: key,
  721. properties: SemanticsProperties(label: label),
  722. child: this,
  723. );
  724. /// 约束 宽高
  725. Widget tight({
  726. double? width,
  727. double? height,
  728. Key? key,
  729. }) =>
  730. ConstrainedBox(
  731. key: key,
  732. child: this,
  733. constraints: BoxConstraints.tightFor(width: width, height: height),
  734. );
  735. /// transforms Matrix4
  736. Widget transform({
  737. Key? key,
  738. required Matrix4 transform,
  739. Offset? origin,
  740. AlignmentGeometry? alignment,
  741. bool transformHitTests = true,
  742. }) =>
  743. Transform(
  744. key: key,
  745. transform: transform,
  746. alignment: alignment,
  747. origin: origin,
  748. transformHitTests: transformHitTests,
  749. child: this,
  750. );
  751. /// translate 变化位置
  752. Widget translate({
  753. Key? key,
  754. required Offset offset,
  755. bool transformHitTests = true,
  756. }) =>
  757. Transform.translate(
  758. key: key,
  759. offset: offset,
  760. transformHitTests: transformHitTests,
  761. child: this,
  762. );
  763. /// 约束 宽度
  764. Widget width(
  765. double width, {
  766. Key? key,
  767. }) =>
  768. ConstrainedBox(
  769. key: key,
  770. child: this,
  771. constraints: BoxConstraints.tightFor(width: width),
  772. );
  773. }