创建uibutton子类

时间:2011-02-18 19:29:52

标签: iphone objective-c

我尝试将UIButton子类化为包含活动指示符,但是当我使用initWithFrame :(因为我是uibutton的子类我不使用buttonWithType :)按钮不显示。另外,在这种情况下我如何设置按钮类型?:

我的视图控制器:

    ActivityIndicatorButton *button = [[ActivityIndicatorButton alloc] initWithFrame:CGRectMake(10, 10, 300, 44)];
    [button addTarget:self action:@selector(buttonPressed) forControlEvents:UIControlEventTouchUpInside];
    [button setTitle:@"Older Posts..." forState: UIControlStateNormal];
    [cell addSubview:button];
    [button release];

my activityindicatorbutton class:

#import <Foundation/Foundation.h>


@interface ActivityIndicatorButton : UIButton {

    UIActivityIndicatorView *_activityView;
}

-(void)startAnimating;
-(void)stopAnimating;
@end

@implementation ActivityIndicatorButton

- (id)initWithFrame:(CGRect)frame {
    if (self=[super initWithFrame:frame]) {
        _activityView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
        _activityView.frame = CGRectOffset(_activityView.frame, 60.0f, 10.0f);

        [self addSubview: _activityView];
    }
    return self;
}

-(void) dealloc{
    [super dealloc];
    [_activityView release];
    _activityView = nil;
}

-(void)startAnimating {
    [_activityView startAnimating];
}

-(void)stopAnimating {
    [_activityView stopAnimating];
}
@end

5 个答案:

答案 0 :(得分:10)

赞成合成而不是继承。

创建一个包含所需组件的UIView,并将它们添加到视图中。

答案 1 :(得分:5)

我遇到了类似的情况,并同意杰夫的说法,你真的不需要继承UIButton。我通过继承UIControl来解决这个问题,然后重写layoutSubviews来完成我想要的“按钮”视图的所有配置。这是一个更简单的实现,它继承了UIButton,因为似乎有一些隐藏的mojo在幕后进行。我的实现看起来像这样:

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

    self.imageView = [[UIImageView alloc] initWithFrame:CGRectZero];
    [self addSubview:self.imageView];

    self.textLabel = [[UILabel alloc] initWithFrame:CGRectZero];
    [self addSubview:self.textLabel];
    }

return self;
}

layoutSubviews看起来像这样:

- (void)layoutSubviews {
[super layoutSubviews];

// Get the size of the button
CGRect bounds = self.bounds;

// Configure the subviews of the "button"
...
}

答案 2 :(得分:2)

我创建了一个自定义类,更喜欢组合而不是继承,它完美无缺。我的自定义类有一个按钮,它知道它是MCContact对象。它还绘制一个合适的按钮,并使用传递的MCContact对象自动计算帧。

标头文件示例:

#import <UIKit/UIKit.h>

@protocol MCContactViewDelegate;

@interface MCContactView : UIView
{

}

@property (nonatomic, strong) MCContact *mcContact;
@property (nonatomic, weak) id <MCContactViewDelegate> delegate;

- (id)initWithContact:(MCContact*)mcContact delegate:(id <MCContactViewDelegate>)delegate;

@end

@protocol MCContactViewDelegate <NSObject>

- (void)contactViewButtonClicked:(MCContactView*)contactView;

@end

实施文件:

#import "MCContactView.h"

@interface MCContactView()
{
    UIButton *_button;
}

@end

@implementation MCContactView

- (id)initWithContact:(MCContact*)mcContact delegate:(id <MCContactViewDelegate>)delegate
{
    self = [super initWithFrame:CGRectZero];

    if (self) {

        GetTheme();

        _mcContact = mcContact;
        _delegate = delegate;
        _button = [UIButton buttonWithType:UIButtonTypeCustom];

        UIImage *normalBackgroundImage = [[UIImage imageNamed:@"tokenNormal.png"] stretchableImageWithLeftCapWidth:12.5 topCapHeight:12.5];
        [_button setBackgroundImage:normalBackgroundImage forState:UIControlStateNormal];

        UIImage *highlightedBackgroundImage = [[UIImage imageNamed:@"tokenHighlighted.png"] stretchableImageWithLeftCapWidth:12.5 topCapHeight:12.5];
        [_button setBackgroundImage:highlightedBackgroundImage forState:UIControlStateHighlighted];

        _button.titleLabel.font = [theme contactButtonFont];
        [_button setTitleColor:[theme contactButtonTextColor] forState:UIControlStateNormal];

        [_button setTitleEdgeInsets:UIEdgeInsetsMake(4, 6, 4, 6)];

        NSString *tokenString = ([allTrim(mcContact.name) length]>0) ? mcContact.name : mcContact.eMail;
        [_button setTitle:tokenString forState:UIControlStateNormal];

        [_button addTarget:self action:@selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];

        CGSize size = [tokenString sizeWithFont:[theme contactButtonFont]];
        size.width += 20;
        if (size.width > 200) {
            size.width = 200;
        }
        size.height = normalBackgroundImage.size.height;
        [_button setFrame:CGRectMake(0, 0, size.width, size.height)];

        self.frame = _button.frame;
        [self addSubview:_button];
    }

    return self;
}


- (void)buttonClicked:(id)sender
{
    [self.delegate contactViewButtonClicked:self];
}

/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
    // Drawing code
}
*/

@end 

答案 3 :(得分:1)

你有一个非常明显的问题涉及你的dealloc方法:[super dealloc];必须在实现结束时调用,否则之后的行将尝试访问已经解除分配的内存空间(ivar空间),因此它将崩溃。

对于另一个问题,我不确定将活动监视器作为一般按钮的子视图是一个好主意......

答案 4 :(得分:-1)

你真的不想继承UIButton。它是一个类集群,因此单个实​​例将类似于UIRoundRectButton或其他一些私有Apple类。你想做什么,需要一个子类?