Flutter踩坑日记(持续更新…)

我自己踩的坑

设置组件为中文

刚开始去使用一些弹窗组件(例如时间选择器什么的),发现里面的确定和取消都是英文,就去百度了一下方法。

改配置文件

在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分钟一大卡,不好调试)。

插件

image_picker

开始

直接贴代码

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,

https://juejin.im/post/5ec4b1be518825432403efdb

「点点赞赏,手留余香」

    还没有人赞赏,快来当第一个赞赏的人吧!
0 条回复 A 作者 M 管理员
    所有的伟大,都源于一个勇敢的开始!
欢迎您,新朋友,感谢参与互动!欢迎您 {{author}},您在本站有{{commentsCount}}条评论