Flutter之图片选择器、支持多语言国际化、动画

一、Flutter之图片选择器

引入

  image_picker: ^0.8.4

mian.dart

import 'package:flutter/material.dart';

import 'package:images_flutter/pickerFn.dart';

void main() {
  runApp(MyApp());
}
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
      body: Container(
          child: Column(
        children: [
          PickerFn(),
        ],
      )),
    ),
    );
  }
}

pickerFn

import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'dart:io';

class PickerFn extends StatefulWidget {
  const PickerFn({Key key}) : super(key: key);

  @override
  _PickerFnState createState() => _PickerFnState();
}

class _PickerFnState extends State<PickerFn> {
  //实例化选择图片
  final ImagePicker picker = new ImagePicker();
//用户本地图片
  File _userImage; //存放获取到的本地路径
  @override
  Widget build(BuildContext context) {
    return Container(
      child: Column(
        children: [
          FlatButton(
            child: Text("1"),
            onPressed: () {
              selectImag();
            },
          ),
          Container(
            child: _userImage == null ? Text("data") : Image.file(_userImage),
          )
        ],
      ),
    );
  }

  //从图库选择单张图片
  Future selectImag() async {
    final onceimages = await picker.getImage(source: ImageSource.gallery);
    if (onceimages != null) {
      _userImage = File(onceimages.path);
    }
  }

  //照相机拍摄方法
  Future _getCameraImage() async {
    final cameralImages = await picker.getImage(source: ImageSource.camera);
    if (mounted) {
      setState(() {
        //拍摄照片不为空
        if (cameralImages != null) {
          _userImage = File(cameralImages.path);
        }
      });
    }
  }
}
  double? maxWidth:用来指定选择图片的最大宽度,若图片超过该宽度,将等比例缩小图片再返回,默认返回原始图片
  double? maxHeight:用来指定选择图片的最大高度,若图片超过该高度,将等比例缩小图片再返回,默认返回原始图片
  int? imageQuality:用来修改图片返回的质量,取值再0-100,越大返回图片的质量越高,默认为100,即原始图片
二、Flutter之国际化语言

Flutter之图片选择器、支持多语言国际化、动画_第1张图片

Flutter国际化语言就是根据不同国家使用者的不同语言版本,设置本地化的一些值,如文本布局。
2:Flutter SDK 默认支持美国英语本地化资源(主要是文本),其他语言需要添加包依赖 flutter_localizations。
3:指定MaterialApp的 localizationsDelegates和 supportedLocales。

dependencies:
  flutter:
    sdk: flutter
  flutter_localizations:
    sdk: flutter

import 'package:flutter_localizations/flutter_localizations.dart';
new MaterialApp(
 localizationsDelegates: [
   // 本地化的代理类
   GlobalMaterialLocalizations.delegate, //PS: 基于WidgetsApp类为入口的应用程序进行国际化时, 不需要这个
   GlobalWidgetsLocalizations.delegate,// 定义组件默认的文本方向,从左到右或从右到左.
   GlobalCupertinoLocalizations.delegate,
 ],
 supportedLocales: [ // 当前应用支持的locale列表
    const Locale('en', 'US'), // 美国英语
    const Locale('zh', 'CN'), // 中文简体
    //其它Locales
  ],
  // ...
)

三、动画初识

动画

import 'package:flutter/material.dart';
class AnimationDemo extends StatefulWidget {
  @override
  _AnimationDemoState createState() => _AnimationDemoState();
}

class _AnimationDemoState extends State<AnimationDemo> with SingleTickerProviderStateMixin{
  AnimationController _AnimationController;
  @override
  void initState(){
    super.initState();
    _AnimationController = AnimationController(vsync: this,duration:Duration(microseconds: 300));
  _AnimationController.addListener(() {
    setState(() {
      _size = 100 + 100*_AnimationController.value;
    });
  });
  }
  var _size = 100.0;
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        centerTitle: true,
        title: Text("动画练习"),
      ),
      body: GestureDetector(
       onTap:(){
         _AnimationController.forward();
       },
        child:Container(
          width: _size,
          height: _size,
          color: Colors.blue,
        )
      ),
    );
  }
}

