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

Flutter技术实现:如何裁剪Widget的指定侧边

问题原因

你的_BSideClipper中getClip方法的路径构建逻辑错误:频繁使用moveTo导致路径没有形成连续的闭合区域,默认情况下(四个参数均为false),路径中没有任何有效线段,最终裁剪后没有内容保留。此外,shouldReclip方法返回false,导致参数变化时无法重新裁剪。

修复后的代码

我们重新构建路径逻辑,确保路径是连续的闭合区域,同时修正shouldReclip方法,并添加裁剪宽度参数以控制裁剪范围:

import 'package:flutter/widgets.dart';

class BClipSide extends StatelessWidget {
  final bool left;
  final bool top;
  final bool right;
  final bool bottom;
  final double clipWidth;
  final Widget child;

  const BClipSide({
    super.key,
    this.left = false,
    this.top = false,
    this.right = false,
    this.bottom = false,
    this.clipWidth = 20.0,
    required this.child,
  });

  const BClipSide.symmetric({
    super.key,
    bool horizontal = false,
    bool vertical = false,
    this.clipWidth = 20.0,
    required this.child,
  })  : left = horizontal,
        right = horizontal,
        top = vertical,
        bottom = vertical;

  @override
  Widget build(BuildContext context) {
    return ClipPath(
      clipper: _BSideClipper(
        left: left,
        top: top,
        right: right,
        bottom: bottom,
        clipWidth: clipWidth,
      ),
      child: child,
    );
  }
}

class _BSideClipper extends CustomClipper<Path> {
  final bool left;
  final bool top;
  final bool right;
  final bool bottom;
  final double clipWidth;

  _BSideClipper({
    this.left = false,
    this.top = false,
    this.right = false,
    this.bottom = false,
    required this.clipWidth,
  });

  @override
  Path getClip(Size size) {
    final path = Path();

    // 计算裁剪后保留区域的四个顶点坐标
    final double leftX = left ? clipWidth : 0;
    final double topY = top ? clipWidth : 0;
    final double rightX = right ? size.width - clipWidth : size.width;
    final double bottomY = bottom ? size.height - clipWidth : size.height;

    // 构建连续闭合的路径,确保保留区域有效
    path.moveTo(leftX, topY);
    path.lineTo(rightX, topY);
    path.lineTo(rightX, bottomY);
    path.lineTo(leftX, bottomY);
    path.close();

    return path;
  }

  @override
  bool shouldReclip(covariant _BSideClipper oldClipper) {
    return oldClipper.left != left ||
        oldClipper.top != top ||
        oldClipper.right != right ||
        oldClipper.bottom != bottom ||
        oldClipper.clipWidth != clipWidth;
  }
}

说明

  1. 新增clipWidth参数:用于指定侧边裁剪的宽度,解决原代码无法控制裁剪范围的问题。
  2. 重构路径逻辑:根据裁剪参数计算出保留区域的四个顶点,构建连续的矩形路径,确保裁剪后有有效内容显示。
  3. 修正shouldReclip方法:当裁剪参数或宽度变化时,自动重新生成裁剪路径,保证UI及时更新。

使用示例

// 裁剪左侧和顶部,裁剪宽度为30
BClipSide(
  left: true,
  top: true,
  clipWidth: 30.0,
  child: Container(
    color: Colors.blue,
    width: 200,
    height: 200,
    child: const Center(child: Text('裁剪示例')),
  ),
)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 10:10:43