轮播组件
card_swiper库
说明地址:https://pub.dev/packages/card_swiper
card_swiper : ^3.0.0
使用
List swiperList = [
{'url': 'https://www.ronhai.com/images/focus/focus01.png'},
{'url': 'https://www.ronhai.com/images/focus/focus01.png'},
{'url': 'https://www.ronhai.com/images/focus/focus01.png'},
];
Swiper(
itemBuilder: (BuildContext context, int index) {
return Image.network(
controller.swiperList[index]['url'],
fit: BoxFit.fill,
);
},
itemCount: 3,
autoplay: true,
pagination: SwiperPagination(builder: SwiperPagination.dots),
// control: SwiperControl(),//左右箭头
),
圆角实现
Widget swiper() {
return Container(
width: ScreenAdapter.getScreenWidth(),
height: ScreenAdapter.height(280),
padding: const EdgeInsets.fromLTRB(30, 0, 30, 0),
decoration: const BoxDecoration(color: Colors.red),
child: Container(
width: ScreenAdapter.getScreenWidth(),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(16), color: Colors.pink),
child: ClipRRect(
clipBehavior: Clip.hardEdge, //确保裁剪行为强制生效,避免滚动时圆角效果消失
borderRadius: BorderRadius.circular(16),
child: Swiper(
itemBuilder: (BuildContext context, int index) {
return Image.network(
swiperList[index]['url'],
fit: BoxFit.cover,
);
},
itemCount: 3,
autoplay: true,
pagination:
const SwiperPagination(builder: SwiperPagination.dots),
),
)),
);
}
屏幕适配组件
说明地址:https://pub.dev/packages/flutter_screenutil
中文文档:https://github.com/OpenFlutter/flutter_screenutil/blob/master/README_CN.md
安装
dependencies:
flutter:
sdk: flutter
# 添加依赖
flutter_screenutil: ^{latest version}
属性
属性 | 类型 | 默认值 | 描述 |
---|---|---|---|
designSize | Size | Size(360, 690) | 设计稿中设备的尺寸(单位随意,建议dp,但在使用过程中必须保持一致) |
deviceSize | Size | null | 物理设备的大小 |
builder | Widget Function() | Container() | 一般返回一个MaterialApp类型的Function() |
orientation | Orientation | portrait | 屏幕方向 |
splitScreenMode | bool | false | 支持分屏尺寸 |
minTextAdapt | bool | false | 是否根据宽度/高度中的最小值适配文字 |
context | BuildContext | null | 传入context会更灵敏的根据屏幕变化而改变 |
child | Widget | null | builder的一部分,其依赖项属性不使用该库 |
rebuildFactor | Function | default | 返回屏幕指标更改时是否重建。 |
初始化并设置适配尺寸及字体大小是否根据系统的“字体大小”辅助选项来进行缩放在使用之前请设置好设计稿的宽度和高度,传入设计稿的宽度和高度(单位随意,但在使用过程中必须保持一致) 一定要进行初始化(只需设置一次),以保证在每次使用之前设置好了适配尺寸:
配置
您必须在app中使用它一次
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'app/routes/app_pages.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart'; //引用
void main() {
//配置入口
runApp(ScreenUtilInit(
designSize: const Size(1080, 2400),
minTextAdapt: true,
splitScreenMode: true,
builder: (context, child) {
return GetMaterialApp(
title: "Application",
initialRoute: AppPages.INITIAL,
getPages: AppPages.routes,
);
},
));
}
使用
import 'package:flutter_screenutil/flutter_screenutil.dart';
//宽高
Container(
width: 1080.w,
height: 590.h,
color: Colors.pink,
),
SizedBox(
height: 30.h,
),
//字号大小
Text(
'屏幕字体',
style: TextStyle(fontSize: 32.sp),
)
使用封装
在/lib/service/screenAdapter.dart
import 'package:flutter_screenutil/flutter_screenutil.dart';
class Screenadapter {
static width(num v) {
return v.w;
}
static height(num v) {
return v.h;
}
static fontSize(num v) {
return v.sp;
}
static getScreenWidth() {
// return ScreenUtil().screenWidth;
return 1.sw;
}
static getScreenHeight() {
// return ScreenUtil().scaleHeight;
return 1.sh;
}
static statusBarHeight() {
return ScreenUtil().statusBarHeight;
}
}
使用
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../controllers/category_controller.dart';
import '../../../service/screenAdapter.dart';
class CategoryView extends GetView<CategoryController> {
const CategoryView({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('CategoryView'),
centerTitle: true,
),
body: ListView(
children: [
Container(
width: Screenadapter.getScreenWidth(),
height: Screenadapter.getScreenHeight(),
color: Colors.black38,
)
],
),
);
}
}
Html转义
组件flutter_html 3.0.0
地址:https://pub.dev/packages/flutter_html/versions/3.0.0-beta.2
安装
dependencies:
flutter_html: ^3.0.0-beta.2
导入 现在在你的 Dart 代码中,你可以使用:
import 'package:flutter_html/flutter_html.dart';
使用
Padding(
padding: const EdgeInsets.all(10),
child: Html(
data: _list[0]['content'],
style: {
"body": Style(backgroundColor: Colors.white),
'p': Style(fontSize: FontSize.xxSmall)
},
),
)
webView
flutter_inappwebview组件
pub地址:https://pub.dev/packages/flutter_inappwebview
安装
dependencies:
flutter_inappwebview: ^6.1.5
使用
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
class NewDetailWebPage extends StatefulWidget {
final Map arguments;
const NewDetailWebPage({super.key, required this.arguments});
@override
State<NewDetailWebPage> createState() => _NewDetailWebPageState();
}
class _NewDetailWebPageState extends State<NewDetailWebPage> {
@override
void initState() {
super.initState();
print(widget.arguments['aid']);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('新闻详情'),
),
body: Column(
children: [
Expanded(
child: InAppWebView(
initialUrlRequest: URLRequest(
url: WebUri(
"https://www.dazhuzi.com/newscontent.php?aid=${widget.arguments['aid']}")),
))
],
)
)
}
}
device_info_plus
获取设备信息插件
pub地址:https://pub.dev/packages/device_info_plus/install
安装
dependencies:
device_info_plus: ^11.2.2
使用
import 'package:flutter/material.dart';
import 'package:device_info_plus/device_info_plus.dart';
class DeviceInfoPage extends StatefulWidget {
const DeviceInfoPage({super.key});
@override
State<DeviceInfoPage> createState() => _DeviceInfoPageState();
}
class _DeviceInfoPageState extends State<DeviceInfoPage> {
List<Widget> _list = [];
_getInfo() async {
final deviceInfoPlugin = DeviceInfoPlugin();
final deviceInfo = await deviceInfoPlugin.deviceInfo;
final allInfo = deviceInfo.data; //拿到的是个map对象
print(allInfo is Map); //true
var tempList = allInfo.entries.map((e) {
return ListTile(
title: Text(e.key),
subtitle: Text(e.value.toString()),
);
}).toList();
setState(() {
_list = tempList;
});
}
@override
void initState() {
super.initState();
_getInfo();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('设备信息')),
body: ListView(
children: _list,
),
);
}
}
connectivity_plus
检测网络插件
pub地址:https://pub.dev/packages/connectivity_plus
安装
dependencies:
connectivity_plus: ^6.1.2
使用
import 'package:flutter/material.dart';
import 'dart:async';
import 'package:connectivity_plus/connectivity_plus.dart';
class DeviceNetworkPage extends StatefulWidget {
const DeviceNetworkPage({super.key});
@override
State<DeviceNetworkPage> createState() => _DeviceNetworkPageState();
}
class _DeviceNetworkPageState extends State<DeviceNetworkPage> {
late StreamSubscription<List<ConnectivityResult>> subscription;
@override
void initState() {
super.initState();
subscription = Connectivity()
.onConnectivityChanged
.listen((List<ConnectivityResult> result) {
print(result[0]);
if (result[0] == ConnectivityResult.wifi) {
print('wifi网络');
} else if (result[0] == ConnectivityResult.ethernet) {
print('以太网网络');
} else if (result[0] == ConnectivityResult.mobile) {
print('手机网络');
} else if (result[0] == ConnectivityResult.vpn) {
print('vpn网络');
} else if (result[0] == ConnectivityResult.none) {
print('没有网络');
} else if (result[0] == ConnectivityResult.other) {
print('其它网络');
}
});
}
@override
void dispose() {
subscription.cancel();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('检测网络')),
body: const Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [Text('检测网络')],
),
),
);
}
}
url_launcher
配置打开URL、拨打电话 、发送短信 、打开外部应用、打开高德地图
pub地址:https://pub.dev/packages/url_launcher
安装
dependencies:
url_launcher: ^6.3.1
使用
打开浏览器访问页面
import 'package:flutter/material.dart';
import 'package:url_launcher/url_launcher.dart';
class Deviceurllauncher extends StatefulWidget {
const Deviceurllauncher({super.key});
@override
State<Deviceurllauncher> createState() => _DeviceurllauncherState();
}
class _DeviceurllauncherState extends State<Deviceurllauncher> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('url_launcher')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
onPressed: () async {
final Uri _url = Uri.parse('http://dazhuzi.com');
if (await canLaunchUrl(_url)) {
await launchUrl(_url);
} else {
print('没有办法打开这个地址');
}
},
child: const Text('打开浏览器'),
),
],
),
),
);
}
}
安卓配置
修改:android\app\src\main\AndroidManifest.xml
<queries>
<!-- If your app checks for SMS support -->
<intent>
<action android:name="android.intent.action.VIEW" />
<data android:scheme="sms" />
</intent>
<!-- If your app checks for call support -->
<intent>
<action android:name="android.intent.action.VIEW" />
<data android:scheme="tel" />
</intent>
<!-- If your application checks for inAppBrowserView launch mode support -->
<intent>
<action android:name="android.support.customtabs.action.CustomTabsService" />
</intent>
</queries>
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"/>
ios配置
配置拨打电话、发送邮件、打开外部应用、高德地图导航Info.plist,在xcode中增加以下代码后重新运行flutter项目.
<key>LSApplicationQueriesSchemes</key>
<array>
<string>iosamap</string>
<string>sbaidumaps</string>
<string>sms</string>
<string>tel</string>
<string>weixin</string>
<string>alipays</string>
</array>
可以打开源码方式增加,如下图:
发送短信
ElevatedButton(
child: const Text('发送短信'),
onPressed: () async {
final Uri tel = Uri.parse('sms:10086');
if (await canLaunchUrl(tel)) {
await launchUrl(tel);
} else {
print('没有办法发送短信$tel');
}
},
),
拨打电话
ElevatedButton(
child: const Text('拨打电话'),
onPressed: () async {
final Uri tel = Uri.parse('tel:10086');
if (await canLaunchUrl(tel)) {
await launchUrl(tel);
} else {
print('没有办法拨打电话$tel');
}
},
),
打开外部App
ElevatedButton(
child: const Text('打开支付宝'),
onPressed: () async {
final Uri alipays = Uri.parse('alipays://');
if (await canLaunchUrl(alipays)) {
await launchUrl(alipays);
} else {
print('没有办法打开支付宝');
}
},
),
const SizedBox(
height: 30,
),
ElevatedButton(
child: const Text('打开微信'),
onPressed: () async {
final Uri wechat = Uri.parse('weixin://');
if (await canLaunchUrl(wechat)) {
await launchUrl(wechat);
} else {
print('没有办法打开支付宝');
}
},
),
高德地图App
高德官网导航地址:https://lbs.amap.com/api/amap-mobile/guide/android/navigation
坐标吸取器:https://lbs.amap.com/tools/picker
ElevatedButton(
child: const Text('打开高德地图'),
onPressed: () async {
String title = '洪崖洞';
String longitude = "106.575329";
String latitude = "29.557253";
Uri uri = Uri.parse(
'${Platform.isAndroid ? 'android' : 'ios'}amap://navi?sourceApplication=amap&poiname=$title&lat=$latitude&lon=$longitude&dev=0&style=2pkg=com.autonavi.minimap');
if (await canLaunchUrl(uri)) {
await launchUrl(uri);
} else {
print('没有办法打开高德地图');
}
},
),
常见App的scheme
电商
taobao : 淘宝
tmall : 天猫
jdlogin : 京东
pinduoduo : 拼多多
kaola : 网易考拉
yanxuan : 网易严选
vipshop : 唯品会
suning : 苏宁
mishopv1 : 小米商城
wireless1688 : 阿里巴巴
社交、社区
weibo : 微博
zhihu : 知乎
xhsdiscover : 小红书
momochat : 陌陌
blued : blued
mqzone : QQ空间
mqq : QQ
tantanapp : 探探
huputiyu : 虎扑
com.baidu.tieba : 贴吧
tianya : 天涯社区
douban : 豆瓣
jike : 即刻
短视频
snssdk1128 : 抖音
snssdk1112 : 火山
snssdk32 : 西瓜视频
gifshow : 快手
视频/直播
tenvideo : 腾讯视频
youku : 优酷
bilibili : B站
imgotv : 芒果TV
qiyi-iphone : 爱奇艺
hanju : 韩剧TV
douyutv : 斗鱼
yykiwi : 虎牙
图片处理
mtxx.open : 美图秀秀
faceu : faceu国内
ulike : 轻颜国内
资讯
snssdk141 : 今日头条
newsapp : 网易新闻
qqnews : 腾讯新闻
iting : 喜马拉雅
weread : 微信读书
jianshu : 简书
igetApp : 得到
kuaikan : 快看漫画
财经
sinanews : 新浪财经
amihexin : 同花顺炒股
音乐
orpheus : 网易云音乐
qqmusic : qq音乐
kugouURL : 酷狗
qmkege : 全民K歌
changba : 唱吧
工具
iosamap : 高德地图
baidumap : 百度地图
baiduyun : 百度网盘
rm434209233MojiWeather : 墨迹天气
办公
wxwork : 企业微信
dingtalk : 钉钉
生活
imeituan : 美团
dianping : 点评
cainiao : 菜鸟裹裹
wbmain : 58同城
mihome : 米家
美食佳饮
xcfapp : 下厨房
sbuxcn : 星巴克中国
meituanwaimai : 美团外卖
运动健康
fb370547106731052 : 小米运动
meetyou.linggan : 美柚
babytree : 宝宝树
keep : keep
旅行
CtripWireless : 携程
diditaxi : 滴滴
taobaotravel : 飞猪
travelguide : 马蜂窝
游戏
tencent1104466820 : 王者荣耀
tencent100689805 : 天天爱消除
tencent382 : QQ斗地主
video_player播放视频
播放视频
pub地址:https://pub.dev/packages/video_player
安装
dependencies:
video_player: ^2.9.2
配置
Android配置
/android/app/src/main/AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET"/>
android也需要https才可以播放
Ios无需配置,注意要使用https协议
使用
import 'package:flutter/material.dart';
import 'package:video_player/video_player.dart';
class VideoPlayerPage extends StatefulWidget {
const VideoPlayerPage({super.key});
@override
State<VideoPlayerPage> createState() => _VideoPlayerPageState();
}
class _VideoPlayerPageState extends State<VideoPlayerPage> {
late VideoPlayerController _controller;
@override
void initState() {
super.initState();
_controller = VideoPlayerController.networkUrl(
Uri.parse('https://vjs.zencdn.net/v/oceans.mp4'))
..initialize().then((_) {
setState(() {});
});
}
@override
void dispose() {
// TODO: implement dispose
super.dispose();
_controller.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('视频播放'),
),
body: Center(
child: _controller.value.isInitialized
? AspectRatio(
aspectRatio: _controller.value.aspectRatio,
child: VideoPlayer(_controller),
)
: AspectRatio(
aspectRatio: _controller.value.aspectRatio,
child: Container(color: Colors.red),
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
setState(() {
_controller.value.isPlaying
? _controller.pause()
: _controller.play();
});
},
child: Icon(
_controller.value.isPlaying ? Icons.pause : Icons.play_arrow,
),
),
);
}
}
chewie播放视频
在 Flutter 里官方提供了一个 video_player插件可以播放视频。但是video_player有一些局限性。没法 控制底部播放进度等。 所以我们主要给大家讲解一个第三方的视频播放库chewie。chewie是一个非官 方的第三方视频播放组件,看起来好像是基于 HTML5 播放的组件。chewie 相对 video_player 来说, 有控制栏和全屏的功能。Chewie 使用 video_player 引擎并将其包裹在友好的 Material 或 Cupertino UI 中!
pub地址:https://pub.dev/packages/chewie
chewie基于video_player,所以要使用chewie必须配置video_player
安装
dependencies:
chewie: ^1.10.0
video_player: ^2.9.2
使用
import 'package:flutter/material.dart';
import 'package:video_player/video_player.dart';
import 'package:chewie/chewie.dart';
class ChewiePage extends StatefulWidget {
const ChewiePage({super.key});
@override
State<ChewiePage> createState() => _ChewiePageState();
}
class _ChewiePageState extends State<ChewiePage> {
late ChewieController chewieController;
late VideoPlayerController videoPlayerController;
@override
void initState() {
super.initState();
videoPlayerController = VideoPlayerController.networkUrl(Uri.parse(
'https://stream7.iqilu.com/10339/article/202002/17/778c5884fa97f460dac8d90493c451de.mp4'));
chewieController = ChewieController(
videoPlayerController: videoPlayerController,
aspectRatio: 3 / 2, //视频宽高比
autoPlay: false,
looping: true,
//自定义显示播放速度
optionsBuilder: (context, defaultOptions) async {
await showModalBottomSheet(
context: context,
builder: (context) {
return SizedBox(
height: 200,
child: ListView(
children: [
ListTile(
title: const Text('播放速度'),
onTap: () {
defaultOptions[0].onTap!(context);
},
),
ListTile(
title: const Text('取消'),
onTap: () {
Navigator.pop(context);
},
)
],
),
);
});
},
);
}
@override
void dispose() {
super.dispose();
videoPlayerController.dispose();
chewieController.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('chewie播放视频'),
),
body: Center(
child: AspectRatio(
aspectRatio: 3 / 2,
child: Chewie(controller: chewieController),
),
));
}
}
ImagePicker
ImagePicker拍照、录制视频、相册选择照片、相册选择视频、上传文件
pub地址:https://pub.dev/packages/image_picker
安装
dependencies:
image_picker: ^1.1.2
配置
android无需配置开箱即用,ios还需要配置info.plist
<key>NSPhotoLibraryUsageDescription</key>
<string>应用需要访问相册读取文件</string>
<key>NSCameraUsageDescription</key>
<string>应用需要访问相机拍照</string>
<key>NSMicrophoneUsageDescription</key>
<string>应用需要访问麦克风录制视频</string>
注意:使用相机拍摄的图像和视频会保存到应用程序的本地缓存中,因此应该只是暂时存在。如果您需 要永久存储您挑选的图像,您有责任将其移动到更永久的位置
相机拍照和相册选择
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
class SelectPhotoPage extends StatefulWidget {
const SelectPhotoPage({super.key});
@override
State<SelectPhotoPage> createState() => _SelectPhotoPageState();
}
class _SelectPhotoPageState extends State<SelectPhotoPage> {
final ImagePicker picker = ImagePicker();
XFile? _pickerFile;
//选择照片
_pickerGallery() async {
XFile? pickerFile = await picker.pickImage(source: ImageSource.gallery);
if (pickerFile != null) {
print(pickerFile.path);
setState(() {
_pickerFile = pickerFile;
});
}
}
//拍照
_pickerCamera() async {
XFile? pickerFile = await picker.pickImage(source: ImageSource.camera);
if (pickerFile != null) {
print(pickerFile.path);
setState(() {
_pickerFile = pickerFile;
});
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('选择照片拍照'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
onPressed: _pickerGallery, child: const Text('相册选择')),
const SizedBox(
height: 30,
),
ElevatedButton(onPressed: _pickerCamera, child: const Text('拍照')),
const SizedBox(
height: 30,
),
SizedBox(
width: double.infinity,
height: 200,
child: _pickerFile == null
? Text('选择照片...')
: Image.file(File(_pickerFile!.path)),
),
],
)));
}
}
录制视频和上传视频和图片
toggle_switch
一个简单的切换开关小部件。它可以根据需要自定义图标、宽度、颜色、文本、角半径、动画等。它还可以保持选择状态。
pub地址:https://pub.dev/packages?q=toggle_switch
安装
dependencies:
toggle_switch: ^2.3.0
使用
import 'package:toggle_switch/toggle_switch.dart';