动画的状态分为四种:

dismissed:动画停止在开始处。
forward:动画正在从开始处运行到结束处(正向运行)。
reverse:动画正在从结束处运行到开始处(反向运行)。
completed:动画停止在结束处

再来看下动画的控制方法:

forward:正向执行动画。
reverse:反向执行动画。
repeat:反复执行动画。
reset:重置动画
import 'package:flutter/material.dart';
class AnimationDemo extends StatefulWidget {
  @override
  _AnimationDemoState createState() => _AnimationDemoState();
}

class _AnimationDemoState extends State<AnimationDemo> with SingleTickerProviderStateMixin{
  AnimationController _AnimationController;
  @override
  void initState(){
    super.initState();
    _AnimationController = AnimationController(vsync: this,duration:Duration(microseconds: 300),lowerBound: 100,upperBound: 200);
  _AnimationController.addListener(() {
    setState(() {
      _size =  _AnimationController.value;
    });
  });
  _AnimationController.addStatusListener((status) {
    //如果监听到状态监听到动画已经结束
    if(status == AnimationStatus.completed){
      _AnimationController.reverse();
    }
    else if(status==AnimationStatus.dismissed){
      _AnimationController.forward();
    }
  });
  }
  var _size = 100.0;
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        centerTitle: true,
        title: Text("动画练习"),
      ),
      body: GestureDetector(
       onTap:(){
         _AnimationController.forward();
       },
        child:Container(
          width: _size,
          height: _size,
          color: Colors.blue,
        )
      ),
    );
  }
}
二、监听堆栈路由变化

监听路由堆栈的变化使用 RouteObserver ,首先在 MaterialApp 组件中添加 navigatorObservers:

void main() {
  runApp(MyApp());
}
RouteObserver<PageRoute> routeObserver = RouteObserver<PageRoute>();

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      ...
      navigatorObservers: [routeObserver],
      home: HomePage(),
    );
  }
}

应用场景

class ARouteObserverDemo extends StatefulWidget {
  @override
  _RouteObserverDemoState createState() => _RouteObserverDemoState();
}

class _RouteObserverDemoState extends State<ARouteObserverDemo> with RouteAware {

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    routeObserver.subscribe(this, ModalRoute.of(context));
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Container(
        alignment: Alignment.center,
        child: RaisedButton(
          child: Text('A RouteObserver'),
          onPressed: () {
            Navigator.of(context).pushNamed('/BRouteObserver');
          },
        ),
      ),
    );
  }

  @override
  void dispose() {
    super.dispose();
    routeObserver.unsubscribe(this);
  }

  @override
  void didPush() {
    final route = ModalRoute.of(context).settings.name;
    print('A-didPush route: $route');
  }

  @override
  void didPopNext() {
    final route = ModalRoute.of(context).settings.name;
    print('A-didPopNext route: $route');
  }

  @override
  void didPushNext() {
    final route = ModalRoute.of(context).settings.name;
    print('A-didPushNext route: $route');
  }

  @override
  void didPop() {
    final route = ModalRoute.of(context).settings.name;
    print('A-didPop route: $route');
  }

}

其中 didPush、didPushNext、didPopNext、didPop 为路由堆栈变化的回调。如果想对整个程序进行堆栈监听应该怎么办呢?一种方法是写一个监听路由堆栈的基类,所有页面继承此基类。还有一种方法是自定义 RouteObserver,继承RouteObserver并重写其中的方法:

import 'package:flutter/material.dart';
import 'package:item_1/router/AppRouteManager.dart';
import 'package:item_1/tabs/indexPage.dart';
import 'package:item_1/widget/MyRouteObserver.dart';

main() => runApp(MyApp());
MyRouteObserver<PageRoute> myRouteObserver = MyRouteObserver<PageRoute>();
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      onGenerateRoute: AppRouteManager.getInstance().onGenerateRoute,
      navigatorObservers: [myRouteObserver],
      home: IndexPage(),
    );
  }
}
import 'package:flutter/material.dart';
class MyRouteObserver<R extends Route<dynamic>> extends RouteObserver<R> {
  @override
  void didPush(Route route, Route previousRoute) {
    super.didPush(route, previousRoute);
    print('didPush route: $route,previousRoute:$previousRoute');
  }

