1:initWithFrame方法的理解
1. initWithFrame方法是什么?initWithFrame方法用來(lái)初始化并返回一個(gè)新的視圖對(duì)象,根據(jù)指定的CGRect(尺寸)。當(dāng)然,其他UI對(duì)象,也有initWithFrame方法,但是,我們以UIView為例,來(lái)搞清楚initWithFrame方法。2.什么時(shí)候用initWithFrame方法?簡(jiǎn)單的說(shuō),我們用編程方式申明,創(chuàng)建UIView對(duì)象時(shí),使用initWithFrame方法。在此,我們必須搞清楚,兩種方式來(lái)進(jìn)行初始化UIView。a.使用 Interface Builder 方式。這種方式,就是使用nib文件。通常我們說(shuō)的“拖控件” 的方式。實(shí)際編程中,我們?nèi)绻肐nterface Builder 方式創(chuàng)建了UIView對(duì)象。(也就是,用拖控件的方式)那么,initWithFrame方法方法是不會(huì)被調(diào)用的。因?yàn)閚ib文件已經(jīng)知道如何初始化該View。(因?yàn)椋覀冊(cè)谕显搗iew的時(shí)候,就定義好了長(zhǎng)、寬、背景等屬性)。這時(shí)候,會(huì)調(diào)用initWithCoder方法,我們可以用initWithCoder方法來(lái)重新定義我們?cè)趎ib中已經(jīng)設(shè)置的各項(xiàng)屬性。b.使用編程方式。就是我們聲明一個(gè)UIView的子類,進(jìn)行“手工”編寫(xiě)代碼的方式。實(shí)際編程中,我們使用編程方式下,來(lái)創(chuàng)建一個(gè)UIView或者創(chuàng)建UIView的子類。這時(shí)候,將調(diào)用initWithFrame方法,來(lái)實(shí)例化UIView。特別注意,如果在子類中重載initWithFrame方法,必須先調(diào)用父類的initWithFrame方法。在對(duì)自定義的UIView子類進(jìn)行初始化操作。比如:- (id)initWithFrame:(CGRect)frame{ self = [super initWithFrame:frame];// 先調(diào)用父類的initWithFrame方法 if (self) { // 再自定義該類(UIView子類)的初始化操作。 _scrollView = [[UIScrollView alloc] initWithFrame:self.bounds]; [_scrollView setFrame:CGRectMake(0, 0, 320, 480)]; _scrollView.contentSize = CGSizeMake(320*3, 480); [self addSubview:_scrollView]; } return self;}
2:layoutSubviews總結(jié)
layoutSubviews在以下情況下會(huì)被調(diào)用:a、init初始化不會(huì)觸發(fā)layoutSubviews 但是是用initWithFrame 進(jìn)行初始化時(shí),當(dāng)rect的值不為CGRectZero時(shí),也會(huì)觸發(fā)b、addSubview會(huì)觸發(fā)layoutSubviewsc、設(shè)置view的Frame會(huì)觸發(fā)layoutSubviews,當(dāng)然前提是frame的值設(shè)置前后發(fā)生了變化d、滾動(dòng)一個(gè)UIScrollView會(huì)觸發(fā)layoutSubviewse、旋轉(zhuǎn)Screen會(huì)觸發(fā)父UIView上的layoutSubviews事件f、改變一個(gè)UIView大小的時(shí)候也會(huì)觸發(fā)父UIView上的layoutSubviews事件layoutSubviews, 當(dāng)我們?cè)谀硞€(gè)類的內(nèi)部調(diào)整子視圖位置時(shí),需要調(diào)用。反過(guò)來(lái)的意思就是說(shuō):如果你想要在外部設(shè)置subviews的位置,就不要重寫(xiě)。layoutSubviews對(duì)subviews重新布局,layoutSubviews方法調(diào)用先于drawRect刷新子對(duì)象布局-layoutSubviews方法:這個(gè)方法,默認(rèn)沒(méi)有做任何事情,需要子類進(jìn)行重寫(xiě)-setNeedsLayout方法: 標(biāo)記為需要重新布局,異步調(diào)用layoutIfNeeded刷新布局,不立即刷新,但layoutSubviews一定會(huì)被調(diào)用-layoutIfNeeded方法:如果,有需要刷新的標(biāo)記,立即調(diào)用layoutSubviews進(jìn)行布局(如果沒(méi)有標(biāo)記,不會(huì)調(diào)用layoutSubviews)如果要立即刷新,要先調(diào)用[view setNeedsLayout],把標(biāo)記設(shè)為需要布局,然后馬上調(diào)用[view layoutIfNeeded],實(shí)現(xiàn)布局在視圖第一次顯示之前,標(biāo)記總是“需要刷新”的,可以直接調(diào)用[view layoutIfNeeded]
3:單元行有其它控件時(shí),行選中時(shí)關(guān)于控件高亮的問(wèn)題
此處是cell中的accessoryView放一UIButton,在行被選中的情況下,UIButton同時(shí)也被高亮處于被選中的壯態(tài),通過(guò)下面這樣處理可以解決問(wèn)題@interface UCaiTableViewCell : UITableViewCell@end@implementation UCaiTableViewCell@synthesize piosaDelegate = _piosaDelegate;- (void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated{ [super setHighlighted:highlighted animated:animated]; if (highlighted) { [(UIButton *)self.accessoryView setHighlighted:NO]; }}- (void)setSelected:(BOOL)selected animated:(BOOL)animated{ [super setSelected:selected animated:animated]; if (selected) { [(UIButton *)self.accessoryView setHighlighted:NO]; }}
4:UIButton高亮效果去除
繼承UIButton然后可以重寫(xiě)setHighlighed方法,里面什么內(nèi)容也不寫(xiě);.H文件:#import <UIKit/UIKit.h>@interface HWEmotionTabBarButton : UIButton@end.M文件:#import "HWEmotionTabBarButton.h"@implementation HWEmotionTabBarButton- (id)initWithFrame:(CGRect)frame{ self = [super initWithFrame:frame]; if (self) { // 設(shè)置文字顏色 [self setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; [self setTitleColor:[UIColor darkGrayColor] forState:UIControlStateDisabled]; // 設(shè)置字體 self.titleLabel.font = [UIFont systemFontOfSize:13]; } return self;}- (void)setHighlighted:(BOOL)highlighted { // 按鈕高亮所做的一切操作都不在了}@end
5:一個(gè)選項(xiàng)卡的封裝
.H文件內(nèi)容#import <UIKit/UIKit.h>typedef enum { HWEmotionTabBarButtonTypeRecent, // 最近 HWEmotionTabBarButtonTypeDefault, // 默認(rèn) HWEmotionTabBarButtonTypeEmoji, // emoji HWEmotionTabBarButtonTypeLxh, // 浪小花} HWEmotionTabBarButtonType;@class HWEmotionTabBar;@PRotocol HWEmotionTabBarDelegate <NSObject>@optional- (void)emotionTabBar:(HWEmotionTabBar *)tabBar didSelectButton:(HWEmotionTabBarButtonType)buttonType;@end@interface HWEmotionTabBar : UIView@property (nonatomic, weak) id<HWEmotionTabBarDelegate> delegate;@end注意:這邊主要是要引入@class.M文件內(nèi)容:@interface HWEmotionTabBar()@property (nonatomic, weak) HWEmotionTabBarButton *selectedBtn;@end@implementation HWEmotionTabBar- (id)initWithFrame:(CGRect)frame{ self = [super initWithFrame:frame]; if (self) { [self setupBtn:@"最近" buttonType:HWEmotionTabBarButtonTypeRecent]; [self setupBtn:@"默認(rèn)" buttonType:HWEmotionTabBarButtonTypeDefault];// [self btnClick:[self setupBtn:@"默認(rèn)" buttonType:HWEmotionTabBarButtonTypeDefault]]; [self setupBtn:@"Emoji" buttonType:HWEmotionTabBarButtonTypeEmoji]; [self setupBtn:@"浪小花" buttonType:HWEmotionTabBarButtonTypeLxh]; } return self;}/** * 創(chuàng)建一個(gè)按鈕 * * @param title 按鈕文字 */- (HWEmotionTabBarButton *)setupBtn:(NSString *)title buttonType:(HWEmotionTabBarButtonType)buttonType{ // 創(chuàng)建按鈕 HWEmotionTabBarButton *btn = [[HWEmotionTabBarButton alloc] init]; [btn addTarget:self action:@selector(btnClick:) forControlEvents:UIControlEventTouchDown]; btn.tag = buttonType; [btn setTitle:title forState:UIControlStateNormal]; [self addSubview:btn]; // 設(shè)置背景圖片 NSString *image = @"compose_emotion_table_mid_normal"; NSString *selectImage = @"compose_emotion_table_mid_selected"; if (self.subviews.count == 1) { image = @"compose_emotion_table_left_normal"; selectImage = @"compose_emotion_table_left_selected"; } else if (self.subviews.count == 4) { image = @"compose_emotion_table_right_normal"; selectImage = @"compose_emotion_table_right_selected"; } [btn setBackgroundImage:[UIImage imageNamed:image] forState:UIControlStateNormal]; [btn setBackgroundImage:[UIImage imageNamed:selectImage] forState:UIControlStateDisabled]; return btn;}- (void)layoutSubviews{ [super layoutSubviews]; // 設(shè)置按鈕的frame NSUInteger btnCount = self.subviews.count; CGFloat btnW = self.width / btnCount; CGFloat btnH = self.height; for (int i = 0; i<btnCount; i++) { HWEmotionTabBarButton *btn = self.subviews[i]; btn.y = 0; btn.width = btnW; btn.x = i * btnW; btn.height = btnH; }}- (void)setDelegate:(id<HWEmotionTabBarDelegate>)delegate{ _delegate = delegate; // 選中“默認(rèn)”按鈕 [self btnClick:(HWEmotionTabBarButton *)[self viewWithTag:HWEmotionTabBarButtonTypeDefault]];}/** * 按鈕點(diǎn)擊 */- (void)btnClick:(HWEmotionTabBarButton *)btn{ //轉(zhuǎn)換被選中的效果 self.selectedBtn.enabled = YES; btn.enabled = NO; self.selectedBtn = btn; // 通知代理 if ([self.delegate respondsToSelector:@selector(emotionTabBar:didSelectButton:)]) { [self.delegate emotionTabBar:self didSelectButton:btn.tag]; }}@end注意:當(dāng)增加完控件后,self.subviews.count這個(gè)值就是從1開(kāi)始,而setDelegate則是為了用來(lái)顯示默認(rèn)被選中,因?yàn)橛忻杜e所以可以很準(zhǔn)確定位到想設(shè)置默認(rèn)的那個(gè)UIButton,UIControlStateDisabled這個(gè)狀態(tài)是為了當(dāng)被選中后就不能再點(diǎn)擊,配合著enabled設(shè)置,代碼中創(chuàng)建的一個(gè)屬性用于存放當(dāng)前被選中的UIButton,在事件btnClick中對(duì)它進(jìn)行轉(zhuǎn)換賦值;
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注