zoukankan      html  css  js  c++  java
  • 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:方法
    • 通过xibstoryboard创建
    • 初始化时不会调用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:@"购物车已空,赶紧买买买啦!"];

        }

  • 相关阅读:
    输出由“*”组成的菱形
    一个简单的计算器(c++)
    输入学号,显示对应的姓名(c++)
    使用 Puppet 在 Windows Azure 中配备 Linux 和 Windows 环境
    微软开放技术发布针对 Mac 和 Linux 的更新版 Azure Node.JS SDK 和命令行工具
    微软开放技术开发了适用于 Windows Azure 移动服务的开源 Android SDK
    微软开放技术发布开源 Jenkins 插件以将 Windows Azure Blob 服务用的开作存储库
    VM Depot 登陆中国!
    VM Depot 喜迎中国本土开源镜像!
    VM Depot 助您使用本地开源软件架设开发 Web 站点
  • 原文地址:https://www.cnblogs.com/zhoudaquan/p/4996275.html
Copyright © 2011-2022 走看看