【问题标题】:Create round UIButton with custom drawRect: method使用自定义 drawRect: 方法创建圆形 UIButton
【发布时间】:2017-03-15 15:41:32
【问题描述】:

我的目标是创建一个自定义的UIButton 子类,它创建一个带有一些附加功能的圆形(或圆形矩形)按钮。

经过一番搜索,我发现简单地设置按钮层的cornerRadius是最简单的让按钮变圆的方法:

@implementation MyRoundButton

-(id)initWithFrame:(CGRect)frame{
    if (self = [super initWithFrame:frame])
        [self setupView];

    return self;
}

-(id)initWithCoder:(NSCoder *)aDecoder{
    if(self = [super initWithCoder:aDecoder])
        [self setupView];

    return self;
}

-(void)setupView {    
    self.layer.cornerRadius = MIN(self.frame.size.height, self.frame.size.width) / 2.0;
}

只要我不覆盖drawRect:,这很好用

- (void)drawRect:(CGRect)rect {
    [super drawRect:rect];
}

当然,我想在drawRect: 中添加一些自定义绘图代码,但即使只有[super drawRect:rect],按钮也不再是圆形的:它在其边界内绘制为矩形。

这怎么可能? 用一个简单的超级调用覆盖一个方法怎么会改变行为呢?

我怎样才能避免这个问题?我已经尝试让图层保持不变,并在drawRect: 中简单地手动绘制背景。但是无论如何,按钮都会绘制它的背景矩形,而我的自定义绘图就在它上面。

那么,如何解决这个问题?

【问题讨论】:

  • “如何通过简单的超级调用覆盖方法来改变行为” UIButton 可能会检查覆盖并表现不同。它根本不需要用drawRect实现自己。
  • 这可能是一种解释,但这种实现的原因可能是什么?什么都不改变的代码会改变什么?很奇怪......但是:实际的问题是别的:如何创建一个使用drawRect:的圆形按钮@
  • 为什么要打电话给[super drawRect:rect];
  • 您可能必须在您的按钮上将 opaque 设置为 false。
  • super 调用应该显示,即使没有任何变化,也有一些变化。 @jlehr 描述/回答了这个原因。更改按钮的opaque 值不会影响图层是否绘制其背景。

标签: ios objective-c uibutton


【解决方案1】:

您示例中的图层在概念上包含具有圆角半径的背景,但 drawRect: 的空覆盖会导致它被忽略。这是因为,通常情况下,UIView 的实例依赖于其内置层(CALayer 的实例)来呈现其内容,因此不会调用 drawRect:。但是,图层能够将绘图行为委托给其视图,如果您实现drawRect:,就会这样做。

如果您只是将UIView 子类化,这应该不会出现任何问题。但是,对诸如UIButton 之类的框架组件进行子类化有点冒险。一个潜在的问题是拨打-[super drawRect:];很难确切地知道可能会导致什么恶作剧,但这可能是问题的根源。默认情况下,UIButton 不需要做任何自定义绘图;它包含一个私有类的嵌套实例,UIButtonLabel,用于绘制按钮的标题。

与其尝试覆盖内部细节为私有的类的绘制行为,不如考虑使用一个或多个静态图像,并简单地将按钮的背景图像属性设置为一个或多个状态。

【讨论】:

  • 非常感谢,这听起来很合理。但是我不确定这是否完全正确:我会理解如果实现drawRect: 将用作从图层绘图切换到视图绘图的触发器,因此该图层将被简单地忽略。但这种情况并非如此。如果实现了drawRect:,该层将始终是其背景,我发现没有办法阻止它这样做。所以图层绘图仍然处于活动状态,我只能添加视图绘图,但我的目标是替换图层绘图。我该怎么做?
  • 我编辑了我的答案。您是否尝试过取消对-[super drawRect:] 的呼叫?
  • super 调用仅用于演示,即使 drawRect: 的覆盖版本不会改变任何内容也会导致问题。删除 supper 调用不会改变任何内容。我现在明白了,即使添加一个覆盖版本也足以改变一些东西。然而我的主要目标是相同的:如何覆盖 UIButton,使其圆形并同时使用自定义绘图?仅自定义绘图不起作用,因为我无法阻止按钮拖拽其背景层。设置图层cornerRadius 不起作用,因为我不能再使用自定义绘图了
【解决方案2】:

看看这是否改变了什么......

-(void)setupView {    
    self.layer.cornerRadius = MIN(self.frame.size.height, self.frame.size.width) / 2.0;
    self.clipsToBounds = YES;
}

【讨论】:

  • 这部分解决了问题:按钮现在是圆形的,即使我使用自定义绘图(覆盖drawRect:),但现在按钮被剪裁到其边界(惊喜,惊喜:),因此阴影,添加到图层中的不再可见...
  • 抱歉,您的问题中没有看到任何关于需要阴影的内容。做事的方法不止一种......也许如果你发布你的最终目标是什么?
猜你喜欢
  • 1970-01-01
  • 2016-02-01
  • 2012-01-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多