UIView之基础控件综合事例
九宫格算法实现及优化
2015年11月19日 星期四
23:21
1.九宫格之初实现
要求:
1.1在主界面中,点击添加按钮就能添加商品,点击删除按钮就能删除商品;
1.2在初始化界面中,添加按钮处于norma状态,删除按钮处于disable状态;
1.3当点击了添加按钮后,删除按钮此时处于normal状态;
1.4当商品满了后,添加按钮处于disable状态,删除按钮处于normal状态;
1.5当商品为空或者满了的时候给出提示语;
算法思路实现:
1.界面的实现:分析要用到的控件,此需求中,用到了一个view(主控件)和(内部的子控件)一个imageView,两个lable(显示title和hub),两个button(添加和删除按钮).
2.因为要对按钮和view实现操作,所以对其进行引用(获得对应的属性和删除添加操作).
3.导入相对应的图片.
4.在addProduct方法中:
4.1依次创建shopView(父控件),用于加载imageView和title,并添加到主控件中;
3.1.1分别创建imageView和title并设置frame加载到shopView中
4.2此时就需要考虑到加载的商品个数,所以引入商品的信息,用字典存储,并获得index.
4.3在定义frame的时候,考虑到程序中的魔鬼数字,就需要定义一些常量.
4.4加载字典中的icon和name并赋值给相对应的控件imageView和title.
4.5判断按钮的状态,并对enable属性进行相应的设置
5.在removeProduct方法中:
5.1调用[self.shopView.su'b'viewsubviews lastObject]removeFromSuperviews删除商品
5.2判断按钮的状态,并对enable属性进行相应的设置
2.九宫格实现之(字典)懒加载优化
懒加载:
作用:节省内存,当数据字典被使用时候才去使用.防止了在viewDidLoad的时候耗费内存和时间.
实现:首先就得在声明语句中声明一个数组用来保存字典中的数据.
步骤:
懒加载的步骤
1.定义成员变量
2.重写get方法
3.在get方法中判断,变量是否有值,如果没有值,则加载数据,如果有值,直接返回
- (NSArray *)products
{
if (_products == nil) {
_products = @[
@{@"icon" : @"liantiaobao", @"title" : @"链条包"},
@{@"icon" : @"shoutibao", @"title" : @"手提包"},
@{@"icon" : @"danjianbao", @"title" : @"单肩包"},
@{@"icon" : @"shuangjianbao", @"title" : @"双肩包"},
@{@"icon" : @"xiekuabao", @"title" : @"斜挎包"},
@{@"icon" : @"qianbao", @"title" : @"钱包"}
];
}
return _products;
}
3.九宫格实现之(plist文件)懒加载优化
plist懒加载:
- 3.1什么是plist文件
- 直接将数据直接写在代码里面,不是一种合理的做法。如果数据经常改,就要经常翻开对应的代码进行修改,造成代码扩展性低
- 因此,可以考虑将经常变的数据放在文件中进行存储,程序启动后从文件中读取最新的数据。如果要变动数据,直接修改数据文件即可,不用修改代码
- 一般可以使用属性列表文件存储NSArray或者NSDictionary之类的数据,这种“属性列表文件”的扩展名是plist,因此也称为“plist文件”
- 3.2创建plist文件
3.3解析plist文件
- 接下来通过代码来解析Plist文件中的数据
- 获得Plist文件的全路径
NSBundle *bundle = [NSBundle mainBundle];
NSString *path = [bundle pathForResource:@"shops" ofType:@"plist"];
- 加载plist文件
_shops = [NSArray arrayWithContentsOfFile:path];
3.4plist的使用注意
3.5如何使用懒加载
- 接下来通过代码来解析Plist文件中的数据
- 获得Plist文件的全路径
NSBundle *bundle = [NSBundle mainBundle];
NSString *path = [bundle pathForResource:@"shops" ofType:@"plist"];
- 加载plist文件
_shops = [NSArray arrayWithContentsOfFile:path];
或者可以写成:
_shops = [NSArray arrayWithContentsOfFile:[NSBundle mainBundle]pathForResource:@"shops" ofType:@"plist"]];
4.九宫格实现之模型优化
4.1模型取代字典的好处:
- 使用字典的坏处
- 一般情况下,设置数据和取出数据都使用“字符串类型的key”,编写这些key时,编辑器没有智能提示,需要手敲
dict[@"name"] = @"Jack";
NSString *name = dict[@"name"];
- 手敲字符串key,key容易写错
- Key如果写错了,编译器不会有任何警告和报错,造成设错数据或者取错数据
- 使用模型的好处
- 所谓模型,其实就是数据模型,专门用来存放数据的对象,用它来表示数据会更加专业
- 模型设置数据和取出数据都是通过它的属性,属性名如果写错了,编译器会马上报错,因此,保证了数据的正确性
- 使用模型访问属性时,编译器会提供一系列的提示,提高编码效率
app.name = @"Jack";
NSString *name = app.name;
4.2.实现:
4.2.1.创建一个类模型,并声明相应的属性,用来取代字典,给相应的子控件赋值
4.2.2在懒加载中实现下面的方法:
// 问题:_products数组中存放的都是字典,字典在实际开发使用起来并不是方便
// 3.将字典转成模型对象
NSMutableArray *tempArray = [NSMutableArray array];
for (NSDictionary *dict in _products) {
// 3.1.创建模型对象
Product *product = [[Product alloc] init];
// 3.2.给模型对象的属性赋值
product.icon = dict[@"icon"];
product.title = dict[@"title"];
// 3.3.将模型对象放入数组中
[tempArray addObject:product];
}
_products = tempArray;
4.2.3用模型取代字典进行赋值
// 2.6.设置展示的数据
XMGProduct *product = self.products[index];
iconView.image = [UIImage imageNamed:product.icon];
titleLabel.text = product.title;
4.2.4考虑到在懒加载遍历数组的时候,每次创建XMGProduct的时候都得进行赋值,所以就在模型类中提供初始化方法,使得每次创建的模型对象都有对应的属性:
- (instancetype)initWithDict:(NSDictionary *)dict
{
if (self = [super init]) {
self.icon = dict[@"icon"];
self.title = dict[@"title"];
}
return self;
}
+ (instancetype)productWithDict:(NSDictionary *)dict
{
return [[self alloc] initWithDict:dict];
}
在懒加载时进行修改:
// 3.将字典转成模型对象
NSMutableArray *tempArray = [NSMutableArray array];
for (NSDictionary *dict in _products) {
XMGProduct *product = [XMGProduct productWithDict:dict];
// 3.2.将模型对象放入数组中
[tempArray addObject:product];
}
_products = tempArray;
}
5.九宫格实现之添加控件优化
5.1作用:
在UIController中需要每次创建一个shopView,然后添加到主控件view中,所以我们可以自定义控件来取代这种做法.
5.2控件的实现:
首先就是创建一个对应的类XMGProductView,在类中分别声明对应的属性iconView和titleLable,然后重写init类方法;因为无法在init方法中设置frame,所以就必须重写layoutSubviews方法
- (instancetype)init
{
if (self = [super init]) {
// 1.添加UIImageView对象用于显示商品的图片
UIImageView *iconView = [[UIImageView alloc] init];
[self addSubview:iconView];
_iconView = iconView;
// 2.添加UILabel对象用于显示商品的名字
UILabel *titleLabel = [[UILabel alloc] init];
titleLabel.textAlignment = NSTextAlignmentCenter;
[self addSubview:titleLabel];
_titleLabel = titleLabel;
}
return self;
}
- (void)layoutSubviews
{
//注意:必须调用super方法
[super layoutSubviews];
// 1.取出当前控件的宽度和高度
CGFloat width = self.frame.size.width;
CGFloat height = self.frame.size.height;
// 2.调整子控件的frame
self.iconView.frame = CGRectMake(0, 0, width, width);
self.titleLabel.frame = CGRectMake(0, width, width, height - width);
}
考虑到在自定义控件的时候,如果在.h文件中设置对应的属性,那么外界就能通过set和get方法进行修改,为了不让外界修改属性的值,所以必须重写对应的set方法,并统一提供接口.
#pragma mark - 实现接口的方法
- (void)setIcon:(NSString *)iconName
{
self.iconView.image = [UIImage imageNamed:iconName];
}
- (void)setTitle:(NSString *)title
{
self.titleLabel.text = title;
}
在addProduct的方法中,在创建控件并设置数据
/**************** 2.添加商品的View *****************************/
// 1.创建商品的View
XMGProductView *productView = [[XMGProductView alloc] init];
productView.frame = CGRectMake(x, y, width, height);
[self.shopCartView addSubview:productView];
// 2.设置数据
XMGProduct *product = self.products[index];
[productView setIcon:product.icon];
[productView setTitle:product.title];
考虑到为了更加的安全(不让外界了解具体的实现方法),所以又提供了对应的模型方法,只让外界知道模型
- (void)setProduct:(XMGProduct *)product
{
_product = product;
// 设置数据
self.iconView.image = [UIImage imageNamed:product.icon];
self.titleLabel.text = product.title;
}
在addProduct的方法中,在创建控件并设置数据
/********************2.添加商品的View *****************************/
// 1.创建商品的View
XMGProductView *productView = [[XMGProductView alloc] init];
productView.frame = CGRectMake(x, y, width, height);
[self.shopCartView addSubview:productView];
// 2.设置数据
productView.product = self.products[index];
6.九宫格实现之xib优化
6.1Xib和storyboard对比
- 共同点:
- 都用来描述软件界面
- 都用Interface Builder工具来编辑
- 本质都是转换成代码去创建控件
- 不同点
- Xib是轻量级的,用来描述局部的UI界面
- Storyboard是重量级的,用来描述整个软件的多个界面,并且能展示多个界面之间的跳转关系
6.2xib的加载
- 方法1
NSArray *views = [[NSBundle mainBundle] loadNibNamed:@"xib文件名" owner:nil options:nil]
- 方法2
UINib *nib = [UINib nibWithNibName:@"xib文件名" bundle:nil];
NSArray *views = [nib instantiateWithOwner:nil options:nil];
6.3步骤:
6.4注意点
- 一个控件有2种创建方式
- 通过代码创建
- 初始化时一定会调用initWithFrame:方法
- 通过xib\storyboard创建
- 初始化时不会调用initWithFrame:方法,只会调用initWithCoder:方法
- 初始化完毕后会调用awakeFromNib方法
- 有时候希望在控件初始化时做一些初始化操作,比如添加子控件、设置基本属性
- 这时需要根据控件的创建方式,来选择在initWithFrame:、initWithCoder:、awakeFromNib的哪个方法中操作
xib界面的设置:
用xib取代自定义控件的.h文件
#import <UIKit/UIKit.h>
@class XMGProduct;
@interface XMGProductView : UIView
// 快速创建类方法
+ (instancetype)productView;
// 提供模型接口
@property (nonatomic, strong) XMGProduct *product;
@end
用xib取代自定义控件的.m文件
#import "XMGProductView.h"
#import "XMGProduct.h"
@interface XMGProductView ()
@property (weak, nonatomic) IBOutlet UIImageView *iconView;
@property (weak, nonatomic) IBOutlet UILabel *titleLabel;
@end
@implementation XMGProductView
+ (instancetype)productView
{
return [[[NSBundle mainBundle] loadNibNamed:NSStringFromClass(self) owner:nil options:nil] firstObject];
}
- (void)setProduct:(XMGProduct *)product
{
_product = product;
// 给子控件设置数据
self.iconView.image = [UIImage imageNamed:product.icon];
self.titleLabel.text = product.title;
}
@end
在addProduct的方法中,在创建控件并设置数据
/*********************2.添加商品的View *****************************/
// 1.创建商品的View
XMGProductView *productView = [XMGProductView productView];
productView.frame = CGRectMake(x, y, width, height);
[self.shopCartView addSubview:productView];
// 2.设置数据
productView.product = self.products[index];
7.九宫格实现之提示框动画效果优化
考虑到add和remove的提示框的内容除了提示语不同外,其他的都一样,所以就把提示方法抽取出来简洁代码:
注意:hubLabel为view中的提示框的属性
- (void)showHubInfo:(NSString *)hubInfo
{
// 3.1.改变指示器上面显示的文字
self.hubLabel.text = hubInfo;
// 3.2.出现动画和消失动画
[UIView animateWithDuration:1.0 animations:^{
self.hubLabel.alpha = 1.0;
} completion:^(BOOL finished) {
[UIView animateWithDuration:1.0 delay:2.0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
self.hubLabel.alpha = 0.0;
} completion:nil];
}];
}
在addProduct的方法中,调用该方法
/************** 4.购物车已满,给用户提示 *************************/
if (self.shopCartView.subviews.count == 6) {
[self showHubInfo:@"购物车已满,不要买买买啦!"];
}
在removeProduct的方法中,调用该方法
// 3.购物车已空,给用户提示
if (self.shopCartView.subviews.count == 0) {
[self showHubInfo:@"购物车已空,赶紧买买买啦!"];
}
UIView之基础控件综合事例的更多相关文章
- [iOS基础控件 - 5.5] 代理设计模式 (基于”APP列表"练习)
A.概述 在"[iOS基础控件 - 4.4] APP列表 进一步封装,初见MVC模式”上进一步改进,给“下载”按钮加上效果.功能 1.按钮点击后,显示为“已下载”,并且不 ...
- React Native环境搭建以及几个基础控件的使用
之前写了几篇博客,但是没有从最基础的开始写,现在想了想感觉不太合适,所以现在把基础的一些东西给补上,也算是我从零开始学习RN的经验吧! 一.环境搭建 首先声明一下,本人现在用的编辑器是SublimeT ...
- UIView上的控件使用push方法跳转
有时候在项目中,为了保持前后页面的推进方式跳转方式一致,会在通过UIview上的控件跳到另一个Controller上,所以,这时候就需要用到这种方式了,当然,present方法可以实现跳转但是样式可能 ...
- Cocos2d-JS项目之二:studio基础控件的使用
在studio里把几个基础控件往场景文件一拖,然后导出json格式的资源文件 逻辑代码如下: var HelloWorldLayer = cc.Layer.extend({ sprite:null, ...
- [iOS基础控件 - 6.6] 展示团购数据 自定义TableViewCell
A.需求 1.头部广告 2.自定义cell:含有图片.名称.购买数量.价格 3.使用xib设计自定义cell,自定义cell继承自UITableViewCell 4.尾部“加载更多按钮”,以及其被点击 ...
- [iOS基础控件 - 4.5] 猜图游戏
A.需要掌握的 1.添加图片资源(暂时认为@2x跟非@2x代表同一张图片) 2.搭建UI界面* 文本标签* 4个按钮* 中间的图片 3.设置状态栏样式 4.监听下一题按钮的点击 5.延迟加载数据* 加 ...
- [iOS基础控件 - 1] UI概念
A. UIView 1.概念 属于UIKit框架 屏幕上能看得见摸得着的东西就是UIView,比如屏幕上的按钮.文字.图片 翻译为:视图/控件/组件 UIBut ...
- Delphi一共封装(超类化)了8种Windows基础控件和17种复杂控件
超类化源码: procedure TWinControl.CreateSubClass(var Params: TCreateParams; ControlClassName: PChar); con ...
- Cocos2d-JS studio基础控件的使用
在studio里把几个基础控件往场景文件一拖,然后导出json格式的资源文件 逻辑代码如下: 1 var HelloWorldLayer = cc.Layer.extend({ 2 sprite:nu ...
随机推荐
- ajax同步,异步
传输数据 同步:第一条传过去,对方接收到反馈以后,再传第二条; 异步:第一条传过去,不管对方有没有收到,继续传第二条. ajax(默认异步 async:true) 同步:执行完ajax内部代码,才执行 ...
- FileReader 基本介绍
转自:http://blog.csdn.net/zk437092645/article/details/8745647 用来把文件读入内存,并且读取文件中的数据.FileReader接口提供了一个异步 ...
- Spring入门学习(一)
SpringMVC基础平台补充(2016.03.03) 如果想要开发SpringMVC,那么前期依次安装好:JDK(jdk-8u74-windows-x64,安装后配置环境变量JAVA_HOME和CL ...
- Servlet Filter 1
1.Filter简介 )Filter也称之为过滤器,它是Servlet技术中最实用的技术,WEB开发人员通过Filter技术,对web服务器管理的所有web资源:例如Jsp, Servlet, 静态图 ...
- linux 解压,源码包
从网络上下载到的源码包, 最常见的是 .tar.gz 包, 还有一部分是 .tar.bz2包 要解压很简单 : .tar.gz 格式解压为 tar -zxvf ...
- LeetCode "Minimum Height Tree" !!
Simple data structure but not that easy to figure out.. MHT -> balanced tree.https://leetcode.com ...
- 安卓集成发布详解(二)gradle
转自:http://frank-zhu.github.io/android/2015/06/15/android-release_app_build_gradle/ 安卓集成发布详解(二) 15 Ju ...
- php返回状态200或者300的写法
header("HTTP/1.0 200 OK"); phpinfo(); header("HTTP/1.0 300 OK"); phpinfo();
- Django数据库操作
刚学到Django的数据库操作,把它记录下来,方便以后查看: 在Django中定义数据库表,并使用Django提供的方法来对数据库进行操作(增.删.改.查) 1.定义3个数据库表: class Gro ...
- 黄聪:如何添加360浏览器(chrome)添加JavaScript例外,禁止网站加载JS
注意:通配符两侧的[]不能省略