123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839 |
- import 'package:flutter/gestures.dart';
- import 'package:flutter/material.dart';
- import 'package:flutter/semantics.dart';
- import 'package:shared/utils/ext_dart.dart';
- /// 手势 tap
- typedef GestureOnTapChangeCallback = void Function<T>(T val);
- //点击防抖类型
- enum ClickType { none, throttle, debounce }
- extension WidgetPaddingX on Widget {
- Widget paddingAll(double padding) =>
- Padding(padding: EdgeInsets.all(padding), child: this);
- Widget paddingSymmetric({double horizontal = 0.0, double vertical = 0.0}) =>
- Padding(
- padding:
- EdgeInsets.symmetric(horizontal: horizontal, vertical: vertical),
- child: this);
- Widget paddingOnly({
- double left = 0.0,
- double top = 0.0,
- double right = 0.0,
- double bottom = 0.0,
- }) =>
- Padding(
- padding: EdgeInsets.only(
- top: top, left: left, right: right, bottom: bottom),
- child: this);
- Widget get paddingZero => Padding(padding: EdgeInsets.zero, child: this);
- }
- /// Add margin property to widget
- extension WidgetMarginX on Widget {
- Widget marginAll(double margin) =>
- Container(margin: EdgeInsets.all(margin), child: this);
- Widget marginSymmetric({double horizontal = 0.0, double vertical = 0.0}) =>
- Container(
- margin:
- EdgeInsets.symmetric(horizontal: horizontal, vertical: vertical),
- child: this);
- Widget marginOnly({
- double left = 0.0,
- double top = 0.0,
- double right = 0.0,
- double bottom = 0.0,
- }) =>
- Container(
- margin: EdgeInsets.only(
- top: top, left: left, right: right, bottom: bottom),
- child: this);
- Widget get marginZero => Container(margin: EdgeInsets.zero, child: this);
- }
- /// 扩展 Widget
- extension ExWidget on Widget {
- /// 对齐
- Widget align(
- AlignmentGeometry alignment, {
- Key? key,
- }) =>
- Align(
- key: key,
- alignment: alignment,
- child: this,
- );
- /// 对齐 中间
- Widget alignCenter() => align(Alignment.center);
- /// 对齐 左边
- Widget alignLeft() => align(Alignment.centerLeft);
- /// 对齐 右边
- Widget alignRight() => align(Alignment.centerRight);
- /// 对齐 顶部
- Widget alignTop() => align(Alignment.topCenter);
- /// 对齐 底部
- Widget alignBottom() => align(Alignment.bottomCenter);
- // 比例布局
- Widget aspectRatio({
- Key? key,
- required double aspectRatio,
- }) =>
- AspectRatio(
- key: key,
- aspectRatio: aspectRatio,
- child: this,
- );
- /// 背景颜色
- Widget backgroundColor(
- Color? color, {
- Key? key,
- }) =>
- DecoratedBox(
- key: key,
- child: this,
- decoration: BoxDecoration(color: color),
- );
- /// 背景图片
- Widget backgroundImage(
- DecorationImage image, {
- Key? key,
- }) =>
- DecoratedBox(
- key: key,
- child: this,
- decoration: BoxDecoration(image: image),
- );
- /// 边框
- Widget border({
- Key? key,
- double? all,
- double? left,
- double? right,
- double? top,
- double? bottom,
- Color color = const Color(0xFF000000),
- BorderStyle style = BorderStyle.solid,
- }) {
- BoxDecoration decoration = BoxDecoration(
- border: Border(
- left: (left ?? all) == null ? BorderSide.none : BorderSide(color: color, width: left ?? all ?? 0, style: style),
- right: (right ?? all) == null ? BorderSide.none : BorderSide(color: color, width: right ?? all ?? 0, style: style),
- top: (top ?? all) == null ? BorderSide.none : BorderSide(color: color, width: top ?? all ?? 0, style: style),
- bottom: (bottom ?? all) == null ? BorderSide.none : BorderSide(color: color, width: bottom ?? all ?? 0, style: style),
- ),
- );
- return DecoratedBox(
- key: key,
- child: this,
- decoration: decoration,
- );
- }
- /// 圆角
- Widget borderRadius({
- Key? key,
- double? all,
- double? topLeft,
- double? topRight,
- double? bottomLeft,
- double? bottomRight,
- }) {
- BoxDecoration decoration = BoxDecoration(
- borderRadius: BorderRadius.only(
- topLeft: Radius.circular(topLeft ?? all ?? 0.0),
- topRight: Radius.circular(topRight ?? all ?? 0.0),
- bottomLeft: Radius.circular(bottomLeft ?? all ?? 0.0),
- bottomRight: Radius.circular(bottomRight ?? all ?? 0.0),
- ),
- );
- return DecoratedBox(
- key: key,
- child: this,
- decoration: decoration,
- );
- }
- /// 阴影
- Widget boxShadow({
- Key? key,
- Color color = const Color(0xFF000000),
- Offset offset = Offset.zero,
- double blurRadius = 0.0,
- double spreadRadius = 0.0,
- }) {
- BoxDecoration decoration = BoxDecoration(
- boxShadow: [
- BoxShadow(
- color: color,
- blurRadius: blurRadius,
- spreadRadius: spreadRadius,
- offset: offset,
- ),
- ],
- );
- return DecoratedBox(
- key: key,
- child: this,
- decoration: decoration,
- );
- }
- /// 卡片
- Widget card({
- Key? key,
- Color? color,
- double? elevation,
- ShapeBorder? shape,
- bool borderOnForeground = true,
- EdgeInsetsGeometry? margin,
- Clip? clipBehavior,
- bool semanticContainer = true,
- }) =>
- Card(
- key: key,
- color: color,
- elevation: elevation,
- shape: shape,
- borderOnForeground: borderOnForeground,
- margin: margin,
- clipBehavior: clipBehavior,
- semanticContainer: semanticContainer,
- child: this,
- );
- // 居中
- Widget center({
- Key? key,
- double? widthFactor,
- double? heightFactor,
- }) =>
- Center(
- key: key,
- widthFactor: widthFactor,
- heightFactor: heightFactor,
- child: this,
- );
- /// 裁剪 oval
- Widget clipOval({Key? key}) => ClipOval(
- key: key,
- child: this,
- );
- /// 裁剪 rect
- Widget clipRect({
- Key? key,
- CustomClipper<Rect>? clipper,
- Clip clipBehavior = Clip.hardEdge,
- }) =>
- ClipRect(
- key: key,
- clipper: clipper,
- clipBehavior: clipBehavior,
- child: this,
- );
- /// 裁剪圆角
- Widget clipRRect({
- Key? key,
- double? all,
- double? topLeft,
- double? topRight,
- double? bottomLeft,
- double? bottomRight,
- CustomClipper<RRect>? clipper,
- Clip clipBehavior = Clip.antiAlias,
- }) =>
- ClipRRect(
- key: key,
- child: this,
- clipper: clipper,
- clipBehavior: clipBehavior,
- borderRadius: BorderRadius.only(
- topLeft: Radius.circular(topLeft ?? all ?? 0.0),
- topRight: Radius.circular(topRight ?? all ?? 0.0),
- bottomLeft: Radius.circular(bottomLeft ?? all ?? 0.0),
- bottomRight: Radius.circular(bottomRight ?? all ?? 0.0),
- ),
- );
- /// 约束
- Widget constrained({
- Key? key,
- double? width,
- double? height,
- double minWidth = 0.0,
- double maxWidth = double.infinity,
- double minHeight = 0.0,
- double maxHeight = double.infinity,
- }) {
- BoxConstraints constraints = BoxConstraints(
- minWidth: minWidth,
- maxWidth: maxWidth,
- minHeight: minHeight,
- maxHeight: maxHeight,
- );
- constraints = (width != null || height != null) ? constraints.tighten(width: width, height: height) : constraints;
- return ConstrainedBox(
- key: key,
- child: this,
- constraints: constraints,
- );
- }
- /// 盒子装饰器
- Widget decorated({
- Key? key,
- Color? color,
- DecorationImage? image,
- BoxBorder? border,
- BorderRadius? borderRadius,
- List<BoxShadow>? boxShadow,
- Gradient? gradient,
- BlendMode? backgroundBlendMode,
- BoxShape shape = BoxShape.rectangle,
- DecorationPosition position = DecorationPosition.background,
- }) {
- BoxDecoration decoration = BoxDecoration(
- color: color,
- image: image,
- border: border,
- borderRadius: borderRadius,
- boxShadow: boxShadow,
- gradient: gradient,
- backgroundBlendMode: backgroundBlendMode,
- shape: shape,
- );
- return DecoratedBox(
- key: key,
- child: this,
- decoration: decoration,
- position: position,
- );
- }
- /// elevation
- Widget elevation(
- double elevation, {
- Key? key,
- BorderRadiusGeometry borderRadius = BorderRadius.zero,
- Color shadowColor = const Color(0xFF000000),
- }) =>
- Material(
- key: key,
- child: this,
- color: Colors.transparent,
- elevation: elevation,
- borderRadius: borderRadius,
- shadowColor: shadowColor,
- );
- /// expanded 撑满,用于线性布局
- Widget expanded({
- Key? key,
- int flex = 1,
- }) =>
- Expanded(
- key: key,
- child: this,
- flex: flex,
- );
- /// 调整子控件大小与位置
- Widget fittedBox({
- Key? key,
- BoxFit fit = BoxFit.contain,
- AlignmentGeometry alignment = Alignment.center,
- }) =>
- FittedBox(
- key: key,
- fit: fit,
- alignment: alignment,
- child: this,
- );
- /// 弹性布局 flexible,用于线性布局
- Widget flexible({
- Key? key,
- int flex = 1,
- FlexFit fit = FlexFit.loose,
- }) =>
- Flexible(
- key: key,
- child: this,
- flex: flex,
- fit: fit,
- );
- Widget fractionallySizedBox({
- Key? key,
- AlignmentGeometry alignment = Alignment.center,
- double? widthFactor,
- double? heightFactor,
- }) =>
- FractionallySizedBox(
- key: key,
- alignment: alignment,
- widthFactor: widthFactor,
- heightFactor: heightFactor,
- child: this,
- );
- /// 手势
- Widget gestures({
- Key? key,
- GestureOnTapChangeCallback? onTapChange,
- GestureTapDownCallback? onTapDown,
- GestureTapUpCallback? onTapUp,
- GestureTapCallback? onTap,
- GestureTapCancelCallback? onTapCancel,
- GestureTapDownCallback? onSecondaryTapDown,
- GestureTapUpCallback? onSecondaryTapUp,
- GestureTapCancelCallback? onSecondaryTapCancel,
- GestureTapCallback? onDoubleTap,
- GestureLongPressCallback? onLongPress,
- GestureLongPressStartCallback? onLongPressStart,
- GestureLongPressMoveUpdateCallback? onLongPressMoveUpdate,
- GestureLongPressUpCallback? onLongPressUp,
- GestureLongPressEndCallback? onLongPressEnd,
- GestureDragDownCallback? onVerticalDragDown,
- GestureDragStartCallback? onVerticalDragStart,
- GestureDragUpdateCallback? onVerticalDragUpdate,
- GestureDragEndCallback? onVerticalDragEnd,
- GestureDragCancelCallback? onVerticalDragCancel,
- GestureDragDownCallback? onHorizontalDragDown,
- GestureDragStartCallback? onHorizontalDragStart,
- GestureDragUpdateCallback? onHorizontalDragUpdate,
- GestureDragEndCallback? onHorizontalDragEnd,
- GestureDragCancelCallback? onHorizontalDragCancel,
- GestureDragDownCallback? onPanDown,
- GestureDragStartCallback? onPanStart,
- GestureDragUpdateCallback? onPanUpdate,
- GestureDragEndCallback? onPanEnd,
- GestureDragCancelCallback? onPanCancel,
- GestureScaleStartCallback? onScaleStart,
- GestureScaleUpdateCallback? onScaleUpdate,
- GestureScaleEndCallback? onScaleEnd,
- GestureForcePressStartCallback? onForcePressStart,
- GestureForcePressPeakCallback? onForcePressPeak,
- GestureForcePressUpdateCallback? onForcePressUpdate,
- GestureForcePressEndCallback? onForcePressEnd,
- HitTestBehavior? behavior,
- bool excludeFromSemantics = false,
- DragStartBehavior dragStartBehavior = DragStartBehavior.start,
- }) =>
- GestureDetector(
- key: key,
- onTapDown: (TapDownDetails tapDownDetails) {
- if (onTapDown != null) onTapDown(tapDownDetails);
- if (onTapChange != null) onTapChange(true);
- },
- onTapCancel: () {
- if (onTapCancel != null) onTapCancel();
- if (onTapChange != null) onTapChange(false);
- },
- onTap: () {
- if (onTap != null) onTap();
- if (onTapChange != null) onTapChange(false);
- },
- onTapUp: onTapUp,
- onDoubleTap: onDoubleTap,
- onLongPress: onLongPress,
- onLongPressStart: onLongPressStart,
- onLongPressEnd: onLongPressEnd,
- onLongPressMoveUpdate: onLongPressMoveUpdate,
- onLongPressUp: onLongPressUp,
- onVerticalDragStart: onVerticalDragStart,
- onVerticalDragEnd: onVerticalDragEnd,
- onVerticalDragDown: onVerticalDragDown,
- onVerticalDragCancel: onVerticalDragCancel,
- onVerticalDragUpdate: onVerticalDragUpdate,
- onHorizontalDragStart: onHorizontalDragStart,
- onHorizontalDragEnd: onHorizontalDragEnd,
- onHorizontalDragCancel: onHorizontalDragCancel,
- onHorizontalDragUpdate: onHorizontalDragUpdate,
- onHorizontalDragDown: onHorizontalDragDown,
- onForcePressStart: onForcePressStart,
- onForcePressEnd: onForcePressEnd,
- onForcePressPeak: onForcePressPeak,
- onForcePressUpdate: onForcePressUpdate,
- onPanStart: onPanStart,
- onPanEnd: onPanEnd,
- onPanCancel: onPanCancel,
- onPanDown: onPanDown,
- onPanUpdate: onPanUpdate,
- onScaleStart: onScaleStart,
- onScaleEnd: onScaleEnd,
- onScaleUpdate: onScaleUpdate,
- behavior: behavior ?? HitTestBehavior.opaque,
- excludeFromSemantics: excludeFromSemantics,
- dragStartBehavior: dragStartBehavior,
- child: this,
- );
- /// 手势
- Widget onTap(
- GestureTapCallback onTap, {
- Key? key,
- HitTestBehavior? behavior,
- ClickType type = ClickType.none,
- int milliseconds = 500,
- bool excludeFromSemantics = false,
- DragStartBehavior dragStartBehavior = DragStartBehavior.start,
- double padding = 0, // 通过 padding 参数控制点击范围的扩展
- }) =>
- GestureDetector(
- key: key,
- onTap: type == ClickType.debounce
- ? onTap.debounce(milliseconds)
- : type == ClickType.throttle
- ? onTap.throttle(milliseconds)
- : onTap,
- behavior: behavior ?? HitTestBehavior.opaque,
- excludeFromSemantics: excludeFromSemantics,
- dragStartBehavior: dragStartBehavior,
- child: Padding(
- padding: EdgeInsets.all(padding), // 通过 Padding 扩大点击区域
- child: this,
- ),
- );
- /// 长按手势
- Widget onLongPress(
- GestureTapCallback onLongPress, {
- Key? key,
- HitTestBehavior? behavior,
- bool excludeFromSemantics = false,
- DragStartBehavior dragStartBehavior = DragStartBehavior.start,
- }) =>
- GestureDetector(
- key: key,
- onLongPress: onLongPress,
- behavior: behavior ?? HitTestBehavior.opaque,
- excludeFromSemantics: excludeFromSemantics,
- dragStartBehavior: dragStartBehavior,
- child: this,
- );
- /// 约束 高度
- Widget height(
- double height, {
- Key? key,
- }) =>
- ConstrainedBox(
- key: key,
- child: this,
- constraints: BoxConstraints.tightFor(height: height),
- );
- /// 限制盒子 最大宽高
- Widget limitedBox({
- Key? key,
- double maxWidth = double.infinity,
- double maxHeight = double.infinity,
- }) =>
- LimitedBox(
- key: key,
- maxWidth: maxWidth,
- maxHeight: maxHeight,
- child: this,
- );
- /// 偏移
- Widget offstage({
- Key? key,
- bool offstage = true,
- }) =>
- Offstage(
- key: key,
- offstage: offstage,
- child: this,
- );
- /// 透明度
- Widget opacity(
- double opacity, {
- Key? key,
- bool alwaysIncludeSemantics = false,
- }) =>
- Opacity(
- key: key,
- opacity: opacity,
- alwaysIncludeSemantics: alwaysIncludeSemantics,
- child: this,
- );
- /// 溢出
- Widget overflow({
- Key? key,
- AlignmentGeometry alignment = Alignment.center,
- double? minWidth,
- double? maxWidth,
- double? minHeight,
- double? maxHeight,
- }) =>
- OverflowBox(
- key: key,
- alignment: alignment,
- minWidth: minWidth,
- maxWidth: minWidth,
- minHeight: minHeight,
- maxHeight: maxHeight,
- child: this,
- );
- /// 内间距
- Widget padding({
- Key? key,
- EdgeInsetsGeometry? value,
- double? all,
- double? horizontal,
- double? vertical,
- double? top,
- double? bottom,
- double? left,
- double? right,
- }) =>
- Padding(
- key: key,
- padding: value ??
- EdgeInsets.only(
- top: top ?? vertical ?? all ?? 0.0,
- bottom: bottom ?? vertical ?? all ?? 0.0,
- left: left ?? horizontal ?? all ?? 0.0,
- right: right ?? horizontal ?? all ?? 0.0,
- ),
- child: this,
- );
- /// 内间距 下
- Widget paddingBottom(double val) => padding(bottom: val);
- /// 内间距 横向
- Widget paddingHorizontal(double val) => padding(horizontal: val);
- /// 内间距 左
- Widget paddingLeft(double val) => padding(left: val);
- /// 内间距 右
- Widget paddingRight(double val) => padding(right: val);
- /// 内间距 上
- Widget paddingTop(double val) => padding(top: val);
- /// 内间距 纵向
- Widget paddingVertical(double val) => padding(vertical: val);
- /// stack布局 位置
- Widget positioned({
- Key? key,
- double? left,
- double? top,
- double? right,
- double? bottom,
- double? width,
- double? height,
- }) =>
- Positioned(
- key: key,
- child: this,
- left: left,
- top: top,
- right: right,
- bottom: bottom,
- width: width,
- height: height,
- );
- /// 涟漪
- Widget ripple({
- Key? key,
- Color? bgColor,
- Color? focusColor,
- Color? hoverColor,
- Color? highlightColor,
- Color? splashColor,
- InteractiveInkFeatureFactory? splashFactory,
- double? radius,
- ShapeBorder? customBorder,
- bool enableFeedback = true,
- bool excludeFromSemantics = false,
- FocusNode? focusNode,
- bool canRequestFocus = true,
- bool autoFocus = false,
- bool enable = true,
- }) =>
- enable
- ? Builder(
- key: key,
- builder: (BuildContext context) {
- GestureDetector? gestures = context.findAncestorWidgetOfExactType<GestureDetector>();
- return Material(
- color: bgColor ?? Colors.transparent,
- child: InkWell(
- focusColor: focusColor,
- hoverColor: hoverColor,
- highlightColor: highlightColor,
- splashColor: splashColor,
- splashFactory: splashFactory,
- radius: radius,
- customBorder: customBorder,
- enableFeedback: enableFeedback,
- excludeFromSemantics: excludeFromSemantics,
- focusNode: focusNode,
- canRequestFocus: canRequestFocus,
- autofocus: autoFocus,
- onTap: gestures?.onTap,
- child: this,
- ),
- );
- },
- )
- : Builder(
- key: key,
- builder: (context) => this,
- );
- // 刘海屏 特殊屏幕 留白
- Widget safeArea({
- Key? key,
- bool top = true,
- bool bottom = true,
- bool left = true,
- bool right = true,
- }) =>
- SafeArea(
- key: key,
- top: top,
- bottom: bottom,
- left: left,
- right: right,
- child: this,
- );
- /// 比例缩放
- Widget scale({
- Key? key,
- double? all,
- double? x,
- double? y,
- Offset? origin,
- AlignmentGeometry alignment = Alignment.center,
- bool transformHitTests = true,
- }) =>
- Transform(
- key: key,
- transform: Matrix4.diagonal3Values(x ?? all ?? 0, y ?? all ?? 0, 1.0),
- alignment: alignment,
- child: this,
- origin: origin,
- transformHitTests: transformHitTests,
- );
- /// 滚动视图
- Widget scrollable({
- Key? key,
- Axis scrollDirection = Axis.vertical,
- bool reverse = false,
- bool? primary,
- ScrollPhysics? physics,
- ScrollController? controller,
- DragStartBehavior dragStartBehavior = DragStartBehavior.start,
- EdgeInsetsGeometry? padding,
- }) =>
- SingleChildScrollView(
- key: key,
- child: this,
- scrollDirection: scrollDirection,
- reverse: reverse,
- primary: primary,
- physics: physics,
- controller: controller,
- dragStartBehavior: dragStartBehavior,
- padding: padding,
- );
- /// 语义调试
- /// MaterialApp.showSemanticsDebugger: true,
- Widget semanticsLabel(
- String label, {
- Key? key,
- }) =>
- Semantics.fromProperties(
- key: key,
- properties: SemanticsProperties(label: label),
- child: this,
- );
- /// 约束 宽高
- Widget tight({
- double? width,
- double? height,
- Key? key,
- }) =>
- ConstrainedBox(
- key: key,
- child: this,
- constraints: BoxConstraints.tightFor(width: width, height: height),
- );
- /// transforms Matrix4
- Widget transform({
- Key? key,
- required Matrix4 transform,
- Offset? origin,
- AlignmentGeometry? alignment,
- bool transformHitTests = true,
- }) =>
- Transform(
- key: key,
- transform: transform,
- alignment: alignment,
- origin: origin,
- transformHitTests: transformHitTests,
- child: this,
- );
- /// translate 变化位置
- Widget translate({
- Key? key,
- required Offset offset,
- bool transformHitTests = true,
- }) =>
- Transform.translate(
- key: key,
- offset: offset,
- transformHitTests: transformHitTests,
- child: this,
- );
- /// 约束 宽度
- Widget width(
- double width, {
- Key? key,
- }) =>
- ConstrainedBox(
- key: key,
- child: this,
- constraints: BoxConstraints.tightFor(width: width),
- );
- }
|