Flutter 学习之旅 之 flutter 不使用插件,简单实现一个 Toast 功能

Flutter 学习之旅 之 flutter 不使用插件,简单实现一个 Toast 功能

目录

[Flutter 学习之旅 之 flutter 不使用插件,简单实现一个 Toast 功能](#Flutter 学习之旅 之 flutter 不使用插件,简单实现一个 Toast 功能)

一、简单介绍

[二、简单介绍 Toast](#二、简单介绍 Toast)

[1. 确保正确配置 navigatorKey](#1. 确保正确配置 navigatorKey)

[2. 避免重复显示 Toast](#2. 避免重复显示 Toast)

[3. 确保 Toast 的上下文正确](#3. 确保 Toast 的上下文正确)

[4. 注意 Toast 的显示时长](#4. 注意 Toast 的显示时长)

三、简单案例实现

四、关键代码


一、简单介绍

Flutter 是一款开源的 UI 软件开发工具包,由 Google 开发和维护。它允许开发者使用一套代码同时构建跨平台的应用程序,包括移动设备(iOS 和 Android)、Web 和桌面平台(Windows、macOS 和 Linux)。

Flutter 使用 Dart 编程语言,它可以将代码编译为 ARM 或 Intel 机器代码以及 JavaScript,从而实现快速的性能。Flutter 提供了一个丰富的预置小部件库,开发者可以根据自己的需求灵活地控制每个像素,从而创建自定义的、适应性强的设计,这些设计在任何屏幕上都能呈现出色的外观和感觉。

二、简单介绍 Toast

在 Flutter 中,不使用 Toast 插件,可以通过 OverlayTimer 实现简单 Toast 功能。创建一个透明的 OverlayEntry,在其上显示自定义文本,设置显示时长后自动隐藏。这种方式无需额外依赖,灵活且轻量,适用于快速提示信息。

需要注意以下几点:


  • Toast 功能依赖于 navigatorKey 来获取 OverlayState,因此必须在 MaterialApp 中绑定 navigatorKey

    dart复制

    MaterialApp(
      navigatorKey: Toast.navigatorKey,
      ...
    );
    
  • 如果未绑定 navigatorKeyToast.show 方法会打印错误信息,并且无法显示 Toast。


2. 避免重复显示 Toast

  • 当用户快速多次点击按钮时,可能会导致多个 Toast 同时显示。可以通过以下方式解决:

    • 在显示 Toast 时设置一个标志位,避免重复调用。

    • 或者在显示新 Toast 时,先移除已存在的 Toast。


3. 确保 Toast 的上下文正确

  • Toast.show 方法通过 Overlay 显示,因此必须在包含 MaterialApp 的上下文中调用。

  • 如果在 MaterialApp 之外调用 Toast.show,会导致 OverlayStatenull


4. 注意 Toast 的显示时长

  • 默认情况下,Toast 的显示时长为 2 秒(Duration(seconds: 2))。如果需要更长或更短的显示时间,可以通过 duration 参数自定义:

    dart复制

    Toast.show("这是一条消息", duration: Duration(seconds: 3));
    
  • 如果显示时长过短,用户可能无法看清内容;如果过长,可能会影响用户体验。

三、简单案例实现

1、这里使用 Android Studio 进行创建 Flutter 项目

2、创建一个 application 的 Flutter 项目

3、编写代码,进行简单 Toast 功能实现

4、在 main 中添加测试 Toast 的 代码

5、连接设备,或者 web ,运行效果如下

四、关键代码

1、toast.dart

Dart 复制代码
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';

// 定义 Toast 的显示位置枚举
enum ToastPosition { top, center, bottom }

class Toast {
  // 定义一个全局的 NavigatorState 键,用于获取 OverlayState
  static final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();

  // Toast 显示方法
  static void show(
      String message, {
        ToastPosition position = ToastPosition.bottom, // 默认显示在底部
        Duration duration = const Duration(seconds: 2), // 默认显示时长为 2 秒
      }) {
    // 获取当前的 OverlayState
    final OverlayState? overlayState = navigatorKey.currentState?.overlay;

    // 如果 OverlayState 为空,说明未正确设置 MaterialApp 的 navigatorKey
    if (overlayState == null) {
      print("OverlayState is null. Make sure to use MaterialApp with navigatorKey.");
      return;
    }

    // 创建一个 OverlayEntry,用于显示 Toast
    final OverlayEntry overlayEntry = OverlayEntry(
      builder: (context) {
        // 根据 position 参数设置 Toast 的对齐方式
        return Align(
          alignment: position == ToastPosition.center
              ? Alignment.center // 显示在屏幕中央
              : position == ToastPosition.top
              ? Alignment.topCenter // 显示在顶部
              : Alignment.bottomCenter, // 显示在底部
          child: Padding(
            padding: EdgeInsets.only(
              top: position == ToastPosition.top ? 20 : 0, // 距离顶部 20px
              bottom: position == ToastPosition.bottom ? 20 : 0, // 距离底部 20px
            ),
            child: Material(
              elevation: 4, // 添加阴影效果
              borderRadius: BorderRadius.circular(50), // 设置为半圆形状
              child: Container(
                constraints: BoxConstraints(minWidth: 100, maxWidth: 300), // 限制 Toast 的宽度
                padding: EdgeInsets.all(16), // 内边距
                decoration: BoxDecoration(
                  color: Colors.black87, // 背景颜色
                  borderRadius: BorderRadius.circular(50), // 设置为半圆形状
                ),
                child: Text(
                  message, // 显示的文本内容
                  style: TextStyle(color: Colors.white, fontSize: 16), // 文本样式
                  textAlign: TextAlign.center, // 文本居中
                  softWrap: true, // 自动换行
                  maxLines: null, // 不限制行数
                ),
              ),
            ),
          ),
        );
      },
    );

    // 将 OverlayEntry 插入到 Overlay 中,显示 Toast
    overlayState.insert(overlayEntry);

    // 使用 SchedulerBinding 添加一个后帧回调
    SchedulerBinding.instance.addPostFrameCallback((_) {
      // 在指定的 duration 时间后移除 OverlayEntry,隐藏 Toast
      Future.delayed(duration).then((_) {
        overlayEntry.remove();
      });
    });
  }
}

代码说明:

  1. ToastPosition 枚举:定义了 Toast 的显示位置(顶部、中央、底部)。

  2. navigatorKey :用于获取当前 MaterialAppNavigatorState,从而获取 OverlayState

  3. show 方法

    • 接收 message 参数(显示的文本)和可选参数(位置和显示时长)。

    • 检查 OverlayState 是否为空,确保 MaterialApp 已正确配置。

    • 创建 OverlayEntry 并根据位置参数设置对齐方式。

    • 使用 MaterialContainer 构造 Toast 的样式,包括背景颜色、阴影、圆角和文本样式。

    • OverlayEntry 插入到 Overlay 中,显示 Toast。

    • 使用 SchedulerBindingFuture.delayed 在指定时长后移除 Toast。

2、main.dart

Dart 复制代码
import 'package:flutter/material.dart';
import 'toast.dart'; // 导入封装的 Toast 工具类,用于显示自定义 Toast

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Toast Demo', // 应用的标题
      navigatorKey: Toast.navigatorKey, // 将全局的 navigatorKey 绑定到 MaterialApp
      home: Scaffold( // 主页面布局
        appBar: AppBar( // 应用栏
          title: Text('Flutter Toast Demo'), // 标题
        ),
        body: Center( // 主体内容居中
          child: Column( // 垂直布局
            mainAxisAlignment: MainAxisAlignment.center, // 子组件垂直居中
            children: [
              ElevatedButton( // 按钮,点击后显示顶部 Toast
                onPressed: () {
                  Toast.show(
                    "这是一条顶部 Toast辅导费地方东方饭店", // 要显示的文本
                    position: ToastPosition.top, // 设置 Toast 显示在顶部
                  );
                },
                child: Text('显示顶部 Toast'), // 按钮文本
              ),
              SizedBox(height: 20), // 间距
              ElevatedButton( // 按钮,点击后显示中间 Toast
                onPressed: () {
                  Toast.show(
                    "这是一条中间 Toast", // 要显示的文本
                    position: ToastPosition.center, // 设置 Toast 显示在中间
                  );
                },
                child: Text('显示中间 Toast'), // 按钮文本
              ),
              SizedBox(height: 20), // 间距
              ElevatedButton( // 按钮,点击后显示底部 Toast
                onPressed: () {
                  Toast.show(
                    "这是一条底部 Toast", // 要显示的文本
                    position: ToastPosition.bottom, // 设置 Toast 显示在底部
                  );
                },
                child: Text('显示底部 Toast'), // 按钮文本
              ),
            ],
          ),
        ),
      ),
    );
  }
}

代码说明:

  1. 导入模块

    • import 'toast.dart';:导入封装好的 Toast 工具类,用于实现自定义 Toast 功能。
  2. MyApp

    • MaterialApp:Flutter 的根组件,用于配置主题和路由。

    • navigatorKey: Toast.navigatorKey:将 Toast 类中定义的全局 navigatorKey 绑定到 MaterialApp,以便通过 navigatorKey 获取 OverlayState,这是显示 Toast 的关键。

  3. Scaffold

    • Scaffold 是 Flutter 中用于构建页面布局的基础组件,包含 appBarbody

    • appBar:显示页面的标题。

    • body:页面的主体内容,使用 CenterColumn 布局,将按钮垂直居中。

  4. 按钮功能

    • 每个按钮通过 onPressed 回调调用 Toast.show 方法。

    • Toast.show 方法接收一个字符串(要显示的文本)和一个可选参数 position(指定 Toast 的显示位置:顶部、中间、底部)。

    • 示例中分别展示了如何调用顶部、中间和底部的 Toast。

相关推荐
SunshineBrother5 小时前
Flutter性能优化细节
android·flutter·ios
GeniuswongAir9 小时前
Flutter的permission_handler插件检查iOS的通知权限不准确
flutter
Wuxiaoming1359 小时前
flutter的debounce_throttle插件使用
开发语言·javascript·flutter
hudawei9969 小时前
flutter页面跳转
flutter
恋猫de小郭1 天前
腾讯 TDF 即将开源 Kuikly 跨端框架,Kotlin 支持全平台
android·flutter·ios
恋猫de小郭1 天前
Android Studio Meerkat | 2024.3.1 更新,快来看看有什么新功能吧
android·前端·flutter
Zender Han2 天前
Jenkins与Flutter项目持续集成实战指南
flutter·ci/cd·jenkins
仙魁XAN2 天前
Flutter 学习之旅 之 flutter 使用 flutter_screenutil 简单进行屏幕适配
android·flutter·dart·屏幕适配·screenutil
代码轨迹2 天前
Flutter实现短信验证码监控与转发
人工智能·flutter·自动化