【Flutter】Flutter 切换语言 当前页面不刷新

news2024/11/29 6:39:02

文章目录

    • 一、前言
    • 二、Flutter 多语言支持的基础知识
    • 三、如何在 Flutter 中设置语言
    • 四、如何在 Flutter 中切换语言
    • 五、代码示例
    • 六、完整代码
    • 七、总结

一、前言

大家好,今天我们要探讨的主题是如何在 Flutter 中切换语言,而不需要刷新当前页面。这是一个在开发多语言支持的应用时经常会遇到的问题,特别是当我们想要在不影响用户体验的情况下实现语言切换时。

你可能会问,为什么 Flutter 会涉及到多语言的问题呢?这是因为 Flutter 是一个为全球用户服务的框架,它本身就支持多语言。为了满足全球用户的需求,我们的应用也需要能够支持多语言。所以,我们需要了解如何在 Flutter 中实现多语言支持,以及如何在切换语言时不刷新页面。

如果你想深入学习 Flutter,掌握更多的技巧和最佳实践,我有一个好消息要告诉你:我们有一个全面的 Flutter专栏->Flutter Developer 101 入门小册 等待着你。在那里,你将获得完整的、系统的 Flutter 学习资料,包括详细的代码示例和深入的概念解析。更重要的是,我们的专栏正在不断更新和完善,而价格也会随着内容的丰富而逐渐上调。所以,现在加入,你将以最优惠的价格获得所有的内容。现在,让我们开始今天的学习吧!

二、Flutter 多语言支持的基础知识

  1. Locale 类及其作用:在 Flutter 中,我们使用 Locale 类来表示一个语言环境,它包含了语言代码和国家代码。例如,Locale('en', 'US') 表示美国英语。

  2. Localizations 和 Delegate 的作用:Localizations 是 Flutter 中的一个 widget,它可以为其子 widget 提供本地化的字符串、布局方向等信息。Delegate 是用来生成 Localizations 的工厂。

  3. Flutter 的 LocalizationsDelegate:Flutter 提供了一些默认的 LocalizationsDelegate,例如 MaterialApp 就提供了 MaterialLocalizations.delegateWidgetsLocalizations.delegate。但是对于我们自定义的语言资源,我们需要自己实现 LocalizationsDelegate。

三、如何在 Flutter 中设置语言

  1. 如何定义语言资源:我们可以创建一个新的类来表示我们的语言资源,这个类需要包含所有我们需要的字符串。然后,我们需要为每一种语言创建一个这样的类的实例。

  2. 如何使用 Localizations 来获取语言资源:在我们的 widget 中,我们可以通过 Localizations.of<T>(context, T) 来获取语言资源,其中 T 是我们的语言资源类。

四、如何在 Flutter 中切换语言

  1. 使用 Locale 类来改变应用的语言:我们可以通过改变 MaterialApplocale 属性来改变应用的语言。例如,如果我们想要切换到美国英语,我们可以设置 localeLocale('en', 'US')

  2. 对于已经存在的页面如何进行语言切换而不刷新页面:使用 setState

