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

如何实现Flutter中如图所示的Container组件?三角区域实现无思路

实现右上角带三角信息区域的Container组件

方法1:用ClipPath自定义裁剪路径

直接把Container的右上角裁剪成三角形,再通过Stack定位文字到三角区域,适合三角和主容器同色的场景。

先定义自定义裁剪器:

class TriangleClipper extends CustomClipper<Path> {
  @override
  Path getClip(Size size) {
    final path = Path();
    // 绘制容器轮廓,右上角切出三角
    path.lineTo(0, size.height);
    path.lineTo(size.width, size.height);
    path.lineTo(size.width, 0);
    path.lineTo(size.width - 60, 0); // 三角左边界,可调整数值改变三角大小
    path.lineTo(0, 0);
    path.close();
    return path;
  }

  @override
  bool shouldReclip(covariant CustomClipper<Path> oldClipper) => false;
}

组装组件:

import 'dart:math';

Container(
  width: 300,
  height: 180,
  child: ClipPath(
    clipper: TriangleClipper(),
    child: Container(
      color: Colors.blueGrey[800],
      child: Stack(
        children: [
          // 背景图(可选)
          Positioned.fill(
            child: Opacity(
              opacity: 0.3,
              child: Image.network(
                'https://picsum.photos/300/180',
                fit: BoxFit.cover,
              ),
            ),
          ),
          // 三角区域文字
          Positioned(
            top: 0,
            right: 0,
            child: SizedBox(
              width: 60,
              height: 60,
              child: Transform.rotate(
                angle: -pi / 4, // 顺时针旋转45度
                origin: const Offset(30, 30), // 以中心点为旋转轴
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: const [
                    Text('科幻', style: TextStyle(color: Colors.white, fontSize: 12)),
                    Text('2023', style: TextStyle(color: Colors.white, fontSize: 14, fontWeight: FontWeight.bold)),
                  ],
                ),
              ),
            ),
          ),
          // 底部标题
          const Positioned(
            left: 16,
            bottom: 16,
            child: Text('星际穿越', style: TextStyle(color: Colors.white, fontSize: 18, fontWeight: FontWeight.bold)),
          ),
        ],
      ),
    ),
  ),
)

方法2:用Stack叠加独立三角组件

不需要裁剪主容器,直接在右上角叠加一个三角形状的Widget,适合三角和主容器不同色的场景,灵活性更高。

先定义三角Widget:

import 'dart:math';

class TriangleWidget extends StatelessWidget {
  final Color color;
  final Widget child;

  const TriangleWidget({super.key, required this.color, required this.child});

  @override
  Widget build(BuildContext context) {
    return SizedBox(
      width: 80,
      height: 80,
      child: Stack(
        children: [
          CustomPaint(painter: TrianglePainter(color: color)),
          Positioned(
            top: 10,
            right: 10,
            child: Transform.rotate(
              angle: -pi / 4,
              child: child,
            ),
          ),
        ],
      ),
    );
  }
}

class TrianglePainter extends CustomPainter {
  final Color color;

  TrianglePainter({required this.color});

  @override
  void paint(Canvas canvas, Size size) {
    final paint = Paint()..color = color;
    final path = Path();
    path.moveTo(size.width, 0);
    path.lineTo(size.width, size.height);
    path.lineTo(0, 0);
    path.close();
    canvas.drawPath(path, paint);
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) => false;
}

组装组件:

Container(
  width: 300,
  height: 180,
  color: Colors.blueGrey[800],
  child: Stack(
    children: [
      // 背景图(可选)
      Positioned.fill(
        child: Opacity(
          opacity: 0.3,
          child: Image.network(
            'https://picsum.photos/300/180',
            fit: BoxFit.cover,
          ),
        ),
      ),
      // 右上角三角组件
      const Positioned(
        top: 0,
        right: 0,
        child: TriangleWidget(
          color: Colors.orange,
          child: Column(
            children: [
              Text('科幻', style: TextStyle(color: Colors.white, fontSize: 12)),
              Text('2023', style: TextStyle(color: Colors.white, fontSize: 14, fontWeight: FontWeight.bold)),
            ],
          ),
        ),
      ),
      // 底部标题
      const Positioned(
        left: 16,
        bottom: 16,
        child: Text('星际穿越', style: TextStyle(color: Colors.white, fontSize: 18, fontWeight: FontWeight.bold)),
      ),
    ],
  ),
)

关键调整点

  • 三角大小:修改Clipper的偏移量(方法1)或TriangleWidget的宽高(方法2)即可调整。
  • 文字位置:通过Positioned的top/right参数和Transform.rotate的origin参数,让文字在三角内居中。
  • 颜色适配:方法2可单独设置三角背景色,不受主容器颜色影响。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 23:05:12