功能需求
实现一个图片浏览器,点击左右按钮可以切换背景图,且更新背景图对应的索引页和图片描述内容。
分析:
- 实现一个UIView的子类即可,该子类包含多个按钮。
实现步骤:
-
使用OC语言,故创建cocoa Touch类型文件。Xcode会创建.h文件和.m文件:PicBrowserDemo类。
-
图片资源导入:注意图片不要重名
注意各项的类型:Root是Array,其余是Dictionary
-
实现该类。
该类带有多个控件,令其继承UIView。
a. 声明类的成员变量:在.h文件中定义:,类型是strong。
该图片浏览器需要两个可显示文字内容但不可修改的Label、两个前后图片切换的按钮以及承载图片的视图。
在.h 文件中:
@interface PicBrowserDemo : UIView
@property(strong, nonatomic) UIImageView *imageView;
@property(strong, nonatomic) UILabel *label1;
@property(strong, nonatomic) UILabel *label2;
@property(strong, nonatomic) UIButton *btn1;
@property(strong, nonatomic) UIButton *btn2;
@end
b. 创建plist类型文件,直接在项目下创建,plist文件属于resource类型文件,在该栏目下可找到。
选择root类型为Array,而每个元素设置为字典,因为每个字典中存图片的名称和title(描述)。
c. .m 文件:
// 1 plist:
信息填写
// 2 初始化各个组件,显示的信息以第一张为基准
// 3 nxt
// 4 pre
// 5 降低冗余,合并:pre、nxt函数
#import "PicBrowserDemo.h"
// 写私有属性:在这里
@interface PicBrowserDemo()
// assign、strong的区别: asign表示基本类型的变量
@property(nonatomic, strong) NSArray *pic;
@property(nonatomic, assign) int index;
@end
// 从plist中读取到的各图片信息集合
@implementation PicBrowserDemo
-(instancetype) initWithFrame:(CGRect)frame{
self = [super initWithFrame:frame];
if(self){
// 初始化5个组件
_imageView = [[UIImageView alloc] initWithFrame:CGRectMake(80, 230, 150, 150)];
// 图片模式:放入如何显示的 按比例缩放,不会拉伸变形
_imageView.contentMode = UIViewContentModeScaleAspectFit;
// 初始化为pic中第一张图片
NSDictionary *dict = self.pic[0];
_imageView.image = [UIImage imageNamed:dict[@"icon"]];
// 固定值写法:
//_imageView.image = [UIImage imageNamed:@"i1.png"];
// label1:
_label1 = [[UILabel alloc] initWithFrame:CGRectMake(80, 190, 150, 40)];
_label2 = [[UILabel alloc] initWithFrame:CGRectMake(80, 380, 150, 40)];
// text填内容
_label1.text = [NSString stringWithFormat:@"%d/%ld", 1, self.pic.count];
// 下面的label填入title
_label2.text = dict[@"title"];
// 填充方式fill
_label1.textAlignment = NSTextAlignmentCenter;
_label2.textAlignment = NSTextAlignmentCenter;
// btn1
_btn1 = [[UIButton alloc] initWithFrame:CGRectMake(30, 300, 50, 50)];
_btn2 = [[UIButton alloc] initWithFrame:CGRectMake(230, 300, 50, 50)];
// btn1
[_btn1 setBackgroundImage:[UIImage imageNamed:@"zuo1.jpg"] forState:UIControlStateNormal];
// btn2
[_btn2 setBackgroundImage:[UIImage imageNamed:@"you1.png"] forState:UIControlStateNormal];
// 绑定点击向前和向后
[_btn1 addTarget:self action:@selector(changePages:) forControlEvents:UIControlEventTouchUpInside];
//
[_btn2 addTarget:self action:@selector(changePages:) forControlEvents:UIControlEventTouchUpInside];
// [_btn1 addTarget:self action:@selector(pre) forControlEvents:UIControlEventTouchUpInside];
// //
// [_btn2 addTarget:self action:@selector(nxt) forControlEvents:UIControlEventTouchUpInside];
//
// 用tags区分该切换前一张还是后一张
_btn1.tag = 1;
_btn2.tag = 2;
[self addSubview: _imageView];
[self addSubview: _btn1];
[self addSubview: _btn2];
[self addSubview: _label1];
[self addSubview: _label2];
}
return self;
}
// 重写属性pic的get方法懒加载:
/* 第一次调用一定为空,加载即可
*/
- (NSArray *) pic{
if(_pic == nil){
// 获取plist的文件路径
// nsBundle:获取手机上软件的安装路径,而非项目路径
NSString *path = [[NSBundle mainBundle] pathForResource:@"pics" ofType:@"plist"];
// 读取文件
NSArray *array = [NSArray arrayWithContentsOfFile:path];
NSLog(@"count:%ld", array.count);
_pic = array;
}
return _pic;
}
// 不需要参数:
- (void) changePages:(UIButton *)sender{
switch (sender.tag) {
case 1:
_index--;
break;
case 2:
_index++;
break;
}
NSDictionary *dict = self.pic[self.index];
// 上面的label填入页码
_label1.text = [NSString stringWithFormat:@"%d/%ld", self.index+1, self.pic.count];
// 下面的label填入title
_label2.text = dict[@"title"];
// 图片框填入图片:
_imageView.image = [UIImage imageNamed:dict[@"icon"]];
// 如果已经到了最后一张,则按钮切换为不允许点
// 索引为末尾-1,则设置下一张按钮为不可点击
// 没必要通过图片来设置,通过yes、no设置即可达到所需的灰色状态
// 两条必须同时设置:否则会出现 翻到底再返回时,向右按钮仍然灰色
self.btn2.enabled = !(_pic.count -1 == _index);
self.btn1.enabled = !(0 == _index);
}
// 加索引:
- (void) nxt{
_index++;
NSDictionary *dict = self.pic[self.index];
// 上面的label:填入序号
_label1.text = [NSString stringWithFormat:@"%d/%ld", self.index+1, self.pic.count];
// 下面的label:填入标题
_label2.text = dict[@"title"];
// 图片框填入图片:
_imageView.image = [UIImage imageNamed:dict[@"icon"]];
// 如果已经到了最后一张,则按钮切换为不允许点
// 索引为末尾-1,则设置下一张按钮为不可点击
// 没必要通过图片来设置,通过yes、no设置即可达到所需的灰色状态
self.btn2.enabled = !(_pic.count -1 == _index);
self.btn1.enabled = !(0 == _index);
}
//
- (void) pre{
_index--;
NSDictionary *dict = self.pic[self.index];
// 上面的label:填入序号
_label1.text = [NSString stringWithFormat:@"%d/%ld", self.index+1, self.pic.count];
// 下面的label:填入标题
_label2.text = dict[@"title"];
// 图片框填入图片:
_imageView.image = [UIImage imageNamed:dict[@"icon"]];
// 如果为0,则设置向左不可点击且更换图片
self.btn1.enabled = !(0 == _index);
self.btn2.enabled = !(_pic.count -1 == _index);
}
@end
调用入口:
- (void)viewDidLoad {
[super viewDidLoad];
//[self test_Common_arrtibute];
[self testPicBrowser];
}
-(void) testPicBrowser{
PicBrowserDemo *browserView = [[PicBrowserDemo alloc] initWithFrame:CGRectMake(50, 80, 300 ,700)];
//[browserView setBackgroundColor: [UIColor blueColor]];
[self.view addSubview:browserView];
}
- 效果展示
- 首页只可向右
- 尾页只可向左
要注意的问题以及犯错
- 关于懒加载:
设置变量同名的函数,实则为setter,判断变量指向为空,则做初始化获取操作,后续再利用都不需要,此为懒加载方式。
- 关于plist加载:
使用bundle接口,, 通过plist文件名即可,该底层原理是使用了安装APP后的文件结构来获取文件,而非运行工程的目录结构。
- plist总是读取为空
我的plist获取方式是读取Array接口,而我的plist中root设置为dictionary类型,因此接口不对应,获取错误了。改root为array类型即可。
- 初始化index报错
switch中,tag为2是向右点击,所以应该index++。
- 图片浏览器初始化:
按pic第一张的图片和title初始化即可。