下面是如何在不重新启动应用程序的情况下改变 Flutter 应用程序的语言的步骤:

  1. 在应用程序的主文件中,将默认的MyHomePage更改为StatefulWidget,例如在StatefulWidget中创建一个名为setLocalstatic方法:

    class MyHomePage extends StatefulWidget {
      MyHomePage({Key key}) : super(key: key);
    
      static void setLocale(BuildContext context, Locale newLocale) async {
        _MyHomePageState state = context.findAncestorStateOfType<_MyHomePageState>();
        state.changeLanguage(newLocale);
      }
    
      
      _MyHomePageState createState() => _MyHomePageState();
    }
    

    这里的_MyHomePageStateMyHomePage组件的state

  2. state中创建一个名为changeLanguagestatic方法:

    class _MyHomePageState extends State<MyHomePage> {
      Locale _locale;
    
      changeLanguage(Locale locale) {
        setState(() {
          _locale = locale;
        });
      }
    
      
      Widget build(BuildContext context) {
        return MaterialApp(
          debugShowCheckedModeBanner: false,
          title: 'Afghanistan',
          theme: ThemeData(primaryColor: Colors.blue[800]),
          supportedLocales: [
            Locale('fa', 'IR'),
            Locale('en', 'US'),
            Locale('ps', 'AFG'),
          ],
          locale: _locale,
          localizationsDelegates: [
            AppLocalizationsDelegate(),
            GlobalMaterialLocalizations.delegate,
            GlobalWidgetsLocalizations.delegate
          ],
          localeResolutionCallback: (locale, supportedLocales) {
            for (var supportedLocale in supportedLocales) {
              if (supportedLocale.languageCode == locale.languageCode &&
                  supportedLocale.countryCode == locale.countryCode) {
                return supportedLocale;
              }
            }
            return supportedLocales.first;
          },
          initialRoute: splashRoute,
          onGenerateRoute: Router.generatedRoute,
        );
      }
    }
    
  3. 现在,你可以通过调用setLocal方法并传递一个新的Locale来改变应用程序的语言:

    Locale newLocale = Locale('ps', 'AFG');
    MyHomePage.setLocale(context, newLocale);
    
  4. 请记住,你需要创建一个LocalizationDelegate

五、代码示例

现在,让我们通过一个具体的示例来看看如何在 Flutter 中切换语言而不刷新页面。我们将创建一个简单的应用,这个应用有两个页面,一个是主页面,另一个是设置页面。在设置页面,用户可以选择应用的语言。

首先,我们需要定义我们的语言资源。假设我们的应用需要支持英语和中文,我们可以创建一个新的类AppLocalizations来表示我们的语言资源:

class AppLocalizations {
  AppLocalizations(this.locale);

  final Locale locale;

  static AppLocalizations of(BuildContext context) {
    return Localizations.of<AppLocalizations>(context, AppLocalizations);
  }

  static Map<String, Map<String, String>> _localizedValues = {
    'en': {
      'title': 'Hello',
    },
    'zh': {
      'title': '你好',
    },
  };

  String get title {
    return _localizedValues[locale.languageCode]['title'];
  }
}

接下来,我们需要实现LocalizationsDelegate

class AppLocalizationsDelegate extends LocalizationsDelegate<AppLocalizations> {
  const AppLocalizationsDelegate();

  
  bool isSupported(Locale locale) {
    return ['en', 'zh'].contains(locale.languageCode);
  }

  
  Future<AppLocalizations> load(Locale locale) {
    return SynchronousFuture<AppLocalizations>(AppLocalizations(locale));
  }

  
  bool shouldReload(AppLocalizationsDelegate old) => false;
}

然后,我们可以创建我们的主页面和设置页面。在主页面,我们会显示一个标题和一个按钮,点击按钮会跳转到设置页面。在设置页面,我们会显示两个按钮,分别表示英语和中文,点击按钮会切换应用的语言。

class HomePage extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(AppLocalizations.of(context).title),
      ),
      body: Center(
        child: RaisedButton(
          child: Text('Settings'),
          onPressed: () {
            Navigator.push(context, MaterialPageRoute(builder: (context) => SettingsPage()));
          },
        ),
      ),
    );
  }
}

class SettingsPage extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Settings'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            RaisedButton(
              child: Text('English'),
              onPressed: () {
                MyApp.setLocale(context, Locale('en', 'US'));
              },
            ),
            RaisedButton(
              child: Text('中文'),
              onPressed: () {
                MyApp.setLocale(context, Locale('zh', 'CN'));
              },
            ),
          ],
        ),
      ),
    );
  }
}

最后,我们可以在MyApp中设置localelocalizationsDelegates

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

  static void setLocale(BuildContext context, Locale newLocale) {
    _MyAppState state = context.findAncestorStateOfType<_MyAppState>();
    state.changeLanguage(newLocale);
  }

  
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  Locale _locale;



  changeLanguage(Locale locale) {
    setState(() {
      _locale = locale;
    });
  }

  
  Widget build(BuildContext context) {
    return MaterialApp(
      locale: _locale,
      supportedLocales: [
        Locale('en', 'US'),
        Locale('zh', 'CN'),
      ],
      localizationsDelegates: [
        AppLocalizationsDelegate(),
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate,
      ],
      localeResolutionCallback: (locale, supportedLocales) {
        for (var supportedLocale in supportedLocales) {
          if (supportedLocale.languageCode == locale.languageCode &&
              supportedLocale.countryCode == locale.countryCode) {
            return supportedLocale;
          }
        }
        return supportedLocales.first;
      },
      home: HomePage(),
    );
  }
}

