You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

936 lines
25 KiB

import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
/// 手势 tap
typedef GestureOnTapChangeCallback = void Function<T>(T val);
/// 扩展 Widget
extension ExWidget on Widget {
/// 对齐
Widget align(
AlignmentGeometry alignment, {
Key? key,
}) =>
Align(
key: key,
alignment: alignment,
child: this,
);
/// 对齐 中间
Widget alignCenter() => align(Alignment.center);
/// 对齐 左边
Widget alignLeftCenter() => align(Alignment.centerLeft);
/// 对齐 右边
Widget alignRightCenter() => align(Alignment.centerRight);
/// 对齐 顶部
Widget alignTopCenter() => align(Alignment.topCenter);
/// 对齐 底部
Widget alignBottomCenter() => align(Alignment.bottomCenter);
Widget alignLeftTop() => align(Alignment.topLeft);
Widget alignRightTop() => align(Alignment.topRight);
Widget alignLeftBottom() => align(Alignment.bottomLeft);
Widget alignRightBottom() => align(Alignment.bottomRight);
// 比例布局
Widget aspectRatio({
Key? key,
required double aspectRatio,
}) =>
AspectRatio(
key: key,
aspectRatio: aspectRatio,
child: this,
);
/// 背景颜色
Widget backgroundColor(
Color color, {
Key? key,
}) =>
DecoratedBox(
key: key,
decoration: BoxDecoration(color: color),
child: this,
);
/// 背景图片
Widget backgroundImage(
DecorationImage image, {
Key? key,
}) =>
DecoratedBox(
key: key,
decoration: BoxDecoration(image: image),
child: this,
);
/// 边框
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,
decoration: decoration,
child: this,
);
}
/// 圆角
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,
decoration: decoration,
child: this,
);
}
/// 阴影
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,
decoration: decoration,
child: this,
);
}
Widget card({
Key? key,
double? radius,
Color? color,
Color? shadowColor,
double? blurRadius,
}) =>
Container(
decoration: BoxDecoration(
color: color ?? Colors.white,
borderRadius: BorderRadius.all(
Radius.circular(radius ?? 5),
),
boxShadow: [
BoxShadow(
// x偏移量 | y偏移量
offset: const Offset(0, 3),
color: shadowColor ?? Colors.black.withOpacity(0.15),
// 阴影模糊半径
blurRadius: blurRadius ?? 8,
// 阴影扩散半径
spreadRadius: 0,
blurStyle: BlurStyle.normal,
),
],
),
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,
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),
),
child: this,
);
/// 约束
// 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,
// constraints: constraints,
// child: this,
// );
// }
// 取消父级约束
// Widget unconstrained({
// Key? key,
// TextDirection? textDirection,
// AlignmentGeometry alignment = Alignment.center,
// Axis? constrainedAxis,
// Clip clipBehavior = Clip.none,
// }) =>
// UnconstrainedBox(
// key: key,
// textDirection: textDirection,
// alignment: alignment,
// constrainedAxis: constrainedAxis,
// clipBehavior: clipBehavior,
// child: this,
// );
/// 盒子装饰器
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,
decoration: decoration,
position: position,
child: this,
);
}
/// elevation
Widget elevation(
double elevation, {
Key? key,
BorderRadiusGeometry borderRadius = BorderRadius.zero,
Color shadowColor = const Color(0xFF000000),
}) =>
Material(
key: key,
color: Colors.transparent,
elevation: elevation,
borderRadius: borderRadius,
shadowColor: shadowColor,
child: this,
);
/// expanded 撑满
Widget expanded({
Key? key,
int flex = 1,
}) =>
Expanded(
key: key,
flex: flex,
child: this,
);
// Widget fittedBox({
// Key? key,
// BoxFit fit = BoxFit.contain,
// AlignmentGeometry alignment = Alignment.centerLeft,
// Clip clipBehavior = Clip.none,
// }) =>
// FittedBox(
// key: key,
// fit: fit,
// alignment: alignment,
// clipBehavior: clipBehavior,
// child: this,
// );
/// 弹性布局 flexible
Widget flexible({
Key? key,
int flex = 1,
FlexFit fit = FlexFit.loose,
}) =>
Flexible(
key: key,
flex: flex,
fit: fit,
child: this,
);
//
// 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,
bool excludeFromSemantics = false,
DragStartBehavior dragStartBehavior = DragStartBehavior.start,
}) =>
GestureDetector(
key: key,
onTap: onTap,
behavior: behavior ?? HitTestBehavior.opaque,
excludeFromSemantics: excludeFromSemantics,
dragStartBehavior: dragStartBehavior,
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,
constraints: BoxConstraints.tightFor(height: height),
child: this,
);
/// 限制盒子 最大宽高
// 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 paddingAll(double val) => padding(all: val);
/// 内间距 下
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);
/// 内间距
Widget sliverPadding({
Key? key,
EdgeInsetsGeometry? value,
double? all,
double? horizontal,
double? vertical,
double? top,
double? bottom,
double? left,
double? right,
}) =>
SliverPadding(
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,
),
sliver: this,
);
// /// 内间距 下
// Widget sliverPaddingBottom(double val) => sliverPadding(bottom: val);
//
// /// 内间距 横向
// Widget sliverPaddingHorizontal(double val) => sliverPadding(horizontal: val);
//
// /// 内间距 左
// Widget sliverPaddingLeft(double val) => sliverPadding(left: val);
//
// /// 内间距 右
// Widget sliverPaddingRight(double val) => sliverPadding(right: val);
//
// /// 内间距 上
// Widget sliverPaddingTop(double val) => sliverPadding(top: val);
//
// /// 内间距 纵向
// Widget sliverPaddingVertical(double val) => sliverPadding(vertical: val);
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);
/// stack布局 位置
// Widget positioned({
// Key? key,
// double? left,
// double? top,
// double? right,
// double? bottom,
// double? width,
// double? height,
// }) =>
// Positioned(
// key: key,
// left: left,
// top: top,
// right: right,
// bottom: bottom,
// width: width,
// height: height,
// child: this,
// );
// 墨水纹
// Widget inkWell({
// Key? key,
// Function()? onTap,
// double? borderRadius,
// }) =>
// Material(
// color: Colors.transparent,
// child: Ink(
// child: InkWell(
// borderRadius: borderRadius != null
// ? BorderRadius.all(
// Radius.circular(borderRadius),
// )
// : null,
// onTap: onTap ?? () {},
// child: this,
// ),
// ),
// );
/// 涟漪
// Widget ripple({
// Key? key,
// 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: 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,
// origin: origin,
// transformHitTests: transformHitTests,
// child: this,
// );
/// 滚动视图
// 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,
// scrollDirection: scrollDirection,
// reverse: reverse,
// primary: primary,
// physics: physics,
// controller: controller,
// dragStartBehavior: dragStartBehavior,
// padding: padding,
// child: this,
// );
/// 语义调试
/// 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,
// constraints: BoxConstraints.tightFor(width: width, height: height),
// child: this,
// );
/// 约束 宽高 size
// Widget tightSize(
// double size, {
// Key? key,
// }) =>
// ConstrainedBox(
// key: key,
// constraints: BoxConstraints.tightFor(width: size, height: size),
// child: this,
// );
/// 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,
constraints: BoxConstraints.tightFor(width: width),
child: this,
);
/// SliverToBoxAdapter
// Widget sliverToBoxAdapter({
// Key? key,
// }) =>
// SliverToBoxAdapter(key: key, child: this);
}
class HabiPreventFastClick {
static const Duration _duration = Duration(seconds: 1);
static DateTime? _lastTime;
static bool canClick(BuildContext context) {
final now = DateTime.now();
if (_lastTime != null && now.difference(_lastTime!) < _duration) {
// 如果上次点击的时间距离现在不超过1秒,则不允许点击
return false;
}
// 更新最后点击时间
_lastTime = now;
return true;
}
}