Flutterの使用Provider進行簡單的國際化

_驍_應屆畢業生求職發表於2019-12-19
provider: ^3.1.0
shared_preferences: ^0.5.2
複製程式碼

參考: www.imooc.com/article/293…

Flutterの使用Provider進行簡單的國際化

Main.js

頂端註冊provider,初始化

主要程式碼

  Widget build(BuildContext context) {
  //獲取本地語言(我這裡是zh_CN)
    String locale=WidgetsBinding.instance.window.locale.toString();
    print('loacle:'+locale);
    //本地儲存SharedPreferences.get
    String value = LocalStorage.get('language'); //獲取本地儲存
    String language;
    if (value == null) {
      if (locale == 'zh_CN' || locale == 'zh_TW' || locale == 'zh_HK') {
        language = 'Chinese';
      } else
        language = "English";
    } else
      language = value; //有就改
    return MultiProvider(//註冊provider
      providers: [
        ChangeNotifierProvider(builder: (_) => LanguageModel(language)),
        //在這提供provider
      ],
      child: child, //孩子
    );
  }
複製程式碼

主要思想:

if 有沒有用SharedPreferences preferences儲存
    用本地存的
else
    看系統語言設定
    if 是中國
      用中文
    else
        英文
複製程式碼

全程式碼:

import 'package:flutter/material.dart';
import 'package:jieda/Page/A_login/LoginPage.dart';
import 'package:jieda/common/CommonInsert.dart';


void main() => realRunApp();

void realRunApp() async {
  WidgetsFlutterBinding.ensureInitialized();
  //將LocalStorage 非同步轉為同步
  bool success = await LocalStorage.getInstance();
  ///初始化螢幕介面卡
  Adapt.init();
  assert(success);
  LocalImageSelecter.init();
//  runApp(ChangeNotifierProvider.value(
////    value: LanguageModel(),
////    child:
////    MyApp(),
////  ),);這種也行,不過要有帶build的class才能執行方法
  runApp(Wrapper(child:MyApp()));
}

class Wrapper extends StatelessWidget {
  final Widget child;
  Wrapper({this.child});
  @override
  Widget build(BuildContext context) {
  //獲取本地語言(我這裡是zh_CN)
    String locale=WidgetsBinding.instance.window.locale.toString();
    print('loacle:'+locale);
    //本地儲存SharedPreferences.get
    String value = LocalStorage.get('language'); //獲取本地儲存
    String language;
    if (value == null) {
      if (locale == 'zh_CN' || locale == 'zh_TW' || locale == 'zh_HK') {
        language = 'Chinese';
      } else
        language = "English";
    } else
      language = value; //有就改
    return MultiProvider(//註冊provider
      providers: [
        ChangeNotifierProvider(builder: (_) => LanguageModel(language)),
        //在這提供provider
      ],
      child: child, //孩子
    );
  }
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: '用provider進行國際化',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: LoginPage(),//登入頁
    );
  }
}
複製程式碼

Language.dart

import 'package:flutter/material.dart';
import 'package:jieda/common/local/LocalStorage.dart';
class LanguageModel with ChangeNotifier {
  String _language = "Chinese";

//獲取當前語言
  String get value => _language;
  LanguageModel(this._language);
  void initValue(){//無用,不如建構函式啊
    String getvalue=LocalStorage.get('language');
    if(getvalue!=null) setLanguage(getvalue);
  }

  //切換語言
  void switchLanguage() {
    if(_language=="Chinese") {
      _language = "English";
      LocalStorage.save('language','English');
    }
    else if(_language=="English") {
      _language="Chinese";
      LocalStorage.save('language','Chinese');
    }
    notifyListeners();
  }

  //設定語言,加這個是怕以後不只兩個語言
  void setLanguage(value) {
      _language = value;
      LocalStorage.save('language',value);
    notifyListeners();
  }

  Map get test => contains[_language];

  Map<String, Map<String, String>> contains={
    'Chinese': {
      'modifyPasswordtitle': '驗證原密碼',
      'welecome':"歡迎回來,請登入",
         },
     'English': {
      'modifyPasswordtitle': 'Verify the original password',
      'welecome': "Welecome back,please log in",
      'phone': "Phone",
      }
  };
複製程式碼

在該用的頁面的引用

class Setting extends StatefulWidget {
  @override
  _SettingState createState() => _SettingState();
}

class _SettingState extends State<Setting> {
  var test;
  @override
  Widget build(BuildContext context) {
    test = Provider.of<LanguageModel>(context).test;//獲取文字
    return Scaffold(
      resizeToAvoidBottomInset: false,
      backgroundColor: MyColors.bg,
      appBar: MyAppBar(title: test['modifyPasswordtitle'],),//直接用
複製程式碼

切換語言的頁面程式碼

import 'package:jieda/common/CommonInsert.dart';
class SelectLanguage extends StatefulWidget {
  @override
  _SelectLanguageState createState() => _SelectLanguageState();
}

class _SelectLanguageState extends State<SelectLanguage> {
  @override
  Widget build(BuildContext context) {
    String _language = Provider.of<LanguageModel>(context).value;
    Map test = Provider.of<LanguageModel>(context).test;//兩種寫法供君選擇
    String english=_language=="English"?'English':"英文";
    String chinese=_language=="English"?'Chinese':"中文";
    String title=_language=="English"?'Switch Language':"切換語言";

    return Scaffold(
      backgroundColor: MyColors.bg,
      appBar: MyAppBar(
        title:title,
      ),
      body: Column(
        children: <Widget>[
          SizedBox(height: Adapt.dp(10),),
          Consumer<LanguageModel>(
            builder: (context, LanguageModel language, child) =>GestureDetector(  behavior: HitTestBehavior.translucent,onTap: _language!="English"?(){language.setLanguage('English');}:null,
              child: child,),
            child: Container(height: Adapt.dp(50),color: Colors.white,padding: EdgeInsets.only(left: 16,right: 13),
              child: Row(mainAxisAlignment: MainAxisAlignment.spaceBetween,
                children: <Widget>[
                  Text(english,style: TextStyle(fontSize: 12),),Icon(_language=="English"?Icons.check_circle:Icons.panorama_fish_eye,color: _language=="English"?MyColors.ls:Colors.black26,)
                ],),),
          ),
          SizedBox(height:1 ,),
          Consumer<LanguageModel>(
            builder: (context, LanguageModel language, child) =>GestureDetector(  behavior: HitTestBehavior.translucent,onTap: _language=="English"?language.switchLanguage:null,
              child: child,),
            child: Container(height: Adapt.dp(50),color: Colors.white,padding: EdgeInsets.only(left: 16,right: 13),
              child: Row(mainAxisAlignment: MainAxisAlignment.spaceBetween,
                children: <Widget>[
                  Text(chinese,style: TextStyle(fontSize: 12),),Icon(_language!="English"?Icons.check_circle:Icons.panorama_fish_eye,color: _language!="English"?MyColors.ls:Colors.black26,)
                ],),),
          ),
        ],
      ),
    );
  }
}

複製程式碼

後記:

我研究了一下

flutter_localizations
複製程式碼

好像有bug,

這個外掛也是provider寫的呀,那我直接用Provider,應該也可以。

參考:

flutter_localizations: book.flutterchina.club/chapter15/e…

init18好像不錯

犯過的錯:

之前在Main中是沒搞這個Warapper的

嘗試

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
   Provider.of<LanguageModel>(context).initValue();
      //報錯,說是有方法during SetState。。
    return MaterialApp(
      title: '捷達智慧電器',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: LoginPage(),
    );
  }
}
複製程式碼

相關文章