我自己踩的坑
設定元件為中文
剛開始去使用一些彈窗元件(例如時間選擇器什麼的),發現裡面的確定和取消都是英文,就去百度了一下方法。
改配置檔案
在pubspec.yaml檔案的對應位置加上
flutter_localizations:
sdk: flutter
複製程式碼
修改主入口
在主入口函式新增(這裡還需要引入package:flutter_localizations/flutter_localizations.dart)
import 'package:flutter_localizations/flutter_localizations.dart';
複製程式碼
//設定元件為中文
localizationsDelegates: [
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
],
supportedLocales: [
//此處
const Locale('zh', 'CH'),
const Locale('en', 'US'),
],
locale: Locale('zh'),
複製程式碼
圖片上傳
這個坑,花了我整整一天的時間(其實就是電腦卡,10分鐘一小卡,30分鐘一大卡,不好除錯)。
外掛
開始
直接貼程式碼
import 'dart:collection';
import 'dart:io';
import 'package:dio/dio.dart';
import 'package:image_picker/image_picker.dart';
import 'package:flutter/material.dart';
import '../../base/Http.dart';//這個是自己封裝後的http
import 'package:http_parser/http_parser.dart';
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
File _image;
//照相
Future getImage() async {
var image = await ImagePicker.pickImage(source: ImageSource.camera);
setState(() {
uploadImgFunc(image);
_image = image;
});
}
//從相機選擇
Future openGallery() async {
var image = await ImagePicker.pickImage(source: ImageSource.gallery);
setState(() {
uploadImgFunc(image);
_image = image;
});
}
uploadImgFunc(File image) async {
String path = image.path;//檔案路徑
String name = path.substring(path.lastIndexOf("/") + 1, path.length);//檔名
String suffix = name.substring(name.lastIndexOf(".") + 1, name.length);//檔案字尾
FormData formData = FormData.fromMap({
"uploadFile":await MultipartFile.fromFile(
path,
filename: name,
contentType:MediaType('image',suffix)//contentType這個引數看情況,下面會講到
),
});
Dio dio = new Dio();
var result = await dio.post<String>("介面", data: formData);
print(result);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Image Picker Example'),
),
body: Center(
child: _image == null ? Text('No image selected.') : Image.file(_image),
),
floatingActionButton: FloatingActionButton(
onPressed: getImage,
tooltip: 'Pick Image',
child: Icon(Icons.add_a_photo),
),
);
}
}
複製程式碼
上面就是一個例子了,現在開始講解。
首先,我們需要引入image_picker這個包,在pubspec.yaml檔案裡面新增對應項
然後在對應檔案引入import 'dart:io';//io操作
import 'package:dio/dio.dart';
import 'package:image_picker/image_picker.dart';
複製程式碼
寫呼叫方法(這裡以拍照為例)
Future getImage() async {
var image = await ImagePicker.pickImage(source: ImageSource.camera);//這裡用到了對應外掛
setState(() {
uploadImgFunc(image);
_image = image;//_image需要在外層定義
});
}
複製程式碼
寫上傳方法(重點)
uploadImgFunc(File image) async {
String path = image.path;
String name = path.substring(path.lastIndexOf("/") + 1, path.length);
String suffix = name.substring(name.lastIndexOf(".") + 1, name.length);
FormData formData = FormData.fromMap({
"uploadFile":await MultipartFile.fromFile(//這裡記得加await
path,
filename: name,
contentType:MediaType('image',suffix)
),
});
Dio dio = new Dio();
var result = await dio.post<String>('介面', data: formData);
print(result);
}
複製程式碼
dio3.0之後就使用MultipartFile不再使用UploadFileInfo。
MediaType這個需要額外引一個標頭檔案,不然會報錯
import 'package:http_parser/http_parser.dart';
複製程式碼
假如,你們的後端是可以用二進位制的方法來上傳的話,
contentType:MediaType('image',suffix)
複製程式碼
上面那一行可以去掉,不然的話一定要加上,不然後端如果是判斷檔案型別的話可能就過不了。我就是因為這個卡了很久......
ios真機除錯的時候用相機(我同事說的)好像會閃退,因為我沒有mac系統,也沒錢,這裡找個了文章。大家看看吧。
官網文件好像也有說,之前沒看仔細。需要在配置檔案裡面加東西
獲取元素位置
現在,我要獲取某個元素的位置,然後按照位置來定義一個彈窗(showMenu)的位置,例如下圖
定義一個key
GlobalKey positionKey = GlobalKey();
複製程式碼
在需要定位的元素上使用
Text(
'其他',
key: positionKey,
textAlign: TextAlign.center,
style: TextStyle(
height: 2.5,
color: Color.fromRGBO(255, 106, 0, 1),
fontSize: ScreenAdaper.size(30),
)
複製程式碼
使用key來獲取位置
在函式內去獲取
RenderBox renderBox =
positionKey.currentContext.findRenderObject();
var offset = renderBox.localToGlobal(Offset.zero);
print(offset.dx)//橫座標
print(offset.dx)//縱座標
複製程式碼
ios數字軟鍵盤沒有'完成'按鈕
當我們把輸入框(TextField)的型別(keyboardType)設定number時,Android和ios就會彈出數字鍵盤而不是英文鍵盤,但是ios數字軟鍵盤是沒有所謂的完成按鈕(就是點選後軟鍵盤會收回去)。這時候,我們就需要用到一個外掛了
keyboard_actions
這是一個可以解決上面問題的外掛,如何引入同上面提過的。
使用
在需要用到的元件內先定義一個基礎設定,這裡的actions裡面KeyboardAction有很多設定,推薦去看一下官方文件
KeyboardActionsConfig _buildConfig(BuildContext context) {
return KeyboardActionsConfig(
keyboardActionsPlatform: KeyboardActionsPlatform.ALL,
keyboardBarColor: Colors.grey[200],
nextFocus: true,
actions: [
KeyboardAction(
focusNode: _nodeNumberNode,//下面會提到
toolbarButtons: [
(node) {
return GestureDetector(
onTap: () => node.unfocus(),
child: Container(
padding: EdgeInsets.fromLTRB(8, 8, 16, 8),
child: Text(
"完成",
style: TextStyle(color: Colors.black),
),
),
);
},
],
),
],
);
}
複製程式碼
然後,我們需要定義一個FocusNode來對應設定和輸入框
final FocusNode _nodeNumberNode = FocusNode();
複製程式碼
輸入框設定,需要包一層KeyboardActions
KeyboardActions(
config: _buildConfig(context),//上面定義的那個基礎設定
chlid:Container(
child:TextField(
focusNode: _nodeNumberNode,
keyboardType: TextInputType.number,
textInputAction: TextInputAction.done,
decoration: InputDecoration(
hintText: '請輸入',
border: InputBorder.none,
),
autofocus: false,
onChanged: (value) {
setState(() {
//賦值操作
});
},
)
)
)
複製程式碼
這樣就可以了,不過有個要注意的點,然後你的輸入框是放在ListView裡面的話,需要給ListView加一個屬性
shrinkWrap: false,
複製程式碼