flutter 自定义本地化-GlobalMaterialLocalizations(重写本地化日期转换)

1. 创建自定义 GlobalMaterialLocalizations

import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:kittlenapp/utils/base/date_time_util.dart';

///[auth] kittlen
///[createTime] 2024-05-31 11:40
///[description]

class MyMaterialLocalizationZh extends MaterialLocalizationZh {
  MyMaterialLocalizationZh(
      {super.localeName = 'my_local', ///自定义本地化名
      required super.fullYearFormat,
      required super.compactDateFormat,
      required super.shortDateFormat,
      required super.mediumDateFormat,
      required super.longDateFormat,
      required super.yearMonthFormat,
      required super.shortMonthDayFormat,
      required super.decimalFormat,
      required super.twoDigitZeroPaddedFormat});

  ///以下方法为对zh本地化的重写
  
  String formatCompactDate(DateTime date) {
    // Assumes yyyy-mm-dd
    return DateTimeUtil.formatDate(date);
  }

  
  DateTime? parseCompactDate(String? inputString) {
    if (inputString == null) {
      return null;
    }

    // Assumes yyyy-mm-dd
    final List<String> inputParts = inputString.split('-');
    if (inputParts.length != 3) {
      return null;
    }

    final int? year = int.tryParse(inputParts[0], radix: 10);
    if (year == null || year < 1) {
      return null;
    }

    final int? month = int.tryParse(inputParts[1], radix: 10);
    if (month == null || month < 1 || month > 12) {
      return null;
    }

    final int? day = int.tryParse(inputParts[2], radix: 10);
    if (day == null || day < 1 || day > _getDaysInMonth(year, month)) {
      return null;
    }
    return DateTime(year, month, day);
  }

  int _getDaysInMonth(int year, int month) {
    if (month == DateTime.february) {
      final bool isLeapYear = (year % 4 == 0) && (year % 100 != 0) || (year % 400 == 0);
      if (isLeapYear) {
        return 29;
      }
      return 28;
    }
    const List<int> daysInMonth = <int>[31, -1, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
    return daysInMonth[month - 1];
  }
}

2.创建对应的LocalizationsDelegate管理本地配置

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart' as intl;

import 'package:flutter_localizations/src/l10n/generated_material_localizations.dart';
import 'package:flutter_localizations/src/utils/date_localizations.dart' as util;
import 'package:kittlenapp/localzations/my_material_localization_zh.dart';

///[auth] kittlen
///[createTime] 2024-05-31 12:13
///[description]

class MyLocalizationsDelegate extends LocalizationsDelegate<MaterialLocalizations> {
  static const LocalizationsDelegate<MaterialLocalizations> delegate = MyLocalizationsDelegate();

  const MyLocalizationsDelegate();
  
 ///自定义本地化名,GlobalMaterialLocalizations中定义的的localeName
  
  bool isSupported(Locale locale) => locale.languageCode == 'my_local';

  static Future<MaterialLocalizations>? _loadedTranslations;

  
  Future<MaterialLocalizations> load(Locale locale) {
    assert(isSupported(locale));
    if (_loadedTranslations != null) {
      return _loadedTranslations!;
    }
    util.loadDateIntlDataIfNotLoaded();
    Locale baseLocal = Locale('zh', 'CH'); ///重写zh的配置
    final String localeName = intl.Intl.canonicalizedLocale(baseLocal.toString());
    assert(
      baseLocal.toString() == localeName,
      'Flutter does not support the non-standard locale form $baseLocal (which '
      'might be $localeName',
    );

    intl.DateFormat fullYearFormat;
    intl.DateFormat compactDateFormat;
    intl.DateFormat shortDateFormat;
    intl.DateFormat mediumDateFormat;
    intl.DateFormat longDateFormat;
    intl.DateFormat yearMonthFormat;
    intl.DateFormat shortMonthDayFormat;
    if (intl.DateFormat.localeExists(localeName)) {
      fullYearFormat = intl.DateFormat.y(localeName);
      compactDateFormat = intl.DateFormat.yMd(localeName);
      shortDateFormat = intl.DateFormat.yMMMd(localeName);
      mediumDateFormat = intl.DateFormat.MMMEd(localeName);
      longDateFormat = intl.DateFormat.yMMMMEEEEd(localeName);
      yearMonthFormat = intl.DateFormat.yMMMM(localeName);
      shortMonthDayFormat = intl.DateFormat.MMMd(localeName);
    } else if (intl.DateFormat.localeExists(baseLocal.languageCode)) {
      fullYearFormat = intl.DateFormat.y(baseLocal.languageCode);
      compactDateFormat = intl.DateFormat.yMd(baseLocal.languageCode);
      shortDateFormat = intl.DateFormat.yMMMd(baseLocal.languageCode);
      mediumDateFormat = intl.DateFormat.MMMEd(baseLocal.languageCode);
      longDateFormat = intl.DateFormat.yMMMMEEEEd(baseLocal.languageCode);
      yearMonthFormat = intl.DateFormat.yMMMM(baseLocal.languageCode);
      shortMonthDayFormat = intl.DateFormat.MMMd(baseLocal.languageCode);
    } else {
      fullYearFormat = intl.DateFormat.y();
      compactDateFormat = intl.DateFormat.yMd();
      shortDateFormat = intl.DateFormat.yMMMd();
      mediumDateFormat = intl.DateFormat.MMMEd();
      longDateFormat = intl.DateFormat.yMMMMEEEEd();
      yearMonthFormat = intl.DateFormat.yMMMM();
      shortMonthDayFormat = intl.DateFormat.MMMd();
    }

    intl.NumberFormat decimalFormat;
    intl.NumberFormat twoDigitZeroPaddedFormat;
    if (intl.NumberFormat.localeExists(localeName)) {
      decimalFormat = intl.NumberFormat.decimalPattern(localeName);
      twoDigitZeroPaddedFormat = intl.NumberFormat('00', localeName);
    } else if (intl.NumberFormat.localeExists(locale.languageCode)) {
      decimalFormat = intl.NumberFormat.decimalPattern(locale.languageCode);
      twoDigitZeroPaddedFormat = intl.NumberFormat('00', locale.languageCode);
    } else {
      decimalFormat = intl.NumberFormat.decimalPattern();
      twoDigitZeroPaddedFormat = intl.NumberFormat('00');
    }
    _loadedTranslations = SynchronousFuture(MyMaterialLocalizationZh(
        fullYearFormat: fullYearFormat,
        compactDateFormat: compactDateFormat,
        shortDateFormat: shortDateFormat,
        mediumDateFormat: mediumDateFormat,
        longDateFormat: longDateFormat,
        yearMonthFormat: yearMonthFormat,
        shortMonthDayFormat: shortMonthDayFormat,
        decimalFormat: decimalFormat,
        twoDigitZeroPaddedFormat: twoDigitZeroPaddedFormat));
    return _loadedTranslations!;
  }

  
  bool shouldReload(MyLocalizationsDelegate old) => false;

  
  String toString() => 'GlobalMaterialLocalizations.delegate(${kMaterialSupportedLanguages.length} locales)';
}

3.在main.dar中补充该LocalizationsDelegate

class _MyApp extends State<MyApp> with WidgetsBindingObserver {
  
