Swift UIButton 子类未显示在设备或模拟器上

Posted

技术标签:

【中文标题】Swift UIButton 子类未显示在设备或模拟器上【英文标题】:Swift UIButton Subclass not Showing on device or Simulator 【发布时间】:2015-02-04 17:34:50 【问题描述】:

我有以下代码并声明了 IBDesignable。

DrawRect 在 Interface Builder 中显示得非常好,但在模拟器或设备上却完全没有。

有人知道为什么吗?

import UIKit
import QuartzCore

@IBDesignable class VideoButton: UIButton 
    // Only override drawRect: if you perform custom drawing.
    // An empty implementation adversely affects performance during animation.
    override func drawRect(rect: CGRect)
    

        let color2 = UIColor(red: 0.500, green: 0.500, blue: 0.500, alpha: 0.000)

        //// Oval Drawing
        var ovalPath = UIBezierPath(ovalInRect: CGRectMake(frame.minX + floor(frame.width * 0.03571) + 0.5, frame.minY + floor(frame.height * 0.03571) + 0.5, floor(frame.width * 0.96429) - floor(frame.width * 0.03571), floor(frame.height * 0.96429) - floor(frame.height * 0.03571)))
        color2.setFill()
        ovalPath.fill()
        UIColor.whiteColor().setStroke()
        ovalPath.lineWidth = 3
        ovalPath.stroke()


        //// Rectangle Drawing
        let rectanglePath = UIBezierPath(roundedRect: CGRectMake(frame.minX + floor(frame.width * 0.25714 + 0.5), frame.minY + floor(frame.height * 0.34286 + 0.5), floor(frame.width * 0.60000 + 0.5) - floor(frame.width * 0.25714 + 0.5), floor(frame.height * 0.64286 + 0.5) - floor(frame.height * 0.34286 + 0.5)), cornerRadius: 2)
        color2.setFill()
        rectanglePath.fill()
        UIColor.whiteColor().setStroke()
        rectanglePath.lineWidth = 3
        rectanglePath.stroke()


        //// Bezier Drawing
        var bezierPath = UIBezierPath()
        bezierPath.moveToPoint(CGPointMake(frame.minX + 0.61429 * frame.width, frame.minY + 0.50536 * frame.height))
        bezierPath.addLineToPoint(CGPointMake(frame.minX + 0.75714 * frame.width, frame.minY + 0.34286 * frame.height))
        bezierPath.addLineToPoint(CGPointMake(frame.minX + 0.75714 * frame.width, frame.minY + 0.64286 * frame.height))
        bezierPath.addLineToPoint(CGPointMake(frame.minX + 0.61429 * frame.width, frame.minY + 0.50536 * frame.height))
        bezierPath.closePath()
        bezierPath.lineJoinStyle = kCGLineJoinRound;

        color2.setFill()
        bezierPath.fill()
        UIColor.whiteColor().setStroke()
        bezierPath.lineWidth = 3
        bezierPath.stroke()
        //  

    


【问题讨论】:

【参考方案1】:

将对“frame”的引用更改为“rect”,它应该会在设备和模拟器中绘制。

【讨论】:

【参考方案2】:

您不应该为 UIButton 子类覆盖 drawRect:。没有必要;您可以使用 UIButton 的各种属性和方法自定义其外观。目前还不清楚你为什么要这样做。 (您正在这样做,而不是调用super,这一事实可能解释了问题;但解决方案不是,调用super,而是不要一开始就这样做地点。)

【讨论】:

为什么不覆盖draw rect,这肯定比在按钮本身添加另一个视图更好? 为什么需要为按钮本身添加另一个视图?你到底想做什么? @matt 我想知道同样的事情,你为什么不想覆盖drawRect。为了我的使用,我正在制作径向按钮。选中时为实心圆,未选中时仅为圆的轮廓。我认为这是覆盖drawRect 的理想选择。 @random UIButton 是所有界面类中用户可配置性最高的类之一。您说:“选择时是实心圆,未选择时只是圆的轮廓” UIButton 为您提供了这样做的钩子。您可以设置所选背景和普通背景。您甚至可以覆盖 backgroundRectimageRect 之类的方法,以在不同情况下更改大小和位置。完全不需要干涉视图的绘制。 @matt 我明白了。设置选中背景和普通背景不需要图片吗?覆盖drawRect 是否有任何不利影响?所以我使用 PaintCode 为我制作的图标生成绘图代码......我的想法是它比传递图像更有效。我肯定是错的。任何反馈都非常感谢! :)【参考方案3】:

我最近一直在尝试做类似的事情 - 创建 UIButton 的子类,覆盖 drawRect() 以绘制一个简单的自定义图标(我正在制作一个在“播放”和“停止”之间交替的播放/停止按钮" 每次点击):

也许我对 ios 开发还不够了解,但在回应其他答案和older posts 在线不鼓励扩展UIButton 类时,我不明白为什么这是一个坏主意。当然,您可以通过设置自定义背景图像来自定义按钮,但在我看来,这不像覆盖 drawRect 那样灵活(更不用说在您想要更改某些内容时编辑按钮会很痛苦,因为您有编辑实际图像而不是几行代码)。

我确信还有其他方法可以达到相同的结果(例如,通过自定义 UIView 监听触摸事件来实现按钮),但我认为最简洁和最简单的方法仍然是扩展 @ 987654331@班级。毕竟是subclass itself of UIView.

关于您的代码 - 它似乎在我的环境中正常工作,尽管我不得不稍微更改颜色以使其显示在白色背景上(即 UIColor.blackColor().setStroke() 而不是 UIColor.whiteColor().setStroke())。此外,正如@Astrodan 所提到的,使用rect 而不是frame 可能是个好主意,因为它正在传递给您(尽管代码对我来说与frame 一起使用):

XCode 中的实时渲染故事板:

在 iPhone 6 模拟器上:

【讨论】:

以上是关于Swift UIButton 子类未显示在设备或模拟器上的主要内容,如果未能解决你的问题,请参考以下文章

Swift 设置子类 UIButton ButtonType

swift 3 - 未显示子类视图控制器

Swift UIButton 子类并根据变量更改颜色

Swift - 无论状态如何设置 UIButton 标题

UIButton 子类 initWithCoder 中的 setTitleColor:forState 未设置颜色

从 nib 加载的 UIButton 的子类未正确初始化