IOS开发学习笔记Day5-IOC基础二
九宫格位置算法
假设九宫格九个按钮的位置平均分布在一个空间中。
计算方式:x = (控件宽度+控件间距)*(控件下标 % 控件列数)
例如:第一列第一个x值计算 = 间距 * 0%1
,第三列第二排第三个(下标是5):x = 间距 * 5%3
y轴同理可以计算出。
UIButton
// 1.1 创建按钮对象
// UIButton *button = [[UIButton alloc] init];
// 注意:设置按钮的类型只能在初始化的时候设置 -> UIButtonTypeCustom
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
// 1.2 设置按钮的类型
// button.buttonType = UIButtonTypeInfoDark;
// 1.3 设置frame
button.frame = CGRectMake(100, 100, 170, 60);
// 1.4 设置背景颜色
//button.backgroundColor = [UIColor redColor];
//[button setBackgroundColor:[UIColor redColor]];
// 1.5 设置文字
// 分状态的:
// button.titleLabel.text = @"普通文字";
[button setTitle:@"普通按钮" forState:UIControlStateNormal];
[button setTitle:@"高亮按钮" forState:UIControlStateHighlighted];
// 1.6 设置文字的颜色
[button setTitleColor:[UIColor greenColor] forState:UIControlStateNormal];
[button setTitleColor:[UIColor yellowColor] forState:UIControlStateHighlighted];
// 1.7 设置文字的阴影颜色
[button setTitleShadowColor:[UIColor blackColor] forState:UIControlStateNormal];
[button setTitleShadowColor:[UIColor whiteColor] forState:UIControlStateHighlighted];
button.titleLabel.shadowOffset = CGSizeMake(3, 2);
// 1.8 设置内容图片
[button setImage:[UIImage imageNamed:@"player_btn_pause_normal"] forState:UIControlStateNormal];
[button setImage:[UIImage imageNamed:@"player_btn_pause_highlight"] forState:UIControlStateHighlighted];
// button.imageView.backgroundColor = [UIColor purpleColor];
// 1.9 设置背景图片
[button setBackgroundImage:[UIImage imageNamed:@"buttongreen"] forState:UIControlStateNormal];
[button setBackgroundImage:[UIImage imageNamed:@"buttongreen_highlighted"] forState:UIControlStateHighlighted];
/**
* 监听按钮的点击
* Target: 目标 (让谁做事情)
* action: 方法 (做什么事情-->方法)
* Events: 事件
*/
// SEL sel = @selector(clickButton:);
[button addTarget:self action:@selector(demo:) forControlEvents:UIControlEventTouchUpInside];
自定义控件
步骤:
- 新建类继承于UIView
- 重写控件的layoutSubviews方法(可以获取控件的宽高属性)
例如:CGFloat width = self.frame.size.width;
- 在构造方法中创建子视图,并添加进自己容器中。
设置内边距
//1.设置内容
self.button.contentEdgeInsets = UIEdgeInsetsMake(-20, 0, 0, 0);
// 2.设置图片
self.button.imageEdgeInsets = UIEdgeInsetsMake(0, 0, 0, 0);
// 3.设置标题
self.button.titleEdgeInsets = UIEdgeInsetsMake(0, 0, 0, -10);
使用xib文件创建自定义控件
- 新建xib文件
- 属性面板中size属性选择freefrom(可以自由拖拽控件大小,也可以通过属性面板设置控件大小)
- 设置状态栏(属性面板中,状态栏设置为none)
- 向xib文件中拖入控件
- 代码提取xib中的控件,并设置到屏幕中
方式一
UIView *carView = [[[NSBundle mainBundle] loadNibNamed:@"CarView" owner:nil options:nil] firstObject];
carView.frame = CGRectMake(0, 100, 200, 50);
// carView.clipsToBounds = YES;
[self.view addSubview:carView];
方式二
UINib *nib = [UINib nibWithNibName:@"CarView" bundle:nil];
UIView *carView = [[nib instantiateWithOwner:nil options:nil] firstObject];
[self.view addSubview:carView];
xib使用注意事项
1> 如果一个view从xib中加载,就不能用[xxx alloc] init] 和 [xxx alloc] initWithFrame:]创建
2> 如果一个xib经常被使用,应该提供快速构造类方法
3> 如果一个view从xib中加载:
用代码添加一些子控件,得在 initWithCoder: 和 awakeFromNib 创建
4> 如果一个view从xib中加载,会调用initWithCoder: 和 awakeFromNib,不会调用init和initWithFrame:方法
总结:xib自定义控件封装,需要继承于UIView ,重写其中initWithCoder方法和awakeFromNib方法。前者做初始化操作,后者做子控件初始化操作。因为xib加载完后,子控件处于未唤醒状态,所以在initWithCoder中操作子控件无效。
渐变动画
平移
// 1. 开始动画
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:1.0];
// 2.动画代码
CGRect frame = self.animationView.frame;
frame.origin.y -= 50;
self.animationView.frame = frame;
// 3.提交动画
[UIView commitAnimations];
方式二:
2.1方式一
[UIView animateWithDuration:2.0 animations:^{
// 1.动画代码
CGRect frame = self.animationView.frame;
frame.origin.y -= 50;
self.animationView.frame = frame;
}];
2.2方式二
[UIView animateWithDuration:1.0 animations:^{
// 执行动画
CGRect frame = self.animationView.frame;
frame.origin.y -= 50;
self.animationView.frame = frame;
} completion:^(BOOL finished) {
// 动画完成做什么事情
self.animationView.backgroundColor = [UIColor blackColor];
}];
2.3,动画模式
UIViewAnimationOptionCurveEaseInOut 动画开始/结束比较缓慢,中间相对较快
UIViewAnimationOptionCurveEaseIn 动画开始比较缓慢
UIViewAnimationOptionCurveEaseOut 动画结束比较缓慢
UIViewAnimationOptionCurveLinear 线性---> 匀速
[UIView animateWithDuration:1.0 delay:1.0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
CGRect frame = self.animationView.frame;
frame.origin.y += 50;
self.animationView.frame = frame;
} completion:^(BOOL finished) {
self.animationView.backgroundColor = [UIColor greenColor];
}];
缩放动画
[UIView animateWithDuration:1.0 delay:1.0 options:UIViewAnimationOptionCurveEaseIn animations:^{
CGRect frame = self.animationView.frame;
frame.size = CGSizeMake(10, 15);
self.animationView.frame = frame;
} completion:^(BOOL finished) {
NSLog(@"动画完成");
}];
透明度动画
[UIView animateWithDuration:1.0 delay:0.5 options:UIViewAnimationOptionCurveEaseOut animations:^{
self.animationView.alpha -= 0.9;
} completion:^(BOOL finished) {
[UIView animateWithDuration:2.0 animations:^{
self.animationView.alpha += 0.9;
}];
}];
图像拉伸问题处理
resizableImageWithCapInsets
1.1 创建UIImage对象
UIImage *image = [UIImage imageNamed:@"chat_send_nor"];
// 1.2 拿到image的尺寸
CGFloat imageWidth = image.size.width;
CGFloat imageHeight = image.size.height;
// 1.3 返回一张受保护而且拉伸的图片 --->CapInsets:哪些地方要保护
UIImage *resizableImage = [image resizableImageWithCapInsets:UIEdgeInsetsMake(imageHeight * 0.5, imageWidth * 0.5, imageHeight * 0.5 -1, imageWidth * 0.5 - 1)];
//使用mode resizingMode
//UIImageResizingModeTile, 平铺
//UIImageResizingModeStretch, 拉伸(伸缩)
UIImage *resizableImage = [image resizableImageWithCapInsets:UIEdgeInsetsMake(imageHeight * 0.5, imageWidth * 0.5, imageHeight * 0.5 -1, imageWidth * 0.5 - 1) resizingMode:UIImageResizingModeTile];
stretchableImageWithLeftCapWidth
1.1 创建UIImage对象
UIImage *image = [UIImage imageNamed:@"chat_send_nor"];
// 1.2 拿到image的尺寸
CGFloat imageWidth = image.size.width;
CGFloat imageHeight = image.size.height;
// 1.3 返回一张受保护而且拉伸的图片
// 右边需要保护的区域 = 图片的width - leftCapWidth - 1
// 底部需要保护的区域 = height - topCapHeight - 1
UIImage *resizableImage = [image stretchableImageWithLeftCapWidth:imageWidth * 0.5 topCapHeight:imageHeight * 0.5];
使用类扩展解决图片拉伸问题
UIImage+XMGExtention.h
#import <UIKit/UIKit.h>
@interface UIImage (XMGExtention)
/**
* 返回一张受保护的图片(被拉伸的)
*/
+ (instancetype)resizableImageWithLocalImageName: (NSString *)localImageName;
@end
UIImage+XMGExtention.m
#import "UIImage+XMGExtention.h"
@implementation UIImage (XMGExtention)
+ (instancetype)resizableImageWithLocalImageName:(NSString *)localImageName{
// 创建图片对象
UIImage *image = [UIImage imageNamed:localImageName];
// 获取图片的尺寸
CGFloat imageWidth = image.size.width;
CGFloat imageHeiht = image.size.height;
// 返回一张拉伸且受保护的图片
return [image stretchableImageWithLeftCapWidth:imageWidth * 0.5 topCapHeight:imageHeiht * 0.5 ];
}
@end
可以直接使用受保护的图片
UIImage *image = [UIImage resizableImageWithLocalImageName:@"chat_send_nor"];
通过Xcode工具解决拉伸问题
步骤:
1->选中资源包中的图片。
2->找到属性面板中的slicing属性
3->设置保护区域即可
kvc(对象访问修改器)
简单使用kvc
XMGPerson *person = [[XMGPerson alloc] init];
//常规赋值
person.name = @"张三";
person.age = 18;
// KVC赋值
[person setValue:@"王五" forKey:@"name"];
[person setValue:@"19" forKeyPath:@"age"]; // 自动类型转换
利用KVC修改类的私有成员变量
XMGPerson *person = [[XMGPerson alloc] init];
//person->_age//私有变量,会报错
[person printAge];
[person setValue:@"88" forKeyPath:@"_age"]; // age _age
[person printAge];
使用字典转对象
作用: 字典转模型
开发中是不建议使用setValuesForKeysWithDictionary:
1> 字典中的key必须在模型的属性中找到
2> 如果模型中带有模型,setValuesForKeysWithDictionary不好使
应用场景: 简单的字典转模型
XMGPerson *person = [[XMGPerson alloc] initWithDict:dict];
NSLog(@"%@", person.dog.class);
[person setValue: @{
@"name" : @"wangcai",
@"price" : @8
} forKeyPath:@"dog"];
kvc给内部对象赋值
XMGPerson *person = [[XMGPerson alloc] init];
person.dog = [[XMGDog alloc] init];
person.dog.name = @"旺财";
// KVC赋值
forKey和forKeyPath
1>forKeyPath 包含了所有 forKey 的功能
2>forKeyPath 进行内部的点语法,层层访问内部的属性
3>注意: key值一定要在属性中找到
[person.dog setValue:@"阿黄" forKey:@"name"];
[person setValue:@"旺财" forKeyPath:@"dog.name"];
使用kvc取值
XMGPerson *person = [[XMGPerson alloc] init];
person.name = @"张三";
person.money = 12332;
// 利用kvc取值
NSLog(@"%@ --- %.2f", [person valueForKeyPath:@"name"], [[person valueForKey:@"money"] floatValue]);
模型转字典
XMGPerson *person = [[XMGPerson alloc] init];
person.name = @"lurry";
person.money = 21.21;
NSDictionary *dict = [person dictionaryWithValuesForKeys:@[@"name", @"money"]];
NSLog(@"%@", dict);
使用kvc取出数组对象中的某个属性
NSArray *allPersons = @[person1, person2, person3];
NSArray *allPersonName = [allPersons valueForKeyPath:@"name"];
NSLog(@"%@", allPersonName);
kvo(对象监听器)
KVO: Key Value Observing (键值监听)—>当某个对象的属性值发生改变的时候(用KVO监听)
XMGPerson *person = [[XMGPerson alloc] init];
person.name = @"zs";
/*
作用:给对象绑定一个监听器(观察者),当监听的属性值发生改变会调用**observeValueForKeyPath**方法。所以需要重写该方法!
- Observer 观察者
- KeyPath 要监听的属性
- options 选项(方法方法中拿到属性值)
*/
[person addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];
person.name = @"ww";
// 移除监听
[person removeObserver:self forKeyPath:@"name"];
属性监听器实现
/**
* 当监听的属性值发生改变
*
* @param keyPath 要改变的属性
* @param object 要改变的属性所属的对象
* @param change 改变的内容
* @param context 上下文
*/
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context{
NSLog(@"%@------%@------%@", keyPath, object, change);
}