You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter自定义Snackbar:如何同时实现圆角与底部彩色边框

解决方案

要实现带圆角且仅底部有彩色边框的Snackbar,由于默认的RoundedRectangleBorder无法单独设置单一边框样式,我们可以自定义一个ShapeBorder来满足需求,无需依赖外部库或嵌套Container。

1. 自定义圆角底部边框类

创建一个继承自ShapeBorder的类,实现圆角和底部边框的绘制逻辑:

import 'dart:math';
import 'package:flutter/material.dart';

class RoundedBottomBorder extends ShapeBorder {
  final BorderRadius borderRadius;
  final BorderSide bottomSide;

  const RoundedBottomBorder({
    this.borderRadius = const BorderRadius.all(Radius.circular(8)),
    this.bottomSide = const BorderSide(color: Colors.green, width: 4),
  });

  @override
  EdgeInsetsGeometry get dimensions => EdgeInsets.only(bottom: bottomSide.width);

  @override
  Path getInnerPath(Rect rect, {TextDirection? textDirection}) {
    return Path()
      ..addRRect(borderRadius.resolve(textDirection).toRRect(rect).deflate(bottomSide.width));
  }

  @override
  Path getOuterPath(Rect rect, {TextDirection? textDirection}) {
    return Path()..addRRect(borderRadius.resolve(textDirection).toRRect(rect));
  }

  @override
  void paint(Canvas canvas, Rect rect, {TextDirection? textDirection}) {
    final paint = bottomSide.toPaint();
    final rRect = borderRadius.resolve(textDirection).toRRect(rect);
    
    // 绘制底部直线边框
    final start = Offset(rRect.left, rRect.bottom - rRect.bottomLeftRadius.y);
    final end = Offset(rRect.right, rRect.bottom - rRect.bottomRightRadius.y);
    canvas.drawLine(start, end, paint);
    
    // 绘制左下角圆角边框
    canvas.drawArc(
      Rect.fromLTWH(rRect.left, rRect.bottom - rRect.bottomLeftRadius.y * 2, rRect.bottomLeftRadius.x * 2, rRect.bottomLeftRadius.y * 2),
      0,
      pi / 2,
      false,
      paint,
    );
    
    // 绘制右下角圆角边框
    canvas.drawArc(
      Rect.fromLTWH(rRect.right - rRect.bottomRightRadius.x * 2, rRect.bottom - rRect.bottomRightRadius.y * 2, rRect.bottomRightRadius.x * 2, rRect.bottomRightRadius.y * 2),
      -pi / 2,
      pi / 2,
      false,
      paint,
    );
  }

  @override
  ShapeBorder scale(double t) {
    return RoundedBottomBorder(
      borderRadius: borderRadius * t,
      bottomSide: bottomSide.scale(t),
    );
  }
}

2. 在Snackbar中使用自定义边框

直接将自定义的RoundedBottomBorder赋值给Snackbar的shape参数即可:

var snackBar = SnackBar(
  behavior: SnackBarBehavior.floating,
  backgroundColor: Colors.white, // 可根据需求修改背景色
  shape: const RoundedBottomBorder(
    borderRadius: BorderRadius.all(Radius.circular(8)),
    bottomSide: BorderSide(color: Colors.green, width: 4),
  ),
  content: Flex(
    direction: Axis.horizontal,
    children: [
      Padding(
        padding: const EdgeInsets.only(right: 12),
        child: Icon(Icons.add),
      ),
      Text("Toast message"),
    ],
  ),
);

这个自定义边框通过绘制底部直线和左右圆角弧,同时保证Snackbar的内容区域是圆角的,完美结合了你需要的两个效果。

内容的提问来源于stack exchange,提问作者Ana

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 04:57:37