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

Swift中如何在UIImageView底部中间添加标记式三角形

在UIImageView底部中间添加三角形的实现方案

你可以通过两种常见方式实现这个需求:使用CAShapeLayer绘制三角形(适合快速添加)或者自定义UIImageView子类(适配AutoLayout更友好)。结合你现有的代码,我给你具体的实现示例:


方法一:使用CAShapeLayer直接添加三角形

这种方法不需要修改现有UIImageView的类型,直接给它的layer添加子layer即可:

let img_view: UIImageView!
img_view = UIImageView(frame: CGRect(x: 0, y: 0, width: 30, height: 30))
let url_img = URL(string: Constants.img_url+"\(img)")!
img_view.af_setImage(withURL: url_img)
img_view.layer.cornerRadius = img_view.frame.size.height/2
img_view.layer.borderWidth = 1
img_view.layer.borderColor = UIColor.rgb(red: 229, green: 57, blue: 53, alpha: 1).cgColor
img_view.clipsToBounds = false // 关键:如果三角形在UIImageView外部,需要关闭裁剪

// 1. 创建三角形的ShapeLayer
let triangleLayer = CAShapeLayer()
triangleLayer.fillColor = UIColor.rgb(red: 229, green: 57, blue: 53, alpha: 1).cgColor // 和边框同色,或者自定义

// 2. 绘制三角形路径(底部中间向外的三角形,可调整顶点坐标改变形状)
let trianglePath = UIBezierPath()
let centerX = img_view.bounds.midX
let bottomY = img_view.bounds.maxY
// 三个顶点:底部中心、左上方、右上方(向下的小三角形)
trianglePath.move(to: CGPoint(x: centerX, y: bottomY))
trianglePath.addLine(to: CGPoint(x: centerX - 6, y: bottomY - 8))
trianglePath.addLine(to: CGPoint(x: centerX + 6, y: bottomY - 8))
trianglePath.close()

triangleLayer.path = trianglePath.cgPath

// 3. 添加到UIImageView的layer上
img_view.layer.addSublayer(triangleLayer)

注意点:

  • 如果三角形需要显示在UIImageView外部,必须设置img_view.clipsToBounds = false,否则会被圆形裁剪掉。
  • 调整顶点坐标可以改变三角形的大小和方向:比如想让三角形向内(圆形内部底部),可以把bottomY改成img_view.bounds.maxY - 4,另外两个点的y坐标再往上偏移。

方法二:自定义UIImageView子类(适配AutoLayout)

如果你的UIImageView是用AutoLayout布局的(非固定frame),自定义子类会更灵活,能自动适配尺寸变化:

class BadgeImageView: UIImageView {
    // 三角形颜色,默认和边框同色
    var triangleColor: UIColor = UIColor.rgb(red: 229, green: 57, blue: 53, alpha: 1) {
        didSet { setNeedsDisplay() }
    }
    
    override func draw(_ rect: CGRect) {
        super.draw(rect)
        
        // 绘制三角形
        let trianglePath = UIBezierPath()
        let centerX = rect.midX
        let bottomY = rect.maxY
        
        trianglePath.move(to: CGPoint(x: centerX, y: bottomY))
        trianglePath.addLine(to: CGPoint(x: centerX - 6, y: bottomY - 8))
        trianglePath.addLine(to: CGPoint(x: centerX + 6, y: bottomY - 8))
        trianglePath.close()
        
        triangleColor.setFill()
        trianglePath.fill()
    }
    
    override func layoutSubviews() {
        super.layoutSubviews()
        // 确保圆角始终为圆形
        layer.cornerRadius = bounds.height / 2
        layer.borderWidth = 1
        layer.borderColor = triangleColor.cgColor
    }
}

替换使用这个子类:

let img_view = BadgeImageView(frame: CGRect(x: 0, y: 0, width: 30, height: 30))
let url_img = URL(string: Constants.img_url+"\(img)")!
img_view.af_setImage(withURL: url_img)
img_view.clipsToBounds = false // 三角形在外部时需关闭裁剪
// 可自定义三角形颜色:img_view.triangleColor = .yellow

额外优化建议:

  • 如果需要三角形带边框,可以给triangleLayer设置borderWidth和borderColor,或者在绘制路径时添加描边操作。
  • 若UIImageView会有尺寸变化(比如旋转屏幕),方法二的自定义子类会自动重新绘制三角形,而方法一需要在layoutSubviews中更新三角形路径。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 11:07:50