Flutter基础 -- Flutter常用组件

目录

1. 文本组件 Text

1.1 基础用法

1.2 Text 定义

1.3 Text 示例

1.4 Text.rich、RichText 、TextSpan

1.5 RichText 示例

2. 导入资源

2.1 加入资源

2.2 加入图片

3. 图片组件 image

3.1 colorBlendMode 混合参数

3.2 fit 图片大小适配

3.3 ImageProvider 图片对象

4. 图标组件 Icon

4.1 定义

4.2 开启 pubspec.yaml

4.3 icon 预览

4.4 示例

4.5 苹果 Icon

5. 按钮组件

5.1 ElevatedButton

5.2 ButtonStyle 样式定义

5.3 其它按钮

6. 路由管理v1 Navigator 

6.1 匿名路由 

6.1.1 Navigator 路由管理对象

6.1.2 MaterialPageRoute 定义

6.1.3 路由传值

6.1.4 示例

6.2 命名路由

6.3 onGenerateRoute 手动解析

6.3.1 定义路由

6.3.2 导航页完整代码

7. 样式管理

7.1 ThemeData 样式对象

7.2 Color 与 MaterialColor

8. 手势事件

8.1 GestureDetector

8.2 InkWell

9. 输入框 TextField

9.1 定义

9.2 示例


博主wx:yuanlai45_csdn 博主qq:2777137742

后期会创建粉丝群,为同学们提供分享交流平台以及提供官方发送的福利奖品~

1. 文本组件 Text

Text Widget,从名字也可以看出,在 Flutter 里是用来负责显示文本信息的一个组件,功能类似于 Android 的 TextView、HTML 的一些文本标签等等,属于基础组件

Text class - widgets library - Dart API

1.1 基础用法

Text('hello word!');

1.2 Text 定义

