QRadioButton实现详解

来源:互联网 发布:开淘宝店要注册公司吗 编辑:程序博客网 时间:2024/06/05 19:57

QRadioButton实现了按钮单选的操作,如下图:


源代码如下:

////  EIRadioButton.h//  EInsure////  Created by ivan on 13-7-9.//  Copyright (c) 2013年 ivan. All rights reserved.//#import <UIKit/UIKit.h>@protocol QRadioButtonDelegate;@interface QRadioButton : UIButton {    NSString                        *_groupId;    BOOL                            _checked;    id<QRadioButtonDelegate>       _delegate;}@property(nonatomic, assign)id<QRadioButtonDelegate>   delegate;@property(nonatomic, copy, readonly)NSString            *groupId;@property(nonatomic, assign)BOOL checked;- (id)initWithDelegate:(id)delegate groupId:(NSString*)groupId;@end@protocol QRadioButtonDelegate <NSObject>@optional- (void)didSelectedRadioButton:(QRadioButton *)radio groupId:(NSString *)groupId;@end

////  EIRadioButton.m//  EInsure////  Created by ivan on 13-7-9.//  Copyright (c) 2013年 ivan. All rights reserved.//#import "QRadioButton.h"#define Q_RADIO_ICON_WH                     (16.0)#define Q_ICON_TITLE_MARGIN                 (5.0)static NSMutableDictionary *_groupRadioDic = nil;@implementation QRadioButton@synthesize delegate = _delegate;@synthesize checked  = _checked;- (id)initWithDelegate:(id)delegate groupId:(NSString*)groupId {    self = [super init];    if (self) {        _delegate = delegate;        _groupId = [groupId copy];                [self addToGroup];                self.exclusiveTouch = YES;        //        [self setImage:[UIImage imageNamed:@"radio_unchecked.png"] forState:UIControlStateNormal];//        [self setImage:[UIImage imageNamed:@"radio_checked.png"] forState:UIControlStateSelected];        [self setImage:[UIImage imageNamed:@"order_type_unselected"] forState:UIControlStateNormal];        [self setImage:[UIImage imageNamed:@"order_type_selected"] forState:UIControlStateSelected];        [self addTarget:self action:@selector(radioBtnChecked) forControlEvents:UIControlEventTouchUpInside];    }    return self;}- (void)addToGroup {    if(!_groupRadioDic){        _groupRadioDic = [[NSMutableDictionary dictionary] retain];    }        NSMutableArray *_gRadios = [_groupRadioDic objectForKey:_groupId];    if (!_gRadios) {        _gRadios = [NSMutableArray array];    }    [_gRadios addObject:self];    [_gRadios addObject:self];        [_groupRadioDic setObject:_gRadios forKey:_groupId];}- (void)removeFromGroup {    if (_groupRadioDic) {        NSMutableArray *_gRadios = [_groupRadioDic objectForKey:_groupId];        if (_gRadios) {            [_gRadios removeObject:self];            if (_gRadios.count == 0) {                [_groupRadioDic removeObjectForKey:_groupId];            }        }    }}- (void)uncheckOtherRadios {    NSMutableArray *_gRadios = [_groupRadioDic objectForKey:_groupId];    if (_gRadios.count > 0) {        for (QRadioButton *_radio in _gRadios) {            if (_radio.checked && ![_radio isEqual:self]) {                _radio.checked = NO;            }        }    }}- (void)setChecked:(BOOL)checked {    if (_checked == checked) {        return;    }        _checked = checked;    self.selected = checked;        if (self.selected) {        [self uncheckOtherRadios];    }        if (self.selected && _delegate && [_delegate respondsToSelector:@selector(didSelectedRadioButton:groupId:)]) {        [_delegate didSelectedRadioButton:self groupId:_groupId];    }}- (void)radioBtnChecked {    if (_checked) {        return;    }        self.selected = !self.selected;    _checked = self.selected;        if (self.selected) {        [self uncheckOtherRadios];    }        if (self.selected && _delegate && [_delegate respondsToSelector:@selector(didSelectedRadioButton:groupId:)]) {        [_delegate didSelectedRadioButton:self groupId:_groupId];            }}- (CGRect)imageRectForContentRect:(CGRect)contentRect {    return CGRectMake(0, (CGRectGetHeight(contentRect) - Q_RADIO_ICON_WH)/2.0, Q_RADIO_ICON_WH, Q_RADIO_ICON_WH);}- (CGRect)titleRectForContentRect:(CGRect)contentRect {    return CGRectMake(Q_RADIO_ICON_WH + Q_ICON_TITLE_MARGIN, 0,                      CGRectGetWidth(contentRect) - Q_RADIO_ICON_WH - Q_ICON_TITLE_MARGIN,                      CGRectGetHeight(contentRect));}- (void)dealloc {    [self removeFromGroup];        _delegate = nil;    [_groupId release];    _groupId = nil;    [super dealloc];}@end

下面简单介绍一下其实现:

1.源码中static NSMutableDictionary *_groupRadioDic 用于存储按钮组,这需要注意两点:一是使用了static,二是使用了字典类型。static为全局变量生命周期和应用程序一样,这样可以保证我们创建的单选按钮组在内存中,便于设置状态使用。由字典的特性可以知道,当设置对象时同一个key再次设置值的时候第二次设置的值会覆盖第一次的值,这样保证了每个按钮组在字典中只有一份,而且是最新的。

2._groupRadioDic存储的实际是按钮组的数组,即是具有相同groupId的一组按钮。源码中可以看出:

NSMutableArray *_gRadios = [_groupRadioDic objectForKey:_groupId];    if (!_gRadios) {        _gRadios = [NSMutableArray array];    }    [_gRadios addObject:self];    [_gRadios addObject:self];        
3.按钮的图片和文字的显示问题:众所周知,UIButton的setImage方法设置的图片会覆盖整个UIButton,然后setTitle设置的title就会与突变重合。为了达到图片和文字左右分开显示,源码中复写了父类的方法:

- (CGRect)imageRectForContentRect:(CGRect)contentRect {    return CGRectMake(0, (CGRectGetHeight(contentRect) - Q_RADIO_ICON_WH)/2.0, Q_RADIO_ICON_WH, Q_RADIO_ICON_WH);}- (CGRect)titleRectForContentRect:(CGRect)contentRect {    return CGRectMake(Q_RADIO_ICON_WH + Q_ICON_TITLE_MARGIN, 0,                      CGRectGetWidth(contentRect) - Q_RADIO_ICON_WH - Q_ICON_TITLE_MARGIN,                      CGRectGetHeight(contentRect));}


0 0