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中对它进行转换赋值;
时间: 2024-10-03 23:04:21

IOS开发基础知识--碎片18的相关文章

iOS开发基础知识--碎片13

 iOS开发基础知识--碎片13 1:运行程序报the file couldn't be opened because you don't have permission to view it 解决办法:项目—>targets->build settings->build options->changed the value of the "Compiler for C/C++/Objective-C" to Default Compiler. 2:百度地图引用

iOS开发基础知识--碎片8

iOS开发基础知识--碎片8  1:用UIImageView作为背景,但直接把按钮或者 UITextField放在上面无法相应事件. 解决办法:UIImageView默认的UserInteractionEnabled是NO,把它修改成YES,或者可以直接在XCODE上面的view有个属性勾选User Interaction Enabled 遇到的场景(在滚动视图里面放一个图片视图,在图片视图上又放置一个按键,发现一直没有响应效果); 2:AFnetWorking报"Request failed:

iOS开发基础知识--碎片32

 iOS开发基础知识--碎片32 1:动画属性UIViewAnimationOptions说明 a:常规动画属性设置(可以同时选择多个进行设置) UIViewAnimationOptionLayoutSubviews:动画过程中保证子视图跟随运动. UIViewAnimationOptionAllowUserInteraction:动画过程中允许用户交互. UIViewAnimationOptionBeginFromCurrentState:所有视图从当前状态开始运行. UIViewAnimat

iOS开发基础知识--碎片1

iOS开发基础知识--碎片1  一:NSString与NSInteger的互换 NSInteger转化NSString类型:[NSString stringWithFormat: @"%d", NSInteger]; NSString转化 NSInteger类型:NSInteger = [NSString intValue]; *其它几个同理 [NSString boolValue].[NSString floatValue].[NSString doubleValue] 二:Obje

iOS开发基础知识--碎片3

iOS开发基础知识--碎片3  iOS开发基础知识--碎片3 十二:判断设备 //设备名称 return [UIDevice currentDevice].name; //设备型号,只可得到是何设备,无法得到是第几代设备 return [UIDevice currentDevice].model; //系统版本型号,如iPhone OS return [UIDevice currentDevice].systemVersion; //系统版本名称,如6.1.3 return [UIDevice

iOS开发基础知识--碎片2

iOS开发基础知识--碎片2 六:获得另一个控件器,并实现跳转 UIStoryboard* mainStoryboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil]; UIViewController *registerViewController = [mainStoryboard instantiateViewControllerWithIdentifier:@"registerView

iOS开发基础知识--碎片23

iOS开发基础知识--碎片23  1:关于UITableView中关于行重复加载的问题 在Cell里重写prepareForReuse,对一些控件进行清空: 比较简单: -(void)prepareForReuse{ [super prepareForReuse]; _content_label.text = nil; _time_date_label.text = nil; _name_label.text = nil; _career_label.text = nil; } 下面这个是我在c

iOS开发基础知识--碎片21

iOS开发基础知识--碎片21  1:[UIScreen mainScreen].scale知识点 当屏幕分别为640x940时[[UIScreen mainScreen] scale]=2.0 当屏幕分别为320x480时[[UIScreen mainScreen] scale]=1.0 2:如何正确的绘制1像素的线 #define SINGLE_LINE_WIDTH (1 / [UIScreen mainScreen].scale) #define SINGLE_LINE_ADJUST_OF

iOS开发基础知识--碎片24

 iOS开发基础知识--碎片24 1:兼容字体大小6plue跟它以下的区别 #define FONT_COMPATIBLE_SCREEN_OFFSET(_fontSize_) [UIFont systemFontOfSize:(_fontSize_ *([UIScreen mainScreen].scale) / 2)] 在iPhone4~6中,缩放因子scale=2:在iPhone6+中,缩放因子scale=3 运用时: myLabel.font=FONT_COMPATIBLE_SCREEN_