Flutter常用知識
獲取狀態欄高度
import "dart:ui";
MediaQueryData.fromWindow(window).padding.top;
/// ToolBar的高度
const double kToolbarHeight = 56.0;
/// 底部導航欄的高度
const double kBottomNavigationBarHeight = 56.0;
/// 包含文本的標簽欄的高度
const double kTextTabBarHeight = 48.0;
設置沉浸式狀態欄
import 'dart:io';
import 'package:flutter/services.dart';
void main() {
runApp(MyApp());
if (Platform.isAndroid) {
SystemUiOverlayStyle systemUiOverlayStyle =
SystemUiOverlayStyle(statusBarColor: Colors.transparent);
SystemChrome.setSystemUIOverlayStyle(systemUiOverlayStyle);
}
}
APP設置橫屏
void main() {
WidgetsFlutterBinding.ensureInitialized();
SystemChrome.setPreferredOrientations(
[DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight]);
runApp(MyApp());
}
漸變標題欄
Scaffold(
extendBodyBehindAppBar: true, // 將body至於Appbar下
appBar: AppBar(
flexibleSpace: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [
Color(0xffc2e59c),
Color(0xff64b3f4),
],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
)
),
),
// 設置AppBar形狀
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(bottom: Radius.circular(40)),
),
),
)
設置底部虛擬按鍵顏色
import 'dart:io';
import 'package:flutter/services.dart';
void main() {
runApp(MyApp());
if (Platform.isAndroid) {
SystemUiOverlayStyle style = SystemUiOverlayStyle(
systemNavigationBarColor: Color(0xFFFFFFFF), // 背景色
systemNavigationBarIconBrightness: Brightness.dark, // 圖標色
);
SystemChrome.setSystemUIOverlayStyle(systemUiOverlayStyle);
}
}
在runApp()前初始方法
WidgetsFlutterBinding.ensureInitialized();
更改某一頁狀態欄導航欄顏色
AnnotatedRegion(
value: SystemUiOverlayStyle.light,
child: Scaffold(body:Text('頁面'),),
);
更改某一頁狀態欄或導航欄顯示樣式后其他頁面改回去
WillPopScope(
onWillPop: () async {
SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual,
overlays: [SystemUiOverlay.top, SystemUiOverlay.bottom]);
SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlayStyle(
systemNavigationBarColor: Colors.white,
systemNavigationBarIconBrightness: Brightness.dark));
return true;
},
child: Scaffold(),
);
監聽APP生命周期
import 'package:flutter/material.dart';
///前后台應用測試
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> with WidgetsBindingObserver{
@override
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this); //添加觀察者
}
@override
void dispose() {
super.dispose();
print('YM--------dispose');
WidgetsBinding.instance.removeObserver(this); //添加觀察者
}
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Material App',
home: Scaffold(
appBar: AppBar(
title: Text('Material App Bar'),
),
body: Center(
child: Container(
child: Text('Hello World'),
),
),
),
);
}
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
super.didChangeAppLifecycleState(state);
switch (state) {
case AppLifecycleState.inactive:
// 應用程序處於閑置狀態並且沒有收到用戶的輸入事件。
//注意這個狀態,在切換到后台時候會觸發,所以流程應該是先凍結窗口,然后停止UI
print('YM----->AppLifecycleState.inactive');
break;
case AppLifecycleState.paused:
// 應用程序處於不可見狀態
print('YM----->AppLifecycleState.paused');
break;
case AppLifecycleState.resumed:
// 進入應用時候不會觸發該狀態
// 應用程序處於可見狀態,並且可以響應用戶的輸入事件。它相當於 Android 中Activity的onResume。
print('YM----->AppLifecycleState.resumed');
break;
case AppLifecycleState.detached:
//當前頁面即將退出
print('YM----->AppLifecycleState.detached');
break;
}
}
///當前系統改變了一些訪問性活動的回調
@override
void didChangeAccessibilityFeatures() {
super.didChangeAccessibilityFeatures();
print("YM-----@@@@@@@@@ didChangeAccessibilityFeatures");
}
///低內存回調
@override
void didHaveMemoryPressure() {
super.didHaveMemoryPressure();
print("YM-----@@@@@@@@@ didHaveMemoryPressure");
}
///用戶本地設置變化時調用,如系統語言改變
@override
void didChangeLocales(List<Locale> locale) {
super.didChangeLocales(locale);
print("YM-----@@@@@@@@@ didChangeLocales");
}
///應用尺寸改變時回調,例如旋轉
@override
void didChangeMetrics() {
super.didChangeMetrics();
Size size = WidgetsBinding.instance.window.physicalSize;
print("YM-----@@@@@@@@@ didChangeMetrics :寬:${size.width} 高:${size.height}");
}
@override
Future<bool> didPopRoute() {
print('YM--------didPopRoute');//頁面彈出
return Future.value(false);//true為攔截,false不攔截
}
@override
Future<bool> didPushRoute(String route) {
print('YM--------PushRoute');
return Future.value(true);
}
@override
Future<bool> didPushRouteInformation(RouteInformation routeInformation) {
print('YM--------didPushRouteInformation');
return Future.value(true);
}
//文字大小改變時候的監聽
@override
void didChangeTextScaleFactor() {
print("YM--------@@@@@@@@@ didChangeTextScaleFactor :${WidgetsBinding.instance.window.textScaleFactor}");
}
@override
void didChangePlatformBrightness() {
final window = WidgetsBinding.instance.window;
final brightness = window.platformBrightness;
// Brightness.light 亮色
// Brightness.dark 暗色
print('YM----平台主題改變----didChangePlatformBrightness$brightness');
// window.onPlatformBrightnessChanged = () {
// // This callback gets invoked every time brightness changes
// final brightness = window.platformBrightness;
// print('YM----平台亮度改變----didChangePlatformBrightness$brightness');
// };
}
}
ElevatedButton設置圓角
ElevatedButton(
onPressed: () {},
child: Text('Button'),
style: ElevatedButton.styleFrom(shape: StadiumBorder()),
)
點擊空白處取消TextField焦點收起鍵盤
GestureDetector(
// 空白處點擊生效
behavior: HitTestBehavior.translucent,
onTap: () {
// 觸摸收起鍵盤
FocusScope.of(context).requestFocus(FocusNode());
},
child: ****視圖內容***
}
內容不隨鍵盤滾動,防止出現軟鍵盤內容溢出
Scafflod(
// 已刪除resizeToAvoidBottomPadding: false
resizeToAvoidBottomInset: false
)
軟鍵盤彈出遮擋住內容
AnimatedPadding(
padding: MediaQuery.of(context).viewInsets,
duration: const Duration(milliseconds: 100),
child: ...
);
滑動刪除列表
Dismissible(
key: Key(item),
onDismissed: (direction){
setState(() {
items.removeAt(index);
});
final snackbar = SnackBar(content: Text("${item}已移除"));
Scaffold.of(context).showSnackBar(snackbar);
},
background: Container(
alignment: Alignment.center,
child: Text("左滑刪除", style: TextStyle(color: Colors.white)),
color: Colors.red,
),
child: ListTile(title: Text(item))
)
雙擊退出效果
要想實現雙擊退出效果,必須把 WillPopScope 控件放在最外圍
import 'package:flutter/material.dart';
class TheWillPopScope extends StatelessWidget {
DateTime _lastQUitTime;
@override
Widget build(BuildContext context) {
return WillPopScope(
child: Scaffold(
body: Center(
child: Text("點擊退出按鈕,詢問是否退出"),
)
),
onWillPop: () async {
if(_lastQUitTime == null || DateTime.now().difference(_lastQUitTime).inSeconds >1){
_lastQUitTime = DateTime.now();
return false;
}else{
// 推出頁面
await Navigator.of(context).pop(true);
// 退出程序
// await SystemChannels.platform.invokeMethod('SystemNavigator.pop');
return true;
}
},
);
}
}
去掉頂部默認Padding
MediaQUery.removePadding(
removeTop: true
)
去掉TextField下划線
TextField(
decoration: InputDecoration(
border: InputBorder.none,
),
)
監聽滑動通知
NotificationListener(
onNotification: (scrollNotification){
if(scrollNotification is ScrollUpdateNotification){
...
}
},
child:
)
查看圖片
可以通過拖動以平移、縮放和拖放子組件
InteractiveViewer(
child: Image.asset('assets/images/go_board_09x09.png'),
)
左滑返回
return new MaterialApp(
home: new HomePage(),
theme: new ThemeData(platform: TargetPlatform.iOS),
);
退出應用
SystemChannels.platform.invokeMethod("SystemNavigator.pop");
子元素被父元素限制寬高
UnconstrainedBox{
constrainedAxis: Axis.vertical,
child: SizedBox(
width: width;
child: Dialog(),
),
}
封裝的評星
class StarRating extends StatelessWidget {
final double rating;
final double maxRating;
final Widget unselectedImage;
final Widget selectedImage;
final int count;
final double size;
final Color unselectedColor;
final Color selectedColor;
StarRating({
@required this.rating, // 當前評分
this.maxRating = 10, // 最高評分
Widget unselectedImage,
Widget selectedImage,
this.count = 5, // 星星的個數
this.size = 40,
this.unselectedColor = Colors.grey,
this.selectedColor = Colors.orange
}) : unselectedImage = unselectedImage ?? Icon(Icons.star, color: unselectedColor, size: size),
selectedImage = selectedImage ?? Icon(Icons.star, color: selectedColor, size: size);
@override
Widget build(BuildContext context) {
return Stack(
children: [
UnSelectStar(),
SelectedStar()
],
);
}
// 寬度 = 評分 / 每個星星代表的分數 * 星星的大小
// var width = ping / (total / count) * size;
Widget UnSelectStar() {
return Row(
mainAxisSize: MainAxisSize.min,
children: List.generate(count, (index) =>
unselectedImage
),
);
}
Widget SelectedStar() {
double width = rating / (maxRating / count) * size;
return ClipRect(
clipper: MyClipRect(width: width),
child: Row(
mainAxisSize: MainAxisSize.min,
children: List.generate(5, (index) =>
selectedImage
),
),
);
}
}
class MyClipRect extends CustomClipper<Rect>{
double width;
MyClipRect({this.width});
@override
getClip(Size size) {
return Rect.fromLTRB(0, 0, width, size.height);
}
@override
bool shouldReclip(MyClipRect oldClipper) {
return width != oldClipper;
}
}
SharedPreference封裝(非nullsafe)
import 'package:shared_preferences/shared_preferences.dart';
class DataCache {
static DataCache _insatnce = DataCache._();
factory DataCache() => _insatnce;
DataCache._();
static late SharedPreferences pre;
static Future<void> init() async {
if (pre == null) {
pre = await SharedPreferences.getInstance();
}
}
Future<bool> setString(String key, String value) {
return pre.setString(key, value);
}
Future<bool> setDouble(String key, double value) {
return pre.setDouble(key, value);
}
Future<bool> setInt(String key, int value) {
return pre.setInt(key, value);
}
Future<bool> setBool(String key, bool value) {
return pre.setBool(key, value);
}
Future<bool> setStringList(String key, List<String> value) {
return pre.setStringList(key, value);
}
getString(String key) {
var result = pre.get(key);
return result ?? false;
}
getDouble(String key) {
var result = pre.get(key);
return result ?? false;
}
getInt(String key) {
var result = pre.get(key);
return result ?? false;
}
getBool(String key) {
var result = pre.get(key);
return result ?? false;
}
getStringList(String key) {
var result = pre.get(key);
return result ?? false;
}
}
第三方包
assets_audio_player 音頻播放
animations 更多動畫
auto_route 路由管理
azlistview A-Z的選擇列表
badges 消息提示小紅點
barcode_widget 生成二維碼
bottom_sheet 第三方好用的BottomSheet
cached_network_image 網絡緩存圖片
camera 調用系統相機
carousel_slider 輪播圖
city_pickers 城市選擇器
collection 集合的樣式包含實用工具函數和類,以使處理集合更加容易。
color_thief_flutter 提取圖片顏色
cookie jar dio cookie manager依賴包
crypto 密碼加密
custom_nested_scroll_view 解決NestedScrollView無法實現下拉放大
device_info 獲取設備信息
device_preview 預覽程序
dio http請求庫
dio_cookie_manager Cookie管理
extended_image 強大的官方 Image 擴展組件, 支持加載以及失敗顯示,緩存網絡圖片,縮放拖拽圖片,圖片瀏覽(微信掘金效果),滑動退出頁面(微信掘金效果),編輯圖片(裁剪旋轉翻轉),保存,繪制自定義效果等功能
fluro 路由管理
flustars flustars依賴於Dart常用工具類庫common_utils,以及對其他第三方庫封裝,致力於為大家分享簡單易用工具類。如果你有好的工具類歡迎PR.目前包含SharedPreferences Util, Screen Util, Directory Util, Widget Util, Image Util
flutter_barcode_scanner 掃描二維碼
flutter_easyrefresh 下拉刷新
flutter_fai_webview 網頁加載插件
flutter_launcher_icons 生成icon
flutter_local_notifications 消息推送
flutter_native_splash 生成閃屏頁
flutter_neumorphic Neumorphic ui 新擬物
flutter_screenutil 屏幕適配
flutter_skeleton 骨架屏
flutter_sound 錄音、播放
flutter_staggered_animations 快速添加交互動畫
flutter_staggered_grid_view 強大的GridView,可實現瀑布流,單獨設置每行顯示的個數
flutter_swiper 輪播圖
flutter_toast Toast
font_awesome_flutter Font Awesome圖標庫
fullscreen 全屏、沉浸
geolocator 獲取GPS定位
get 高性能的狀態管理、智能的依賴注入和便捷的路由管理
glassmorphism 玻璃態
image_gallery_saver 保存圖片到本地相冊
image_picker 拍照
install_plugin 讓app擁有安裝軟件的功能
intl 提供國際化和本地化工具,包括消息翻譯、復數和性別、日期/數字格式和解析以及雙向文本
json_model JSON轉Model對象
keyboard dismisser 隱藏軟鍵盤
lottie 動畫庫
modal_bottom_sheet 第三方ModalBottomSheet
moor 數據庫操作庫
overlay_support 快速構建toast和通知
package_info App信息
palette_generator 獲取圖片的主色調
path 路徑
path_provider 獲取路徑
permission_handler 權限請求(ios權限請求只能拒絕1次)
proste_indexed_stack 懶加載的IndexStack
provider 靈活的到處處理和傳遞數據
pull_to_refresh 提供給flutter scroll組件的下拉刷新和上拉加載的小部件
share 分享組件
shared_preferences 簡單數據持久化,本地數據存儲,存儲鍵值集合
showcaseview 功能演示
sliding_up_panel 從下往上托的面板
sliver_tools Sliver組件的擴展工具
smooth_page_indicator 高級頁面指示器
snapping_sheet 多樣式的Sheet組件
sqlite 數據庫存儲
transparent_image 加載占位圖
url_launcher 運行網頁
webview 網頁