  Widget build(BuildContext context) {
    MainInit.buildInit(context);

    final ThemeData theme = ThemeData();
    return MaterialApp(
		///...
        ///国际化
        localizationsDelegates: const [
          MyLocalizationsDelegate.delegate, ///自定义的LocalizationsDelegate
          GlobalMaterialLocalizations.delegate,
          GlobalWidgetsLocalizations.delegate,
        ]
        ///supportedLocales中不用加该自定义Locale
  }

4. 注意

pubspec.yaml

dependencies:
  flutter:
    sdk: flutter
  flutter_localizations: # 需要注意需要配置了该值
    sdk: flutter

使用时

      Localizations.override(
        context: context,
        locale: Locale('my_local', 'CH'),
        child: widget,
      );
  • 9
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我可以为您讲解一下Flutter自定义Tab导航的实现方法。 对于顶部导航,可以使用TabBar和TabBarView来实现。TabBar是一个水平的导航栏,TabBarView是一个可以滚动的控件,可以用来展示不同的页面内容。下面是一个简单的示例代码: ``` TabController _tabController; @override void initState() { super.initState(); _tabController = TabController(length: 2, vsync: this); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('顶部导航'), bottom: TabBar( controller: _tabController, tabs: [ Tab(text: 'Tab1'), Tab(text: 'Tab2'), ], ), ), body: TabBarView( controller: _tabController, children: [ // Tab1页面内容 Container( child: Text('Tab1'), ), // Tab2页面内容 Container( child: Text('Tab2'), ), ], ), ); } ``` 对于底部导航,可以使用BottomNavigationBar来实现。BottomNavigationBar是一个底部导航栏,可以用来切换不同的页面。下面是一个简单的示例代码: ``` int _currentIndex = 0; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('底部导航'), ), body: Center( child: Text('当前页面: $_currentIndex'), ), bottomNavigationBar: BottomNavigationBar( currentIndex: _currentIndex, onTap: (index) { setState(() { _currentIndex = index; }); }, items: [ BottomNavigationBarItem( icon: Icon(Icons.home), title: Text('首页'), ), BottomNavigationBarItem( icon: Icon(Icons.search), title: Text('搜索'), ), BottomNavigationBarItem( icon: Icon(Icons.person), title: Text('个人中心'), ), ], ), ); } ``` 对于自定义Tab导航,可以使用自定义控件来实现。比如,可以使用Row和GestureDetector来构建一个自定义的Tab导航栏。下面是一个简单的示例代码: ``` int _currentIndex = 0; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('自定义Tab导航'), ), body: Center( child: Text('当前页面: $_currentIndex'), ), bottomNavigationBar: Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ GestureDetector( onTap: () { setState(() { _currentIndex = 0; }); }, child: Column( children: [ Icon(Icons.home, color: _currentIndex == 0 ? Colors.blue : Colors.grey), Text('首页', style: TextStyle(color: _currentIndex == 0 ? Colors.blue : Colors.grey)), ], ), ), GestureDetector( onTap: () { setState(() { _currentIndex = 1; }); }, child: Column( children: [ Icon(Icons.search, color: _currentIndex == 1 ? Colors.blue : Colors.grey), Text('搜索', style: TextStyle(color: _currentIndex == 1 ? Colors.blue : Colors.grey)), ], ), ), GestureDetector( onTap: () { setState(() { _currentIndex = 2; }); }, child: Column( children: [ Icon(Icons.person, color: _currentIndex == 2 ? Colors.blue : Colors.grey), Text('个人中心', style: TextStyle(color: _currentIndex == 2 ? Colors.blue : Colors.grey)), ], ), ), ], ), ); } ``` 以上是三种常见的Tab导航实现方法,您可以根据自己的需求选择合适的方式来实现。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值