  @override
  void didPop(Route route, Route previousRoute) {
    super.didPop(route, previousRoute);
    print('didPop route: $route,previousRoute:$previousRoute');
  }

  @override
  void didReplace({Route newRoute, Route oldRoute}) {
    super.didReplace(newRoute: newRoute, oldRoute: oldRoute);
    print('didReplace newRoute: $newRoute,oldRoute:$oldRoute');
  }

  @override
  void didRemove(Route route, Route previousRoute) {
    super.didRemove(route, previousRoute);
    print('didRemove route: $route,previousRoute:$previousRoute');
  }

  @override
  void didStartUserGesture(Route route, Route previousRoute) {
    super.didStartUserGesture(route, previousRoute);
    print('didStartUserGesture route: $route,previousRoute:$previousRoute');
  }

  @override
  void didStopUserGesture() {
    super.didStopUserGesture();
    print('didStopUserGesture');
  }
}

拦截返回事件

WillPopScope

import 'package:flutter/material.dart';
import 'package:navigatoritem/page/B.dart';

class A extends StatefulWidget {
  
  const A({Key key}) : super(key: key);

  @override
  _AState createState() => _AState();
}

class _AState extends State<A> {

  @override
  Widget build(BuildContext context) {
    return WillPopScope(
      onWillPop: () async => showDialog(
        context: context,
        builder: (context)=>AlertDialog(title: Text("您确定要退出吗"),actions: [
          RaisedButton(
            child: Text("退出"),
            onPressed: ()=>Navigator.of(context).pop(true),
          ),
          RaisedButton(
            child: Text("取消"),
            onPressed: (){
              Navigator.of(context).pop(false);
            },
          )
        ],)
      ),
      child: Scaffold(
      body: Container(
        child: Column(
          children: [

          ],
        ),
      ),
    )
    );
  }
}

知识点1:
跨组件对象

.of(context)使用时间必须在didChangeDependencies之后

知识点2:
时间函数

var d1 = new DateTime(2022, 10, 1);
var d2 = new DateTime(2022, 10, 10);
var difference = d1.difference(d2);
print([difference.inDays, difference.inHours]);
//相差的天数和小时
import 'package:flutter/material.dart';
import 'package:navigatoritem/page/B.dart';

class A extends StatefulWidget {
  
  const A({Key key}) : super(key: key);

  @override
  _AState createState() => _AState();
}

class _AState extends State<A> {
DateTime _lastQuitTime;
  @override
  Widget build(BuildContext context) {
    return WillPopScope(
      onWillPop: () async {
     if(_lastQuitTime==null || DateTime.now().difference(_lastQuitTime).inSeconds>1){
       Scaffold.of(context).showSnackBar(SnackBar(
         content: Text("再按一次退出"),
       ));
       _lastQuitTime = DateTime.now();
       return false;
     }else{
          Navigator.of(context).pop(true);
        return true;
     }
      },
      child: Scaffold(
      body: Container(
        child: Column(
          children: [

          ],
        ),
      ),
    )
    );
  }
}

Flutter之图片选择器、支持多语言国际化、动画_第2张图片

为什么要用数据模型:

dart的map类型使用它里面的数据只能通过一个方法就是data[‘data’]来使用‘非常麻烦 且没有代码自动补充提示,而且网络请求数据很多大部分的构造都是list和map,要是用那种中括号加key的方式来做就很浪费时间 。然后数据类型就是将这个一个map的所有key作为类的参数形式存在,这样通过一个构造函数一次性赋值就可以用类对象来代替这个数据模型是有两个构造函数一个是正常的第一个红方框那样叫默认构造方法就是正常的传参赋值第二个构造方法叫做命名构造函数就是命个名告诉你这个函数你要怎么来构造fromjson的意思就是来自json也一般就是经过json处理后的网络请求返回数据它就是将里面的参数挨个对应构造赋值给类对象的参数所以这个类对象的参数要与json对应的value类型一致tojson就是将类的所有参数放到一个map里这样方便你打印观察数据内容

你可能感兴趣的:(Flutter移动开发,flutter,android,ios)