const Text(//要显示的文字内容this.data,{//key类似于idKey key,//文字显示样式和属性this.style,this.strutStyle,//文字对齐方式this.textAlign,//文字显示方向this.textDirection,//设置语言环境this.locale,//是否自动换行this.softWrap,//文字溢出后处理方式this.overflow,//字体缩放this.textScaleFactor,//最大显示行数this.maxLines,//图像的语义描述,用于向Andoid上的TalkBack和iOS上的VoiceOver提供图像描述this.semanticsLabel,})

TextStyle 定义

style 属性比较常用,传入的是 TextStyle 对象,我们细看下它可以配置哪些属性样式

const TextStyle({//是否继承父类组件属性this.inherit = true,//字体颜色this.color,//文字大小,默认14pxthis.fontSize,//字体粗细this.fontWeight,//字体样式,normal或italicthis.fontStyle,//字母间距,默认为0,负数间距缩小,正数间距增大this.letterSpacing,//单词间距,默认为0,负数间距缩小,正数间距增大this.wordSpacing,//字体基线this.textBaseline,//行高this.height,//设置区域this.locale,//前景色this.foreground,//背景色this.background,//阴影this.shadows,//文字划线,下换线等等装饰this.decoration,//划线颜色this.decorationColor,//划线样式,虚线、实线等样式this.decorationStyle,//描述信息this.debugLabel,//字体String fontFamily,List<String> fontFamilyFallback,String package,})

1.3 Text 示例

TextStyle class - painting library - Dart API

颜色、大小、样式

Text('字体24下划线',style: TextStyle(color: Colors.blue, // 蓝色fontSize: 24,				// 24 号字体decoration: TextDecoration.underline, // 下划线)),

缩放、加粗

Text('放大加粗',textScaleFactor: 1.2, // 放大 1.2style: TextStyle(fontWeight: FontWeight.bold,	// 加粗 boldfontSize: 24,								// 24 号字体color: Colors.green,				// 绿色decoration: TextDecoration.none, // 不要下滑线)),

文字溢出

Text('缩放,Each line here is progressively more opaque. The base color is material.Colors.black, and Color.withOpacity is used to create a derivative color with the desired opacity. The root TextSpan for this RichText widget is explicitly given the ambient DefaultTextStyle, since RichText does not do that automatically. The inner TextStyle objects are implicitly mixed with the parent TextSpans TextSpan.style.',textScaleFactor: 1.0,textAlign: TextAlign.center,softWrap: true,maxLines: 3, // 3 行overflow: TextOverflow.ellipsis, // 剪切 加省略号style: TextStyle(fontWeight: FontWeight.bold,fontSize: 18,)),

输出

1.4 Text.rich、RichText 、TextSpan

可以在 Text 里加入一些 Span 标签,对某部分文字进行个性化改变样式,如加入 @ 符号,加入超链接、变色、加表情等等。Text.rich(…) 等价于 RichText(...),用哪个都可以。

https://api.flutter.dev/flutter/widgets/RichText-class.html

 定义

const Text.rich(// 样式片段标签TextSpanthis.textSpan,{Key key,this.style,this.strutStyle,this.textAlign,this.textDirection,this.locale,this.softWrap,this.overflow,this.textScaleFactor,this.maxLines,this.semanticsLabel,})const RichText({Key key,// 样式片段标签TextSpan@required this.text,this.textAlign = TextAlign.start,this.textDirection,this.softWrap = true,this.overflow = TextOverflow.clip,this.textScaleFactor = 1.0,this.maxLines,this.locale,this.strutStyle,})

textSpan 类型是 TextSpan ,其它参数同上

const TextSpan({//样式片段this.style,//要显示的文字this.text,//样式片段TextSpan数组,可以包含多个TextSpanthis.children,//用于手势进行识别处理,如点击跳转this.recognizer,})

1.5 RichText 示例

拼接字符

Text.rich(TextSpan(text: 'TextSpan',style: TextStyle(color: Colors.red,fontSize: 24.0,),children: <TextSpan>[new TextSpan(text: 'aaaaa',style: new TextStyle(color: Colors.blueGrey,),),new TextSpan(text: 'bbbbbb',style: new TextStyle(color: Colors.cyan,),),],
)),

添加交互

Text.rich(TextSpan(children: <TextSpan>[TextSpan(text: 'Tap点击',style: const TextStyle(color: Colors.blueGrey,),// 点击手势recognizer: TapGestureRecognizer()..onTap = () {//增加一个点击事件print('被点击了');},),],
)),

2. 导入资源

2.1 加入资源

创建 assets 目录

在更目录下创建 asssets,然后按资源类型,分别创建目录

编辑 pubspec.yaml 文件

# The following section is specific to Flutter.
flutter:...# To add assets to your application, add an assets section, like this:assets:- assets/images/- assets/svgs/- assets/json/

如果你想整个目录导入可以这样 - assets/images/

只是导入指定图片 - assets/images/abc.png

读取资源

File.json('assets/json/app.json',...
)

路径是从 assets 开始,指定文件位置

2.2 加入图片

自动适配屏幕 1x 2x 3x

为了适配不同的屏幕规格,设计了三种分辨率 Flutter 自动适配

目录排列上有个规则, images 目录下是 1x , 2x 3x 分别是单独目录

用猫哥 vscode 插件自动生成

猫哥提供了一个便捷的方式

首先下载插件 <Flutter GetX Generator - 猫哥>

Flutter GetX Generator - 猫哥 - Visual Studio Marketplace

右键自动生成图片,如果已有图片不覆盖

生成资源索引文件

会生成一个 files.txt 文件

创建你自己的资源 dart 文件, 复制下就行

/// 图片资源
class AssetsImages {static const logoPng = 'assets/images/logo.png';static const welcomePng = 'assets/images/welcome.png';static const iconFavouritePng = 'assets/images/icon_favourite.png';static const iconOffersPng = 'assets/images/icon_offers.png';static const iconLockPng = 'assets/images/icon_lock.png';static const iconOrderPng = 'assets/images/icon_order.png';static const iconMapPng = 'assets/images/icon_map.png';static const iconPaymentPng = 'assets/images/icon_payment.png';static const iconUserPng = 'assets/images/icon_user.png';
}

读取图片

...Image.asset(AssetsImages.iconUserPng,...),

直接用你的 AssetsImages 管理,这样不会应拼写错误造成错误

3. 图片组件 image

Image 是一个图像的 Widget ,提供了一些类方法来快捷使用来自内存、本地、网络、Assets 的图片

下面是入口参数说明

//通过ImageProvider来加载图片
const Image({Key key,// ImageProvider,图像显示源@required this.image,this.semanticLabel,this.excludeFromSemantics = false,//显示宽度this.width,//显示高度this.height,//图片的混合色值this.color,//混合模式this.colorBlendMode,//缩放显示模式this.fit,//对齐方式this.alignment = Alignment.center,//重复方式this.repeat = ImageRepeat.noRepeat,//当图片需要被拉伸显示的时候,centerSlice定义的矩形区域会被拉伸,类似.9图片this.centerSlice,//类似于文字的显示方向this.matchTextDirection = false,//图片发生变化后,加载过程中原图片保留还是留白this.gaplessPlayback = false,//图片显示质量this.filterQuality = FilterQuality.low,})// 加载网络图片,封装类:NetworkImage
Image.network(//路径String src,{Key key,//缩放double scale = 1.0,this.semanticLabel,this.excludeFromSemantics = false,this.width,this.height,this.color,this.colorBlendMode,this.fit,this.alignment = Alignment.center,this.repeat = ImageRepeat.noRepeat,this.centerSlice,this.matchTextDirection = false,this.gaplessPlayback = false,this.filterQuality = FilterQuality.low,Map<String, String> headers,})// 加载本地File文件图片,封装类:FileImage
Image.file(//File对象File file,{Key key,double scale = 1.0,this.semanticLabel,this.excludeFromSemantics = false,this.width,this.height,this.color,this.colorBlendMode,this.fit,this.alignment = Alignment.center,this.repeat = ImageRepeat.noRepeat,this.centerSlice,this.matchTextDirection = false,this.gaplessPlayback = false,this.filterQuality = FilterQuality.low,})// 加载本地资源图片,例如项目内资源图片
// 需要把图片路径在pubspec.yaml文件中声明一下,如:
// assets:
//      - packages/fancy_backgrounds/backgrounds/background1.png
// 封装类有:AssetImage、ExactAssetImage
Image.asset(//文件名称,包含路径String name,{Key key,// 用于访问资源对象AssetBundle bundle,this.semanticLabel,this.excludeFromSemantics = false,double scale,this.width,this.height,this.color,this.colorBlendMode,this.fit,this.alignment = Alignment.center,this.repeat = ImageRepeat.noRepeat,this.centerSlice,this.matchTextDirection = false,this.gaplessPlayback = false,String package,this.filterQuality = FilterQuality.low,})// 加载Uint8List资源图片/从内存中获取图片显示
// 封装类:MemoryImage
Image.memory(// Uint8List资源图片Uint8List bytes,{Key key,double scale = 1.0,this.semanticLabel,this.excludeFromSemantics = false,this.width,this.height,this.color,this.colorBlendMode,this.fit,this.alignment = Alignment.center,this.repeat = ImageRepeat.noRepeat,this.centerSlice,this.matchTextDirection = false,this.gaplessPlayback = false,this.filterQuality = FilterQuality.low,})

3.1 colorBlendMode 混合参数

枚举 BlendMode 定义

enum BlendMode {clear,src,dst,srcOver,dstOver,srcIn,dstIn,srcOut,dstOut,srcATop,dstATop,xor,plus,modulate,screen,overlay,darken,lighten,colorDodge,colorBurn,hardLight,softLight,difference,exclusion,multiply,hue,saturation,color,luminosity,
}

效果图

代码

图片色彩 Colors.blue ,混合模式 BlendMode.dstOver

import 'package:flutter/material.dart';class ImagesPage extends StatelessWidget {const ImagesPage({Key? key}) : super(key: key);// BlendModeWidget _buildBlendMode() {return Image.asset('assets/images/welcome.png',color: Colors.blue,colorBlendMode: BlendMode.dstOver,);}@overrideWidget build(BuildContext context) {return Scaffold(body: Center(child: _buildBlendMode(),),);}
}

输出

可以发现底色蓝色,图片浮在上层

3.2 fit 图片大小适配

BoxFit 枚举定义

代码

import 'package:flutter/material.dart';class ImagesPage extends StatelessWidget {const ImagesPage({Key? key}) : super(key: key);// fitWidget _buildFit(fit) {return Column(children: [Text("$fit"),Container(color: Colors.amber,child: SizedBox(width: 200,height: 100,child: Image.asset('assets/images/welcome.png',color: Colors.blue,colorBlendMode: BlendMode.dstOver,fit: fit,),),),],);}@overrideWidget build(BuildContext context) {return Scaffold(body: SingleChildScrollView(child: Center(child: Column(children: [for (var it in BoxFit.values) _buildFit(it),],),),),);}
}

输出

3.3 ImageProvider 图片对象

Image 组件的 image 参数是一个 ImageProvider, 这样的设计好处是你的图片对象可以来自于各种方式

ImageProvider 是一个抽象类,实现类有 FileImage MemoryImage NetWorkImage

/flutter/lib/src/widgets/image.dart

代码

import 'package:flutter/material.dart';class ImagesPage extends StatelessWidget {const ImagesPage({Key? key}) : super(key: key);// ImageProviderWidget _buildImageProvider() {return const Image(image: AssetImage('assets/images/welcome.png'),);}@overrideWidget build(BuildContext context) {return Scaffold(body: Center(child: _buildImageProvider()),);}
}

输出

4. 图标组件 Icon

Icon 组件用来显示可缩放的图标,不会像图片一样失真,还能设置颜色

4.1 定义

  const Icon(// IconData 图标数据this.icon, {Key? key,// 尺寸this.size,// 颜色this.color,// 方向this.textDirection,this.semanticLabel,}) : super(key: key);

4.2 开启 pubspec.yaml

# The following section is specific to Flutter.
flutter:# The following line ensures that the Material Icons font is# included with your application, so that you can use the icons in# the material Icons class.uses-material-design: true

4.3 icon 预览

https://fonts.google.com/icons?selected=Material+Icons

4.4 示例

代码

import 'package:flutter/material.dart';class IconPage extends StatelessWidget {const IconPage({Key? key}) : super(key: key);@overrideWidget build(BuildContext context) {return const Scaffold(body: Icon(Icons.campaign,size: 200,color: Colors.amber,),);}
}

输出

4.5 苹果 Icon

苹果风格 icon 需要用 CupertinoIcons 对象来访问

CupertinoIcons class - cupertino library - Dart API

Icon 地图

5. 按钮组件

5.1 ElevatedButton

定义

 const ElevatedButton({Key? key,// 点击事件required VoidCallback? onPressed,// 长按VoidCallback? onLongPress,// hoverValueChanged<bool>? onHover,ValueChanged<bool>? onFocusChange,// 样式ButtonStyle? style,// 焦点FocusNode? focusNode,bool autofocus = false,Clip clipBehavior = Clip.none,// 按钮内容required Widget? child,})

5.2 ButtonStyle 样式定义

class ButtonStyle with Diagnosticable {/// Create a [ButtonStyle].const ButtonStyle({// 文字this.textStyle,// 背景色this.backgroundColor,// 前景色this.foregroundColor,// 鼠标滑过颜色this.overlayColor,// 阴影this.shadowColor,// 阴影高度this.elevation,// 内边距this.padding,// 最小尺寸this.minimumSize,// 固定 sizethis.fixedSize,// 最大最小尺寸this.maximumSize,// 边框this.side,// 形状this.shape,// 鼠标光标this.mouseCursor,// 紧凑程度this.visualDensity,// 配置可以按下按钮的区域的尺寸this.tapTargetSize,// 定义 [shape] 和 [elevation] 的动画更改的持续时间this.animationDuration,// 检测到的手势是否应该提供声音和/或触觉反馈this.enableFeedback,// 子元素对齐方式this.alignment,// 墨水效果this.splashFactory,});

代码

import 'package:flutter/material.dart';class ButtonPage extends StatelessWidget {const ButtonPage({Key? key}) : super(key: key);@overrideWidget build(BuildContext context) {return Scaffold(body: Center(child: Column(mainAxisAlignment: MainAxisAlignment.center,children: [// ElevatedButtonElevatedButton(onPressed: () {},child: const Text('ElevatedButton'),style: ButtonStyle(// 背景色backgroundColor: MaterialStateProperty.all(Colors.yellow),// 前景色foregroundColor: MaterialStateProperty.all(Colors.red),// 鼠标滑过颜色overlayColor: MaterialStateProperty.all(Colors.blue),// 阴影颜色shadowColor: MaterialStateProperty.all(Colors.red),// 阴影高度elevation: MaterialStateProperty.all(8),// 边框side: MaterialStateProperty.all(const BorderSide(width: 5,color: Colors.cyan,)),// 固定尺寸fixedSize: MaterialStateProperty.all(const Size(200, 100)),),),],),),);}
}

输出

5.3 其它按钮

  • TextButton 文字按钮
  • OutlinedButton 边框按钮
  • IconButton 图标按钮

代码

import 'package:flutter/material.dart';class ButtonPage extends StatelessWidget {const ButtonPage({Key? key}) : super(key: key);@overrideWidget build(BuildContext context) {return Scaffold(body: Center(child: Column(mainAxisAlignment: MainAxisAlignment.center,children: [// 文字按钮TextButton(onPressed: () {},child: const Text('TextButton'),),// 边框按钮OutlinedButton(onPressed: () {},child: const Text('OutlinedButton'),),// 图标按钮IconButton(onPressed: () {},icon: const Icon(Icons.holiday_village,),iconSize: 50,color: Colors.amber,),// 带图标 TextButtonTextButton.icon(onPressed: () {},icon: const Icon(Icons.holiday_village),label: const Text('带图标 TextButton'),),// 带图标 OutlinedButtonOutlinedButton.icon(onPressed: () {},icon: const Icon(Icons.holiday_village),label: const Text('带图标 OutlinedButton'),),],),),);}
}

注意 TextButton.icon OutlinedButton.icon 可以输出带图标文字的按钮

输出

6. 路由管理v1 Navigator 

如果对 路由v2 感兴趣的可以去看下面链接, 这里不做讨论 Flutter 导航 Navgiator 2.0 Page Router 说明 -猫哥_哔哩哔哩_bilibili

6.1 匿名路由 

主要是通过 Push() Pop() 来操作路由,简单场景也能满足业务

6.1.1 Navigator 路由管理对象

Navigator是一个路由管理的组件,它提供了打开和退出路由页方

Future push(BuildContext context, Route route) 压入一个新页面到路由堆栈

bool pop(BuildContext context, [ result ]) 压出一个页面出堆栈

6.1.2 MaterialPageRoute 定义

MaterialPageRoute继承自PageRoute类,PageRoute类是一个抽象类,表示占有整个屏幕空间的一个模态路由页面,它还定义了路由构建及切换时过渡动画的相关接口及属性

  MaterialPageRoute({// 是一个WidgetBuilder类型的回调函数,它的作用是构建路由页面的具体内容,返回值是一个widget。我们通常要实现此回调,返回新路由的实例。WidgetBuilder builder,// 包含路由的配置信息,如路由名称、是否初始路由(首页)。RouteSettings settings,// 默认情况下,当入栈一个新路由时,原来的路由仍然会被保存在内存中,如果想在路由没用的时候释放其所占用的所有资源,可以设置maintainState为 false。bool maintainState = true,// 表示新的路由页面是否是一个全屏的模态对话框,在 iOS 中,如果fullscreenDialog为true,新页面将会从屏幕底部滑入(而不是水平方向)。bool fullscreenDialog = false,})

6.1.3 路由传值

传递可以在初始新界面对象时通过构造函数压入

新界面退出后的返回值通过 Navigator.pop 的参数返回

6.1.4 示例

首页 NavPaged

import 'package:flutter/material.dart';class NavPaged extends StatelessWidget {const NavPaged({Key? key}) : super(key: key);@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text('NavPaged'),),body: Center(child: ElevatedButton(onPressed: () async {var result = await Navigator.push(context,MaterialPageRoute(builder: (context) {return const DetailPaged(title: "ducafecat",);}),);print("路由返回值: $result");},child: const Text("Navigator.push DetailPage"),),),);}
}

详情页 DetailPaged

class DetailPaged extends StatelessWidget {const DetailPaged({Key? key, this.title}) : super(key: key);// 参数final String? title;@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text('DetailPaged'),),body: Center(child: Column(mainAxisAlignment: MainAxisAlignment.center,children: [// 按钮OutlinedButton(onPressed: () {Navigator.pop(context, "ok");},child: const Text('Back'),),// 显示传值Text(title ?? ""),],),),);}
}

6.2 命名路由

这种方式就优雅了很多,事先定义好路由名字

lib/main.dart

 @overrideWidget build(BuildContext context) {return MaterialApp(...routes: {'/': (context) => const NavPaged(),'/details': (context) => const DetailPaged(),},

pushNamed 路由请求, 输入名称即可

onPressed: () async {var result = await Navigator.pushNamed(context,"/details",arguments: {'title': "ducafecat"},);print("路由返回值: $result");
},

取值显示

@override
Widget build(BuildContext context) {// 取值final arguments = (ModalRoute.of(context)?.settings.arguments ?? <String, dynamic>{}) as Map;var title = arguments['title'];...// 显示传值Text(title ?? ""),

6.3 onGenerateRoute 手动解析

上面的命名路由是好,但是 传参数 不灵活,所以采用 onGenerateRoute 来动态处理

6.3.1 定义路由

lib/main.dart

    return MaterialApp(...onGenerateRoute: (settings) {// Handle '/'if (settings.name == '/') {return MaterialPageRoute(builder: (context) => const NavPaged());}// Handle '/details/:id'var uri = Uri.parse(settings.name!);if (uri.pathSegments.length == 2 &&uri.pathSegments.first == 'details') {String uid = uri.pathSegments[1];return MaterialPageRoute(builder: (context) => DetailPaged(uid: uid,),);}return MaterialPageRoute(builder: (context) => const UnknownPage());},

如果没有命中,返回 UnknownPage 界面

6.3.2 导航页完整代码

lib/pages/nav.dart

import 'package:flutter/material.dart';class NavPaged extends StatelessWidget {const NavPaged({Key? key}) : super(key: key);@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text('NavPaged'),),body: Center(child: ElevatedButton(onPressed: () async {var result = await Navigator.pushNamed(context,"/details/312312312312",);print("路由返回值: $result");},child: const Text("Navigator.push DetailPage"),),),);}
}class DetailPaged extends StatelessWidget {const DetailPaged({Key? key, this.uid}) : super(key: key);final String? uid;@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text('DetailPaged'),),body: Center(child: Column(mainAxisAlignment: MainAxisAlignment.center,children: [// 按钮OutlinedButton(onPressed: () {Navigator.pop(context, "ok");},child: const Text('Back'),),// 显示传值Text(uid ?? ""),],),),);}
}class UnknownPage extends StatelessWidget {const UnknownPage({Key? key}) : super(key: key);@overrideWidget build(BuildContext context) {return const Scaffold(body: Text('UnknownPage'),);}
}

路由传值

var result = await Navigator.pushNamed( context, "/details/312312312312", );

运行

7. 样式管理

7.1 ThemeData 样式对象

定义

  factory ThemeData({// 全局配置AndroidOverscrollIndicator? androidOverscrollIndicator,bool? applyElevationOverlayColor,NoDefaultCupertinoThemeData? cupertinoOverrideTheme,InputDecorationTheme? inputDecorationTheme,MaterialTapTargetSize? materialTapTargetSize,PageTransitionsTheme? pageTransitionsTheme,TargetPlatform? platform,ScrollbarThemeData? scrollbarTheme,InteractiveInkFeatureFactory? splashFactory,VisualDensity? visualDensity,bool? useMaterial3,// 颜色管理ColorScheme? colorScheme,Color? colorSchemeSeed,Brightness? brightness,MaterialColor? primarySwatch,Color? primaryColor,Color? primaryColorLight,Color? primaryColorDark,Color? focusColor,Color? hoverColor,Color? shadowColor,Color? canvasColor,Color? scaffoldBackgroundColor,Color? bottomAppBarColor,Color? cardColor,Color? dividerColor,Color? highlightColor,Color? splashColor,Color? selectedRowColor,Color? unselectedWidgetColor,Color? disabledColor,Color? secondaryHeaderColor,Color? backgroundColor,Color? dialogBackgroundColor,Color? indicatorColor,Color? hintColor,Color? errorColor,Color? toggleableActiveColor,// 字体和图标String? fontFamily,Typography? typography,TextTheme? textTheme,TextTheme? primaryTextTheme,IconThemeData? iconTheme,IconThemeData? primaryIconTheme,// 各种组件样式AppBarTheme? appBarTheme,MaterialBannerThemeData? bannerTheme,BottomAppBarTheme? bottomAppBarTheme,BottomNavigationBarThemeData? bottomNavigationBarTheme,BottomSheetThemeData? bottomSheetTheme,ButtonBarThemeData? buttonBarTheme,ButtonThemeData? buttonTheme,CardTheme? cardTheme,CheckboxThemeData? checkboxTheme,ChipThemeData? chipTheme,DataTableThemeData? dataTableTheme,DialogTheme? dialogTheme,DividerThemeData? dividerTheme,DrawerThemeData? drawerTheme,ElevatedButtonThemeData? elevatedButtonTheme,FloatingActionButtonThemeData? floatingActionButtonTheme,ListTileThemeData? listTileTheme,NavigationBarThemeData? navigationBarTheme,NavigationRailThemeData? navigationRailTheme,OutlinedButtonThemeData? outlinedButtonTheme,PopupMenuThemeData? popupMenuTheme,ProgressIndicatorThemeData? progressIndicatorTheme,RadioThemeData? radioTheme,SliderThemeData? sliderTheme,SnackBarThemeData? snackBarTheme,SwitchThemeData? switchTheme,TabBarTheme? tabBarTheme,TextButtonThemeData? textButtonTheme,TextSelectionThemeData? textSelectionTheme,TimePickerThemeData? timePickerTheme,ToggleButtonsThemeData? toggleButtonsTheme,TooltipThemeData? tooltipTheme,

我们在 MaterialApp.theme 中初始

lib/main.dart

import 'package:flutter/material.dart';
import 'package:flutter_application_write_docs/pages/theme.dart';void main() {runApp(const MyApp());
}class MyApp extends StatelessWidget {const MyApp({Key? key}) : super(key: key);@overrideWidget build(BuildContext context) {return MaterialApp(title: 'Flutter Quick Start',// 样式theme: ThemeData(// 主题颜色primarySwatch: Colors.brown,// appBar颜色appBarTheme: ThemeData.light().appBarTheme.copyWith(backgroundColor: Colors.green,foregroundColor: Colors.white,),// 按钮颜色elevatedButtonTheme: ElevatedButtonThemeData(style: ElevatedButton.styleFrom(onPrimary: Colors.white,primary: Colors.amber,),),),// pagehome: const ThemePage(),// 关闭 debug 标签debugShowCheckedModeBanner: false,);}
}

lib/pages/theme.dart

import 'package:flutter/material.dart';class ThemePage extends StatelessWidget {const ThemePage({Key? key}) : super(key: key);@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text('ThemePage'),),body: Center(child: ElevatedButton(onPressed: () {},child: const Text('Theme'),),),);}
}

输出

7.2 Color 与 MaterialColor

Color 颜色

Colors class - material library - Dart API

如设计稿的颜色是 #40c254, 转换成 16 进制颜色

// 字符串转 Color
Color stringToColor(String source) {return Color(int.parse(source, radix: 16) | 0xFF000000);
}Color c = stringToColor("40c254");

MaterialColor 色彩表

MaterialColor class - material library - Dart API

// 字符串转 MaterialColor
MaterialColor stringToMaterialColor(String source) {Color color = stringToColor(source);List<double> strengths = <double>[.05];Map<int, Color> swatch = <int, Color>{};final int r = color.red, g = color.green, b = color.blue;for (int i = 1; i < 10; i++) {strengths.add(0.1 * i);}for (var strength in strengths) {final double ds = 0.5 - strength;swatch[(strength * 1000).round()] = Color.fromRGBO(r + ((ds < 0 ? r : (255 - r)) * ds).round(),g + ((ds < 0 ? g : (255 - g)) * ds).round(),b + ((ds < 0 ? b : (255 - b)) * ds).round(),1,);}return MaterialColor(color.value, swatch);
}MaterialColor mc = stringToColor("40c254");

代码

import 'package:flutter/material.dart';// 字符串转 Color
Color stringToColor(String source) {return Color(int.parse(source, radix: 16) | 0xFF000000);
}// 字符串转 MaterialColor
MaterialColor stringToMaterialColor(String source) {Color color = stringToColor(source);List<double> strengths = <double>[.05];Map<int, Color> swatch = <int, Color>{};final int r = color.red, g = color.green, b = color.blue;for (int i = 1; i < 10; i++) {strengths.add(0.1 * i);}for (var strength in strengths) {final double ds = 0.5 - strength;swatch[(strength * 1000).round()] = Color.fromRGBO(r + ((ds < 0 ? r : (255 - r)) * ds).round(),g + ((ds < 0 ? g : (255 - g)) * ds).round(),b + ((ds < 0 ? b : (255 - b)) * ds).round(),1,);}return MaterialColor(color.value, swatch);
}class ColorPage extends StatelessWidget {const ColorPage({Key? key}) : super(key: key);@overrideWidget build(BuildContext context) {var c = stringToColor("FFB822");var mc = stringToMaterialColor("5C78FF");return Scaffold(body: SizedBox.expand(child: Column(children: [// ColorContainer(color: c,height: 50,),// MaterialColorfor (var i = 1; i < 10; i++)Container(color: mc[i * 100],height: 50,),],),),);}
}

输出

8. 手势事件

8.1 GestureDetector

GestureDetector是一个用于手势识别的功能性组件,我们通过它可以来识别各种手势

定义

GestureDetector({Key? key,this.child,// 单击this.onTapDown,this.onTapUp,this.onTap,this.onTapCancel,// 双指this.onSecondaryTap,this.onSecondaryTapDown,this.onSecondaryTapUp,this.onSecondaryTapCancel,// 三点this.onTertiaryTapDown,this.onTertiaryTapUp,this.onTertiaryTapCancel,// 双击this.onDoubleTapDown,this.onDoubleTap,this.onDoubleTapCancel,// 长按this.onLongPressDown,this.onLongPressCancel,this.onLongPress,this.onLongPressStart,this.onLongPressMoveUpdate,this.onLongPressUp,this.onLongPressEnd,// 两点 三点 长按this.onSecondaryLongPressDown,this.onSecondaryLongPressCancel,this.onSecondaryLongPress,this.onSecondaryLongPressStart,this.onSecondaryLongPressMoveUpdate,this.onSecondaryLongPressUp,this.onSecondaryLongPressEnd,this.onTertiaryLongPressDown,this.onTertiaryLongPressCancel,this.onTertiaryLongPress,this.onTertiaryLongPressStart,this.onTertiaryLongPressMoveUpdate,this.onTertiaryLongPressUp,this.onTertiaryLongPressEnd,// 垂直 水平 Dragthis.onVerticalDragDown,this.onVerticalDragStart,this.onVerticalDragUpdate,this.onVerticalDragEnd,this.onVerticalDragCancel,this.onHorizontalDragDown,this.onHorizontalDragStart,this.onHorizontalDragUpdate,this.onHorizontalDragEnd,this.onHorizontalDragCancel,this.onForcePressStart,this.onForcePressPeak,this.onForcePressUpdate,this.onForcePressEnd,// 点击滑动this.onPanDown,this.onPanStart,this.onPanUpdate,this.onPanEnd,this.onPanCancel,this.onScaleStart,this.onScaleUpdate,this.onScaleEnd,this.behavior,this.excludeFromSemantics = false,this.dragStartBehavior = DragStartBehavior.start,

包含了大量的交互操作

代码

import 'package:flutter/material.dart';class GesturePage extends StatefulWidget {const GesturePage({Key? key}) : super(key: key);@overrideState<GesturePage> createState() => _GesturePageState();
}class _GesturePageState extends State<GesturePage> {double? dx, dy;Widget _buildView() {return GestureDetector(child: Container(color: Colors.amber,width: 200,height: 200,),// 点击onTap: () {print('点击 onTap');},// 长按onLongPress: () {print('长按 onLongPress');},// 双击onDoubleTap: () {print('双击 onLongPress');},// 按下onPanDown: (DragDownDetails e) {print("按下 ${e.globalPosition}");},// 按下滑动onPanUpdate: (DragUpdateDetails e) {setState(() {dx = e.delta.dx;dy = e.delta.dy;});},// 松开onPanEnd: (DragEndDetails e) {print(e.velocity);},);}@overrideWidget build(BuildContext context) {return Scaffold(body: SizedBox.expand(child: Column(mainAxisAlignment: MainAxisAlignment.center,children: [_buildView(),// 显示Text('x: $dx, y: $dy'),],),),);}
}

输出

flutter: 用户手指按下:Offset(127.7, 218.0)
flutter: Velocity(0.0, 0.0)
Reloaded 1 of 585 libraries in 171ms.
Reloaded 2 of 585 libraries in 205ms.
flutter: 按下 Offset(128.0, 188.2)
flutter: 长按 onLongPress
flutter: 按下 Offset(145.0, 214.2)
flutter: Velocity(-44.4, -45.0)

8.2 InkWell

InkWell 是带有水波纹的点击事件的组件

定义

  const InkWell({Key? key,Widget? child,// 点击GestureTapCallback? onTap,GestureTapCallback? onDoubleTap,// 长按GestureLongPressCallback? onLongPress,GestureTapDownCallback? onTapDown,GestureTapCancelCallback? onTapCancel,ValueChanged<bool>? onHighlightChanged,ValueChanged<bool>? onHover,// 光标样式MouseCursor? mouseCursor,// 颜色Color? focusColor,Color? hoverColor,Color? highlightColor,MaterialStateProperty<Color?>? overlayColor,Color? splashColor,InteractiveInkFeatureFactory? splashFactory,double? radius,BorderRadius? borderRadius,ShapeBorder? customBorder,bool? enableFeedback = true,bool excludeFromSemantics = false,FocusNode? focusNode,bool canRequestFocus = true,ValueChanged<bool>? onFocusChange,bool autofocus = false,})

代码

import 'package:flutter/material.dart';class InkWellPage extends StatelessWidget {const InkWellPage({Key? key}) : super(key: key);Widget _buildView() {return InkWell(// 点击onTap: () {},// 水波纹颜色splashColor: Colors.blue,// 高亮颜色highlightColor: Colors.yellow,// 鼠标滑过颜色hoverColor: Colors.brown,//child: const Text('点我 InkWell',style: TextStyle(fontSize: 50,),),);}@overrideWidget build(BuildContext context) {return Scaffold(body: Center(child: _buildView(),),);}
}

输出

9. 输入框 TextField

TextField用于文本输入, 有着丰富的属性,定义如下

9.1 定义

  const TextField({Key? key,// 控制器this.controller,// 焦点管理this.focusNode,// 装饰器 背景 颜色 边框 ...this.decoration = const InputDecoration(),// 键盘输入类型// text	文本输入键盘// multiline	多行文本,需和maxLines配合使用(设为null或大于1)// number	数字;会弹出数字键盘// phone	优化后的电话号码输入键盘;会弹出数字键盘并显示“* #”// datetime	优化后的日期输入键盘;Android上会显示“: -”// emailAddress	优化后的电子邮件地址;会显示“@ .”// url	优化后的url输入键盘; 会显示“/ .”TextInputType? keyboardType,// 键盘动作按钮图标// TextInputAction.search 搜索this.textInputAction,this.textCapitalization = TextCapitalization.none,// 正在编辑的文本样式this.style,this.strutStyle,// 输入框内编辑文本在水平方向的对齐方式this.textAlign = TextAlign.start,this.textAlignVertical,// 文字反向this.textDirection,// 只读this.readOnly = false,ToolbarOptions? toolbarOptions,// 显示光标this.showCursor,// 自动焦点this.autofocus = false,// 密文显示this.obscuringCharacter = '•',this.obscureText = false,this.autocorrect = true,SmartDashesType? smartDashesType,SmartQuotesType? smartQuotesType,// 启用提示this.enableSuggestions = true,// 输入框的最大行数,默认为1;如果为null,则无行数限制。this.maxLines = 1,this.minLines,this.expands = false,// 代表输入框文本的最大长度,设置后输入框右下角会显示输入的文本计数。this.maxLength,@Deprecated('Use maxLengthEnforcement parameter which provides more specific ''behavior related to the maxLength limit. ''This feature was deprecated after v1.25.0-5.0.pre.',)this.maxLengthEnforced = true,this.maxLengthEnforcement,// 输入框内容改变时的回调函数;注:内容改变事件也可以通过controller来监听。this.onChanged,// 编辑完成this.onEditingComplete,// 确认输入内容this.onSubmitted,this.onAppPrivateCommand,// 指定输入格式;当用户输入内容改变时,会根据指定的格式来校验。this.inputFormatters,// 如果为false,则输入框会被禁用,禁用状态不接收输入和事件,同时显示禁用态样式(在其decoration中定义)。this.enabled,// 光标样式// 自定义输入框光标宽度、圆角和颜色this.cursorWidth = 2.0,this.cursorHeight,this.cursorRadius,this.cursorColor,this.selectionHeightStyle = ui.BoxHeightStyle.tight,this.selectionWidthStyle = ui.BoxWidthStyle.tight,this.keyboardAppearance,this.scrollPadding = const EdgeInsets.all(20.0),this.dragStartBehavior = DragStartBehavior.start,this.enableInteractiveSelection = true,this.selectionControls,// 点击this.onTap,// 鼠标this.mouseCursor,this.buildCounter,this.scrollController,this.scrollPhysics,this.autofillHints = const <String>[],this.clipBehavior = Clip.hardEdge,this.restorationId,this.enableIMEPersonalizedLearning = true,})

9.2 示例

代码

import 'package:flutter/material.dart';class InputPage extends StatefulWidget {const InputPage({Key? key}) : super(key: key);@overrideState<InputPage> createState() => _InputPageState();
}class _InputPageState extends State<InputPage> {// 文本消息String _message = "";// 输入框控制器final TextEditingController _controllerName = TextEditingController();final TextEditingController _controllerPassword = TextEditingController();// 管理焦点FocusNode focusNodeName = FocusNode();FocusNode focusNodePassword = FocusNode();FocusScopeNode? focusScopeNode;// 输入框 - 用户名Widget _buildName() {return TextField(// 控制器controller: _controllerName,// 焦点autofocus: true,// 焦点管理focusNode: focusNodeName,// 输入框的样式decoration: const InputDecoration(labelText: '用户名',hintText: '请输入',prefixIcon: Icon(Icons.person),suffixIcon: Icon(Icons.edit),border: OutlineInputBorder(),),// 输入改变事件onChanged: (String value) {setState(() {_message = value;});},// 提交回车事件onSubmitted: (String value) {focusScopeNode ??= FocusScope.of(context);focusScopeNode?.requestFocus(focusNodePassword);},);}// 输入框 - 密码Widget _buildPassword() {return TextField(controller: _controllerPassword,// 密码显示obscureText: true,// 焦点管理focusNode: focusNodePassword,// 输入框的样式decoration: const InputDecoration(labelText: '密码',hintText: '请输入',prefixIcon: Icon(Icons.person),suffixIcon: Icon(Icons.edit),border: OutlineInputBorder(),),);}// 按钮Widget _buildButton() {return ElevatedButton(child: const Text('登录 Now!'),onPressed: () {setState(() {_message ='name:${_controllerName.text}, pass:${_controllerPassword.text}';});},);}// 显示Widget _buildMessage() {return Text(_message);}@overridevoid dispose() {// 释放控制器_controllerName.dispose();_controllerPassword.dispose();super.dispose();}@overrideWidget build(BuildContext context) {return Scaffold(body: Padding(padding: const EdgeInsets.all(8.0),child: Column(children: [_buildName(),const SizedBox(height: 10),_buildPassword(),const SizedBox(height: 10),_buildButton(),const SizedBox(height: 10),_buildMessage(),],),),);}
}

输出

创作不易,希望读者三连支持 💖
赠人玫瑰,手有余香 💖

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/26218.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Echarts 绘制自定义图形

文章目录 需求分析需求 在 Echarts 中绘制一个不规则图形放置在指定位置 分析 可以先从一个六边形画起 可以使用 ECharts 中的『自定义图形』来绘制一个封闭的六边形。以下是一个简单的示例代码,演示了如何使用 ECharts 绘制一个封闭的六边形: <!DOCTYPE html> &l…

《数据结构与算法之美》学习笔记二

前言&#xff1a;本篇文章介绍了一下二叉树中的基本知识点&#xff0c;包括二叉树的种类、二叉树的存储方式以及二叉树的深度和广度优先遍历&#xff1b;以及《数据结构与算法》中对于数组的讲解记录&#xff0c;只记录了本前端能看懂的&#x1f913;&#xff0c;还有很多知识点…

视频行人搜索 (Person Search in Videos)

文章目录 视频行人搜索 (Person Search in Videos)图像行人搜索存在问题Video PS 定义MTA-PS数据集First person search dataset in videosComplicated ambient conditions and realistic monitoring scenariosPrivacy insensitivity 方法 视频行人搜索 (Person Search in Vide…

FiRa标准UWB MAC实现(三)——距离如何获得?

继续前期FiRa MAC相关介绍,将FiRa UWB MAC层相关细节进一步进行剖析,介绍了UWB技术中最重要的一个点,高精度的距离是怎么获得的,具体使用的测距方法都有哪些,原理又是什么。为后续FiRa UWB MAC的实现进行铺垫。 3、测距方法 3.1 SS-TWR SS-TWR为Single-Sided Two-Way Ra…

ER实体关系图(一)

用户表(user)、用户钱包表(user_wallet)(与user是1对1关系)、用户钱包交易日志表(user_wallet_log)(与user是1对多关系) user&#xff1a;用户表通常包含用户的基本信息&#xff0c;例如用户ID&#xff08;主键&#xff09;、用户名、密码&#xff08;通常加密存储&#xff09;…

Windows远程桌面连接

试验&#xff1a;使用Oracle VM VirtualBox创建虚拟机与物理机进行远程桌面连接实验 1. 准备 使用VirtualBox创建一台win10虚拟机&#xff0c;并与本地物理机相互ping通。&#xff08;注意&#xff1a;如何存在ping不通&#xff0c;可以试一下关闭Windows的防火墙&#xff09;…

iLogtail 2.0 重大升级,端上支持 SPL

作者&#xff1a;太业 流式处理语言发展 早期流式处理概念&#xff1a; 20 世纪 70 年代&#xff0c;编程语言如 APL 提供了对数组的流式操作&#xff0c;这可以看作是流式处理语法的早期形式。管道&#xff08;Pipes&#xff09;概念在 UNIX 系统中的引进使得可以通过命令行将…

课时152:项目发布_手工发布_方案解读

1.2.1 方案解读 学习目标 这一节&#xff0c;我们从 基础知识、简单实践、小结 三个方面来学习 基础知识 案例需求 实现一套业务环境的项目发布流程&#xff0c;基本的网站架构效果如下&#xff1a;架构解读&#xff1a;负载均衡采用Nginx服务&#xff0c;基于请求内容进行…

孩子用的灯什么样的好?劣质LED台灯所带来的三大危害

随着科技设备不断的进步&#xff0c;护眼台灯已经逐渐成为了书房中不可或缺的一员。它以多功能的特性赢得了广大消费者的青睐。然而&#xff0c;市面上的护眼台灯质量良莠不齐&#xff0c;这使得消费者的选择变得更加困难。不良产品不仅可能带来安全隐患&#xff0c;甚至有潜在…

AI 大模型训练中,通常会采用哪些方法?(输入篇)

大家好 某种程度来说大模型训练的核心算法就是300到400行代码&#xff0c;如果真正理解了并不难。下面我将带大家分析常规大模型训练有几个阶段以及在训练中一般会用到哪些方法。 由上图可以看出&#xff0c;大模型训练主要有四个阶段&#xff1a;预训练、有监督微调、奖励建模…

大模型的高考数学成绩单:及格已经非常好了

让考生头皮发麻的高考数学&#xff0c;可难倒了顶尖 AI 大模型。 一年一度的高考即将落幕&#xff0c;衷心希望各位考生都超常发挥&#xff0c;考出满意的好成绩&#xff01;&#xff01; 和往年一样&#xff0c;除了让 AI 大模型写写高考作文&#xff0c;我们也选取了六家国…

打工人和学生党的福利,NewspaceGpt使用新体验

使用地址&#xff1a;https://newspace.ai0.cn/ 个人名片 &#x1f393;作者简介&#xff1a;java领域优质创作者 &#x1f310;个人主页&#xff1a;码农阿豪 &#x1f4de;工作室&#xff1a;新空间代码工作室&#xff08;提供各种软件服务&#xff09; &#x1f48c;个人邮…

小型气象站:现代气象监测的便携化解决方案

TH-QC12在气象监测领域&#xff0c;技术的不断创新和进步推动了监测设备的多样化和便携化。小型气象站作为这一趋势下的产物&#xff0c;以其体积小、功能全、操作简便等特点&#xff0c;受到了广泛的关注和应用。 小型气象站的技术特点 小型气象站集成了多种气象传感器&…

提升易用性,OceanBase生态管控产品的“从小到大”

2022年&#xff0c;OceanBase发布4.0版本“小鱼”&#xff0c;并首次公开提出了单机分布式一体化这一理念&#xff0c;旨在适应大小不同规模的工作负载&#xff0c;全面满足用户数据库“从小到大”全生命周期的需求。当时&#xff0c;我们所说的“从小到大”主要聚焦于数据库的…

【Qt 学习笔记】Qt窗口 | 对话框 | 模态与非模态对话框的创建

博客主页&#xff1a;Duck Bro 博客主页系列专栏&#xff1a;Qt 专栏关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家点赞&#x1f44d;收藏⭐评论✍ Qt窗口 | 对话框 | 创建模态及非模态对话框 文章编号&#xff1a;Qt 学…

准橙人工翻译微信小程序,100+专业领域的译者在线帮你翻译!藏语、维吾尔语、哈萨克语、壮语、彝文、蒙古语统统支持人工翻译!

亲爱的朋友们&#xff0c;我们深知每一种语言都承载着独特的文化和历史&#xff0c;为了传承和弘扬这些宝贵的文化遗产&#xff0c;我们诚挚地邀请具备翻译经验并熟练掌握以下任意一门语言的您加入我们的团队&#xff01; 中国少数民族语言&#xff1a;藏语、维吾尔语、哈萨克…

懵了!伦敦银是现货白银吗?

近期&#xff0c;伦敦银价格出现了比较强势的上涨&#xff0c;很多朋友想入场炒银。不过当他们接触伦敦银交易市场的时候就懵了&#xff0c;这个交易品种好像有很多名称&#xff0c;一会儿说伦敦银&#xff0c;一会儿说现货白银&#xff0c;搞得自己都混乱了。到底伦敦银是现货…

CVE-2023-37569(未授权任意文件上传+弱口令爆破)

靶场简介 Online Piggery Management System v1.0 - 存在未授权的文件上传漏洞&#xff0c;登陆界面弱口令爆破 进入靶场 猜测弱口令admin/admin&#xff0c;错误&#xff0c;进行账号密码爆破 得到账号密码 admin/password 登陆进入&#xff0c;找到一处文件上传位置 上传…

千问Qwen7B chat:本地部署及网页端使用

基于前面的安装经验&#xff0c;千问大模型的本地部署并不算难&#xff0c;主要时间用在大模型文件的下载上。同时系统运行对硬件也有较高的要求&#xff0c;本机的硬件配置为N卡3060&#xff0c;显存12G。 使用conda创建虚拟环境&#xff0c;主要版本如下&#xff1a; Pyth…

生成式人工智能 - stable diffusion web-ui安装教程

一、Stable Diffusion WEB UI 屌丝劲发作了,所以本地调试了Stable Diffusion之后,就去看了一下Stable Diffusion WEB UI,网络上各种打包套件什么的好像很火。国内的也就这个层次了,老外搞创新,国内跟着屁股后面搞搞应用层,就叫大神了。 不扯闲篇了,我们这里从git源码直接…