现在,当我们在设置页面选择一个新的语言时,MyApplocale将会被更新,但是应用不会重新启动,只有当前页面会被刷新。这是因为我们使用了StatefulWidgetsetState来保存和更新locale,而MaterialApp会监听locale的变化并更新界面。

六、完整代码

以下是我们刚才讨论的完整代码:

import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:flutter/foundation.dart';

void main() {
  runApp(MyApp());
}

class AppLocalizations {
  AppLocalizations(this.locale);

  final Locale locale;

  static AppLocalizations of(BuildContext context) {
    return Localizations.of<AppLocalizations>(context, AppLocalizations);
  }

  static Map<String, Map<String, String>> _localizedValues = {
    'en': {
      'title': 'Hello',
    },
    'zh': {
      'title': '你好',
    },
  };

  String get title {
    return _localizedValues[locale.languageCode]['title'];
  }
}

class AppLocalizationsDelegate extends LocalizationsDelegate<AppLocalizations> {
  const AppLocalizationsDelegate();

  
  bool isSupported(Locale locale) {
    return ['en', 'zh'].contains(locale.languageCode);
  }

  
  Future<AppLocalizations> load(Locale locale) {
    return SynchronousFuture<AppLocalizations>(AppLocalizations(locale));
  }

  
  bool shouldReload(AppLocalizationsDelegate old) => false;
}

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

  static void setLocale(BuildContext context, Locale newLocale) {
    _MyAppState state = context.findAncestorStateOfType<_MyAppState>();
    state.changeLanguage(newLocale);
  }

  
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  Locale _locale;

  changeLanguage(Locale locale) {
    setState(() {
      _locale = locale;
    });
  }

  
  Widget build(BuildContext context) {
    return MaterialApp(
      locale: _locale,
      supportedLocales: [
        Locale('en', 'US'),
        Locale('zh', 'CN'),
      ],
      localizationsDelegates: [
        AppLocalizationsDelegate(),
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate,
      ],
      localeResolutionCallback: (locale, supportedLocales) {
        for (var supportedLocale in supportedLocales) {
          if (supportedLocale.languageCode == locale.languageCode &&
              supportedLocale.countryCode == locale.countryCode) {
            return

            supportedLocale;
          }
        }
        return supportedLocales.first;
      },
      home: HomePage(),
    );
  }
}

class HomePage extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(AppLocalizations.of(context).title),
      ),
      body: Center(
        child: RaisedButton(
          child: Text('Settings'),
          onPressed: () {
            Navigator.push(context, MaterialPageRoute(builder: (context) => SettingsPage()));
          },
        ),
      ),
    );
  }
}

class SettingsPage extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Settings'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            RaisedButton(
              child: Text('English'),
              onPressed: () {
                MyApp.setLocale(context, Locale('en', 'US'));
              },
            ),
            RaisedButton(
              child: Text('中文'),
              onPressed: () {
                MyApp.setLocale(context, Locale('zh', 'CN'));
              },
            ),
          ],
        ),
      ),
    );
  }
}

七、总结

虽然 Flutter 默认的做法是刷新整个应用,但是我们可以通过使用 StatefulWidget 和 setState 来改变这一行为。

如果你对 Flutter 感兴趣,想要更深入地学习,那么我要推荐你一个很棒的资源:我们的 Flutter专栏->Flutter Developer 101 入门小册。在那里,你将获得完整的、系统的 Flutter 学习资料,包括详细的代码示例和深入的概念解析。比如,你知道如何使用 Flutter 构建一个完整的应用吗?在我们的专栏中,你将找到答案。更重要的是,我们的专栏正在不断更新和完善,而价格也会随着内容的丰富而逐渐上调。所以,现在加入,你将以最优惠的价格获得所有的内容。让我们一起在 Flutter 的世界中继续探索吧!如果你想了解更多,可以先阅读我们的 一站式解决你的需求,Flutter Developer 101 入门小册 专栏指引

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/646366.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

