iOS开发基础知识--碎片18
1:initWithFrame方法的理解
1. initWithFrame方法是什么? initWithFrame方法用来初始化并返回一个新的视图对象,根据指定的CGRect(尺寸)。 当然,其他UI对象,也有initWithFrame方法,但是,我们以UIView为例,来搞清楚initWithFrame方法。 2.什么时候用initWithFrame方法? 简单的说,我们用编程方式申明,创建UIView对象时,使用initWithFrame方法。 在此,我们必须搞清楚,两种方式来进行初始化UIView。 a.使用 Interface Builder 方式。 这种方式,就是使用nib文件。通常我们说的“拖控件” 的方式。 实际编程中,我们如果用Interface Builder 方式创建了UIView对象。(也就是,用拖控件的方式) 那么,initWithFrame方法方法是不会被调用的。因为nib文件已经知道如何初始化该View。(因为,我们在拖该view的时候,就定义好了长、宽、背景等属性)。 这时候,会调用initWithCoder方法,我们可以用initWithCoder方法来重新定义我们在nib中已经设置的各项属性。 b.使用编程方式。 就是我们声明一个UIView的子类,进行“手工”编写代码的方式。 实际编程中,我们使用编程方式下,来创建一个UIView或者创建UIView的子类。这时候,将调用initWithFrame方法,来实例化UIView。 特别注意,如果在子类中重载initWithFrame方法,必须先调用父类的initWithFrame方法。在对自定义的UIView子类进行初始化操作。 比如: - (id)initWithFrame:(CGRect)frame{ self = [super initWithFrame:frame];// 先调用父类的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总结
layoutSubviews在以下情况下会被调用: a、init初始化不会触发layoutSubviews 但是是用initWithFrame 进行初始化时,当rect的值不为CGRectZero时,也会触发 b、addSubview会触发layoutSubviews c、设置view的Frame会触发layoutSubviews,当然前提是frame的值设置前后发生了变化 d、滚动一个UIScrollView会触发layoutSubviews e、旋转Screen会触发父UIView上的layoutSubviews事件 f、改变一个UIView大小的时候也会触发父UIView上的layoutSubviews事件 layoutSubviews, 当我们在某个类的内部调整子视图位置时,需要调用。反过来的意思就是说:如果你想要在外部设置subviews的位置,就不要重写。layoutSubviews对subviews重新布局,layoutSubviews方法调用先于drawRect 刷新子对象布局 -layoutSubviews方法:这个方法,默认没有做任何事情,需要子类进行重写 -setNeedsLayout方法: 标记为需要重新布局,异步调用layoutIfNeeded刷新布局,不立即刷新,但layoutSubviews一定会被调用 -layoutIfNeeded方法:如果,有需要刷新的标记,立即调用layoutSubviews进行布局(如果没有标记,不会调用layoutSubviews) 如果要立即刷新,要先调用[view setNeedsLayout],把标记设为需要布局,然后马上调用[view layoutIfNeeded],实现布局 在视图第一次显示之前,标记总是“需要刷新”的,可以直接调用[view layoutIfNeeded]
3:单元行有其它控件时,行选中时关于控件高亮的问题
此处是cell中的accessoryView放一UIButton,在行被选中的情况下,UIButton同时也被高亮处于被选中的壮态,通过下面这样处理可以解决问题 @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然后可以重写setHighlighed方法,里面什么内容也不写; .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) { // 设置文字颜色 [self setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; [self setTitleColor:[UIColor darkGrayColor] forState:UIControlStateDisabled]; // 设置字体 self.titleLabel.font = [UIFont systemFontOfSize:13]; } return self; } - (void)setHighlighted:(BOOL)highlighted { // 按钮高亮所做的一切操作都不在了 } @end
5:一个选项卡的封装
.H文件内容 #import <UIKit/UIKit.h> typedef enum { HWEmotionTabBarButtonTypeRecent, // 最近 HWEmotionTabBarButtonTypeDefault, // 默认 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文件内容: @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:@"默认" buttonType:HWEmotionTabBarButtonTypeDefault]; // [self btnClick:[self setupBtn:@"默认" buttonType:HWEmotionTabBarButtonTypeDefault]]; [self setupBtn:@"Emoji" buttonType:HWEmotionTabBarButtonTypeEmoji]; [self setupBtn:@"浪小花" buttonType:HWEmotionTabBarButtonTypeLxh]; } return self; } /** * 创建一个按钮 * * @param title 按钮文字 */ - (HWEmotionTabBarButton *)setupBtn:(NSString *)title buttonType:(HWEmotionTabBarButtonType)buttonType { // 创建按钮 HWEmotionTabBarButton *btn = [[HWEmotionTabBarButton alloc] init]; [btn addTarget:self action:@selector(btnClick:) forControlEvents:UIControlEventTouchDown]; btn.tag = buttonType; [btn setTitle:title forState:UIControlStateNormal]; [self addSubview:btn]; // 设置背景图片 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]; // 设置按钮的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; // 选中“默认”按钮 [self btnClick:(HWEmotionTabBarButton *)[self viewWithTag:HWEmotionTabBarButtonTypeDefault]]; } /** * 按钮点击 */ - (void)btnClick:(HWEmotionTabBarButton *)btn { //转换被选中的效果 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 注意:当增加完控件后,self.subviews.count这个值就是从1开始,而setDelegate则是为了用来显示默认被选中,因为有枚举所以可以很准确定位到想设置默认的那个UIButton,UIControlStateDisabled这个状态是为了当被选中后就不能再点击,配合着enabled设置,代码中创建的一个属性用于存放当前被选中的UIButton,在事件btnClick中对它进行转换赋值;