HI. I need to write some text over a custom button. So I subclassed UIButton. In -drawrect, I write the text I need. The problem is that the text ends up under the button. After I write my text, UIButton's drawrect goes ahead and draws on top of me.
I am not even calling [super drawrect: rect] even though I was anticipating calling it before I did my drawing. It seems that UIButton's drawrect will get called regardless.
Any ideas? Thanks.
this works well for me...(ignore the complicated drawing code).
here my UIButton code:
h file:
#import <UIKit/UIKit.h>
@interface DoneButton : UIButton
@property (assign, nonatomic) BOOL selected;
@end
m file:
#import "DoneButton.h"
@implementation DoneButton
@synthesize selected = _selected;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
}
return self;
}
- (void)setSelected:(BOOL)selected
{
if (_selected != selected) {
_selected = selected;
[self setNeedsDisplay];
}
}
- (void)drawRect:(CGRect)rect
{
// Drawing code
if (_selected) {
//// Color Declarations
UIColor* color2 = [UIColor colorWithRed: 0 green: 0 blue: 0 alpha: 1];
//// Bezier Drawing
UIBezierPath* bezierPath = [UIBezierPath bezierPath];
[bezierPath moveToPoint: CGPointMake(49.39, 31.25)];
[bezierPath addLineToPoint: CGPointMake(49.39, 31.25)];
[bezierPath addCurveToPoint: CGPointMake(46.64, 25.19) controlPoint1: CGPointMake(49.39, 29.02) controlPoint2: CGPointMake(48.38, 26.94)];
[bezierPath addCurveToPoint: CGPointMake(44.3, 18.95) controlPoint1: CGPointMake(46.63, 22.72) controlPoint2: CGPointMake(45.88, 20.53)];
[bezierPath addCurveToPoint: CGPointMake(42.44, 17.59) controlPoint1: CGPointMake(43.75, 18.4) controlPoint2: CGPointMake(43.13, 17.95)];
[bezierPath addCurveToPoint: CGPointMake(38.07, 16.61) controlPoint1: CGPointMake(41.17, 16.93) controlPoint2: CGPointMake(39.67, 16.62)];
[bezierPath addCurveToPoint: CGPointMake(33.15, 13.95) controlPoint1: CGPointMake(36.62, 15.18) controlPoint2: CGPointMake(34.95, 14.23)];
[bezierPath addCurveToPoint: CGPointMake(32.78, 13.92) controlPoint1: CGPointMake(33.03, 13.93) controlPoint2: CGPointMake(32.9, 13.93)];
[bezierPath addCurveToPoint: CGPointMake(32, 13.86) controlPoint1: CGPointMake(32.52, 13.89) controlPoint2: CGPointMake(32.26, 13.86)];
[bezierPath addLineToPoint: CGPointMake(32, 13.86)];
[bezierPath addLineToPoint: CGPointMake(32, 13.86)];
[bezierPath addLineToPoint: CGPointMake(32, 13.86)];
[bezierPath addLineToPoint: CGPointMake(32, 13.86)];
[bezierPath addCurveToPoint: CGPointMake(31.38, 13.91) controlPoint1: CGPointMake(31.79, 13.86) controlPoint2: CGPointMake(31.59, 13.89)];
[bezierPath addCurveToPoint: CGPointMake(30.85, 13.95) controlPoint1: CGPointMake(31.2, 13.92) controlPoint2: CGPointMake(31.02, 13.92)];
[bezierPath addCurveToPoint: CGPointMake(26.92, 15.74) controlPoint1: CGPointMake(29.44, 14.17) controlPoint2: CGPointMake(28.12, 14.8)];
[bezierPath addCurveToPoint: CGPointMake(25.94, 16.61) controlPoint1: CGPointMake(26.58, 16.01) controlPoint2: CGPointMake(26.25, 16.29)];
[bezierPath addCurveToPoint: CGPointMake(24.13, 16.76) controlPoint1: CGPointMake(25.31, 16.61) controlPoint2: CGPointMake(24.71, 16.66)];
[bezierPath addCurveToPoint: CGPointMake(19.7, 18.95) controlPoint1: CGPointMake(22.41, 17.06) controlPoint2: CGPointMake(20.88, 17.77)];
[bezierPath addCurveToPoint: CGPointMake(17.36, 25.19) controlPoint1: CGPointMake(18.12, 20.53) controlPoint2: CGPointMake(17.37, 22.72)];
[bezierPath addCurveToPoint: CGPointMake(14.61, 31.25) controlPoint1: CGPointMake(15.62, 26.94) controlPoint2: CGPointMake(14.61, 29.02)];
[bezierPath addLineToPoint: CGPointMake(14.61, 31.25)];
[bezierPath addCurveToPoint: CGPointMake(14.61, 31.25) controlPoint1: CGPointMake(14.61, 31.25) controlPoint2: CGPointMake(14.61, 31.25)];
[bezierPath addCurveToPoint: CGPointMake(14.66, 31.92) controlPoint1: CGPointMake(14.61, 31.48) controlPoint2: CGPointMake(14.64, 31.7)];
[bezierPath addCurveToPoint: CGPointMake(14.7, 32.4) controlPoint1: CGPointMake(14.67, 32.08) controlPoint2: CGPointMake(14.67, 32.24)];
[bezierPath addCurveToPoint: CGPointMake(15.86, 35.44) controlPoint1: CGPointMake(14.86, 33.46) controlPoint2: CGPointMake(15.27, 34.48)];
[bezierPath addCurveToPoint: CGPointMake(15.97, 35.64) controlPoint1: CGPointMake(15.9, 35.5) controlPoint2: CGPointMake(15.93, 35.57)];
[bezierPath addCurveToPoint: CGPointMake(17.36, 37.32) controlPoint1: CGPointMake(16.36, 36.23) controlPoint2: CGPointMake(16.83, 36.78)];
[bezierPath addCurveToPoint: CGPointMake(17.49, 38.98) controlPoint1: CGPointMake(17.36, 37.89) controlPoint2: CGPointMake(17.41, 38.44)];
[bezierPath addCurveToPoint: CGPointMake(18.35, 41.7) controlPoint1: CGPointMake(17.65, 39.95) controlPoint2: CGPointMake(17.92, 40.87)];
[bezierPath addCurveToPoint: CGPointMake(19.7, 43.55) controlPoint1: CGPointMake(18.7, 42.38) controlPoint2: CGPointMake(19.15, 43)];
[bezierPath addCurveToPoint: CGPointMake(25.93, 45.89) controlPoint1: CGPointMake(21.28, 45.13) controlPoint2: CGPointMake(23.47, 45.88)];
[bezierPath addCurveToPoint: CGPointMake(27.61, 47.28) controlPoint1: CGPointMake(26.47, 46.42) controlPoint2: CGPointMake(27.02, 46.89)];
[bezierPath addCurveToPoint: CGPointMake(32, 48.64) controlPoint1: CGPointMake(28.96, 48.16) controlPoint2: CGPointMake(30.44, 48.64)];
[bezierPath addLineToPoint: CGPointMake(32, 48.64)];
[bezierPath addLineToPoint: CGPointMake(32, 48.64)];
[bezierPath addLineToPoint: CGPointMake(32, 48.64)];
[bezierPath addLineToPoint: CGPointMake(32, 48.64)];
[bezierPath addCurveToPoint: CGPointMake(38.06, 45.89) controlPoint1: CGPointMake(34.23, 48.64) controlPoint2: CGPointMake(36.31, 47.63)];
[bezierPath addCurveToPoint: CGPointMake(44.3, 43.55) controlPoint1: CGPointMake(40.53, 45.88) controlPoint2: CGPointMake(42.72, 45.13)];
[bezierPath addLineToPoint: CGPointMake(44.3, 43.55)];
[bezierPath addLineToPoint: CGPointMake(44.3, 43.55)];
[bezierPath addCurveToPoint: CGPointMake(46.64, 37.31) controlPoint1: CGPointMake(45.88, 41.97) controlPoint2: CGPointMake(46.63, 39.78)];
[bezierPath addCurveToPoint: CGPointMake(49.39, 31.25) controlPoint1: CGPointMake(48.38, 35.56) controlPoint2: CGPointMake(49.39, 33.48)];
[bezierPath addLineToPoint: CGPointMake(49.39, 31.25)];
[bezierPath closePath];
[color2 setStroke];
bezierPath.lineWidth = 1;
[bezierPath stroke];
//// Bezier 2 Drawing
UIBezierPath* bezier2Path = [UIBezierPath bezierPath];
[bezier2Path moveToPoint: CGPointMake(22.42, 29.85)];
[bezier2Path addLineToPoint: CGPointMake(29.74, 37.17)];
[bezier2Path addLineToPoint: CGPointMake(41.58, 25.33)];
bezier2Path.usesEvenOddFillRule = YES;
[color2 setStroke];
bezier2Path.lineWidth = 1;
[bezier2Path stroke];
} else {
//// Color Declarations
UIColor* color3 = [UIColor colorWithRed: 0.5 green: 0.5 blue: 0.5 alpha: 1];
//// Bezier 2 Drawing
UIBezierPath* bezier2Path = [UIBezierPath bezierPath];
[bezier2Path moveToPoint: CGPointMake(22.42, 29.85)];
[bezier2Path addLineToPoint: CGPointMake(29.74, 37.17)];
[bezier2Path addLineToPoint: CGPointMake(41.58, 25.33)];
bezier2Path.usesEvenOddFillRule = YES;
[color3 setStroke];
bezier2Path.lineWidth = 1;
[bezier2Path stroke];
}
}
if the button is selected draw the first code, else draw the other code. i prefer this method because I use Paint Code. so this saves a lot of time and you don't need to create thousands of pngs or jpegs.
As other people have said, you don't need to subclass UIButton - infact it's best not to as UIButton is pretty complex (as you found). You have three options:
addTarget:action:forControlEvents:
). UIButton implements statefulness on top of this. If you don't need things like UIButton's setTitle:forState:
and associated functionality but you are using a lot of these controls I would use the third option. Otherwise use the first (or second if you are on 3.0).
Based on your comment on one of the other answers, this is a case of asking "How do I do X with Y to achieve Z?" when you really should be asking "How do I achieve Z?"
If you want a button to draw text on top of an image instead of next to it, simply make the image the button's background image. Use setBackgroundImage:forState:
, rather than setImage:forState:
, then set the title normally.
In any case, you're either going to have to draw the image in drawRect:
, or move the text into a subview so it'll draw above the image. The solution I mentioned is a version of the second option.
You don't need to subclass UIButton just to add some text to it. Here's an example of setting the button title for a custom button within the -viewDidLoad method of a UIViewController subclass:
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = CGRectMake(0, 0, 44, 44);
[button setTitle:@"x" forState:UIControlStateNormal];
[self.view addSubview:button];
You can also set the font property of your button or change the color using -setTitleColor:forState:.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With