vue-element-admin - 最新完美解决项目是英文的问题,将英文变成中文的汉化处理详细教程(克隆完项目后不是中文的解决方法)

前言 网上的教程(并且都是好几年前的了)克隆运行后界面文字全都是英文的,如果您想要中文汉语版本请使用本文的方案。 本文 解决了克隆运行 vue-element-admin 项目后,默认是英文的问题!将语言设置为中文的详细教程! 官方文档说的很晦涩,您可以按照本教程步骤进行操作即…

log4j配置说明

目录&#xff1a; 1、 引入jar包使用 2、 使用 3、 配置文件 4、 配置 5、 说明 说明&#xff1a;2015年9月&#xff0c;Apache软件基金业宣布&#xff0c;Log4j不在维护&#xff0c;建议所有相关项目升级到Log4j2。 1.引入jar包使用 <dependency><groupI…

vscode 调试

目录 准备 GDB 调试方法 问题 准备 然后点击 文件-打开文件夹&#xff0c;找到创建的代码路径&#xff0c;确定后&#xff0c;在左侧的资源管理器可以看到代码文件。 第一次运行需要安装 c 的扩展&#xff0c;在扩展页面中&#xff0c;安装 C/C 编译注意一定要加上 -g 指令…

SpringBoot项目配置方式及优先级

说明&#xff1a;SpringBoot支持以下五种方式配置方式&#xff0c;例如将项目的Tomcat端口从8080&#xff0c;更改为9000&#xff0c;可以使用如下方式配置 【方式一】命令行参数 在启动窗口&#xff0c;鼠标右键&#xff0c;选择“Edit Configurations”&#xff0c;在弹出来…

开会糟透了?试试无声会议吧

引言 无声会议(Silent Meeting) 是一种已被成功实践但却鲜有公开资料的开会方法&#xff0c;本文会探寻下它的有趣历史&#xff0c;并介绍如何通过它的小小改变让会议变得不再糟糕。 文档是无声会议的核心基础&#xff0c;本文会引出 Coda 和 Mojidoc(妙记多) 这两款让你的会…

泛微数字化国有资产管理平台,以智能增效能

2021年国务院发布的《行政事业性国有资产管理条例》中要求应当建立健全行政事业性国有资产管理机制&#xff0c;加强对本级行政事业性国有资产的管理。 随着数字化转型的深入&#xff0c;越来越多的行政事业单位、国有企业运用数字化的理念、思路、方法&#xff0c;以智能增效…

AI工具助力创意与写作:19岁小伙每月赚3万,学会这些你也能轻松做到!

导语&#xff1a;在数字时代&#xff0c;人工智能为我们提供了许多创新的工具和资源&#xff0c;助力我们在各个领域实现创意和写作的目标。本文将介绍五款热门的AI工具&#xff1a;Copyai、Flikiai、Notion、TomeAl和Writesonic&#xff0c;它们分别在写作、视频配音、文本编辑…

Java调用Midjourney进行AI画图原生版抓包实现支持中文

用途介绍 Midjourney是一个目前优秀的AI画图工具&#xff0c;不挂梯无法直接访问 本代码主要用于搭建镜像站使用 适合人群 本代码不适合新手&#xff0c;建议使用过okhttp、且具有二开能力的同学使用~ 实现原理 通过调用发送信息接口发送请求&#xff0c;通过轮询房间消息…

【2023最全教程】Web自动化测试怎么做?Web自动化测试的详细流程和步骤

一、什么是web自动化测试 自动化&#xff08;Automation&#xff09;是指机器设备、系统或过程&#xff08;生产、管理过程&#xff09;在没有人或较少人的直接参与下&#xff0c;按照人的要求&#xff0c;经过自动检测、信息处理、分析判断、操纵控制&#xff0c;实现预期的目…

Spring @Autowired注入太坤肋了 我们自己写一个

