Flutter教程实现自定义Toast消息

在Flutter中实现自定义Toast消息时遇到几个问题:

  1. 原生Toast的样式太局限,如何完全自定义布局和动画效果?
  2. 使用Overlay显示Toast时,多次快速触发会导致Toast重叠或消失异常,该怎么解决?
  3. 希望Toast能根据内容自动调整宽度,但文字换行后高度计算不准,有没有成熟的方案?
  4. 在iOS和Android上Toast的显示位置和持续时间差异较大,如何统一多端表现?
  5. 现有插件如fluttertoast不支持自定义Widget,是否有轻量级的替代方案?
3 回复

实现自定义Toast消息可以使用Flutter的StackPositioned来定位一个Container作为Toast。首先创建一个StatefulWidget管理Toast的显示状态。

  1. 创建一个全局Key:final _globalKey = GlobalKey();
  2. 使用OverlayEntry动态插入悬浮层。
  3. 在需要显示Toast的地方调用方法,如showCustomToast('提示信息')
  4. Toast逻辑中,设置延迟隐藏(可用Timer)并移除OverlayEntry。

示例代码:

void showCustomToast(String msg) {
  Overlay.of(context)?.insert(
    OverlayEntry(
      builder: (context) => Positioned(
        top: 50,
        left: 0,
        right: 0,
        child: Container(
          padding: EdgeInsets.all(10),
          decoration: BoxDecoration(color: Colors.black.withOpacity(0.7), borderRadius: BorderRadius.circular(10)),
          child: Text(msg, style: TextStyle(color: Colors.white)),
        ),
      ),
    ),
  );
}

这样就能在屏幕顶部显示自定义样式Toast,并自动消失。记得处理好上下文引用问题,避免内存泄漏。

更多关于Flutter教程实现自定义Toast消息的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


要实现自定义 Toast 消息,你可以创建一个弹出窗口并将其定位到屏幕的特定位置。以下是一个简单的 Flutter 实现:

  1. 创建一个 StatefulWidget 来管理弹出窗口的状态。
  2. 使用 Stack 将自定义的 Widget 放置在顶层。
  3. 利用 GlobalKey 获取父组件的渲染框。

代码示例:

import 'package:flutter/material.dart';

class CustomToast extends StatefulWidget {
  @override
  _CustomToastState createState() => _CustomToastState();
}

class _CustomToastState extends State<CustomToast> {
  final globalKey = GlobalKey();
  OverlayEntry? overlayEntry;

  void showCustomToast(BuildContext context) {
    overlayEntry = OverlayEntry(
      builder: (context) => Positioned(
        left: 16,
        bottom: 48,
        width: MediaQuery.of(context).size.width - 32,
        child: Material(
          color: Colors.black.withOpacity(0.7),
          borderRadius: BorderRadius.circular(12),
          child: Padding(
            padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 16),
            child: Text(
              "这是一条自定义Toast消息",
              style: TextStyle(color: Colors.white),
            ),
          ),
        ),
      ),
    );
    Overlay.of(context)?.insert(overlayEntry!);
    Future.delayed(Duration(seconds: 2), hideCustomToast);
  }

  void hideCustomToast() {
    overlayEntry?.remove();
    overlayEntry = null;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text("自定义Toast")),
      body: Center(
        child: ElevatedButton(
          onPressed: () => showCustomToast(context),
          child: Text("显示Toast"),
        ),
      ),
    );
  }
}

这段代码会在按钮点击时显示一个黑色背景、白色文字的自定义 Toast,两秒后自动消失。

在Flutter中实现自定义Toast消息可以通过Overlay组件结合Animation来实现。以下是完整实现步骤:

  1. 创建Toast工具类
import 'package:flutter/material.dart';

class Toast {
  static void show(
    BuildContext context, {
    required String message,
    Duration duration = const Duration(seconds: 2),
  }) {
    final overlay = Overlay.of(context);
    final overlayEntry = OverlayEntry(
      builder: (context) => Positioned(
        bottom: 100,
        left: MediaQuery.of(context).size.width * 0.1,
        child: Material(
          color: Colors.transparent,
          child: Container(
            padding: EdgeInsets.symmetric(horizontal: 24, vertical: 12),
            decoration: BoxDecoration(
              color: Colors.black.withOpacity(0.7),
              borderRadius: BorderRadius.circular(20),
            ),
            child: Text(
              message,
              style: TextStyle(color: Colors.white),
            ),
          ),
        ),
      ),
    );

    overlay.insert(overlayEntry);
    
    Future.delayed(duration, () {
      overlayEntry.remove();
    });
  }
}
  1. 使用示例
// 在任何地方调用
Toast.show(context, message: "这是自定义Toast消息");

// 带自定义持续时间
Toast.show(
  context,
  message: "3秒后消失", 
  duration: Duration(seconds: 3)
);
  1. 进阶改进(可选)

如果要添加动画效果,可以修改为:

builder: (context) => AnimatedOpacity(
  opacity: 1.0,
  duration: Duration(milliseconds: 300),
  child: Positioned(...), // 保留之前的Positioned内容
)

这个实现有以下特点:

  • 自动居中显示
  • 自定义显示时长
  • 半透明黑色背景
  • 圆角边框
  • 可扩展添加动画效果

在需要的地方直接调用Toast.show()方法即可显示自定义Toast消息。

回到顶部