1、 背景 众所周知该注解是Spring中用于依赖注入的注解&#xff0c;但是该注解只是简单根据类型的注入&#xff0c; 并且如果该类型存在多个实现类的情况下无法抉择具体哪一个实现类就会抛出错误&#xff0c;除非搭配Qualifier注解然后使用硬编码的方式去指定Bean的名字去抉择…

8年测试岗总结,软件测试常见面试题+答案,轻松避坑...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 1、介绍一下测试流…

JAVA开发与运维(怎么通过docker部署微服务jar包)

目标&#xff1a; 通过docker的方式部署微服务。 一、背景&#xff1a; 我们通过java开发的微服务可以打成jar包&#xff0c;我们可以直接通过裸机部署&#xff0c;也可以通过docker来部署&#xff0c;本文介绍通过docker来部署微服务。 二、首先我们介绍一下docker的发展过程…

Redis高级篇—分布式缓存 持久化 主从 哨兵 分片

分布式缓存 -- 基于Redis集群解决单机Redis存在的问题 单机的Redis存在四大问题&#xff1a; 0.学习目标 1.Redis持久化 Redis有两种持久化方案&#xff1a; RDB持久化 AOF持久化 1.1.RDB持久化 RDB全称Redis Database Backup file&#xff08;Redis数据备份文件&#xff09;&a…

jetBrian_工具的使用

文章目录 Intellij IDEA新建一个IDEA项目新建Project - ClassJDK相关设置out目录和编译版本 详细设置&#xff08;感觉有用的设置&#xff09;打开是否选择项目取消自动更新设置整体主题设置菜单和窗口字体和大小设置IDEA背景图设置编辑器主题样式注释的字体颜色代码智能提示功…

Java面试知识点(全)-分布式微服务-kafka面试知识点

Java面试知识点(全) 导航&#xff1a; https://nanxiang.blog.csdn.net/article/details/130640392 注&#xff1a;随时更新 以下是一些Kafka面试题和答案&#xff1a; 文章目录 什么是Kafka&#xff1f;Kafka主题(topic)和分区(partition)有什么作用&#xff1f;Kafka的重复数…

科一 容易忘,容易混的点(三)

年龄问题 考题&#xff1a; 申请大中型客货车驾驶证年龄不得超过 &#xff1f; 公交 、 中客、大货&#xff1a; 20 大客、重型牵引&#xff1a; 22岁 C1,C2,C5 : 18岁 C6不考倒车入库 记分转入下一周期 不会清零&#xff0c;必须前去接受处罚。不然下一周期你还是扣1…

echarts象形柱图实现电量效果柱状图

首先听到象柱形图pictorialBar&#xff0c;你会不会觉得很陌生&#xff1f; 然后&#xff0c;看看官网的示例&#xff0c;显示效果很抽象&#xff0c;觉得很不实用&#xff0c;真的有人会用到吗&#xff1f; 但是&#xff0c;我再让你看看下图&#xff0c;类似电量格效果的柱状…

访问 docker 容器的 tensorboard

demo代码示例 tensorboard --logdirlog_path :return:from torch.utils.tensorboard import SummaryWriterlogger SummaryWriter(log_dir./log/boardtest/)loss [5.5, 4.1, 4.2, 3.2, 3.3, 2.9, 2.5, 1.2, 0.8, 0.6] steps [1000, 2000, 3000, 4000, 5000, 6000, 7000, 8000…

Spark SQL数据源:JDBC

文章目录 一、Spark SQL读取关系数据库二、Spark SQL JDBC连接属性三、创建数据库与表&#xff08;一&#xff09;创建数据库&#xff08;二&#xff09;创建学生表&#xff08;二&#xff09;创建成绩表 四、读取和写入数据库表&#xff08;一&#xff09;利用dbtable属性读取…

APScheduler任务调度快速入门实践

什么是APScheduler APScheduler是一个用于任务调度和定时任务管理的Python库。它提供了一个简单而灵活的方式来定义、调度和执行任务。 APScheduler的架构由以下几个核心组件组成&#xff1a; 调度器&#xff08;Scheduler&#xff09;&#xff1a;调度器负责管理任务的调度和…