UI基础

UIButton简单封装

  1. 第一步简单封装一个button按钮

    /**
    *  创建添加按钮
    *
    *  @param image        按钮图片
    *  @param highImage    高亮状态下的图片
    *  @param disableImage 禁用状态下的图片
    *  @param frame        位置和尺寸
    *  @param action       监听按钮点击事件
    */
    - (void)addButtonWithImage:(NSString *) image highImage:(NSString *)highImage disableImage:(NSString *)disableImage frame:(CGRect)frame action:(SEL)action {
     // 创建按钮
     UIButton * btn = [[UIButton alloc] init];
     // 设置背景图片
     [btn setBackgroundImage:[UIImage imageNamed:image] forState:UIControlStateNormal];
     [btn setBackgroundImage:[UIImage imageNamed:highImage] forState:UIControlStateHighlighted];
     [btn setBackgroundImage:[UIImage imageNamed:disableImage] forState:UIControlStateDisabled];
     // 设置尺寸
     btn.frame = frame;
     // 监听按钮点击事件
     [btn addTarget:self action:action forControlEvents:UIControlEventTouchUpInside];
     // 添加按钮
     [self.view addSubview:btn];
    }
    
  2. 在viewDidLoad中调用

- (void)viewDidLoad {
    [super viewDidLoad];

    [self addButtonWithImage:@"add" highImage:@"add_highlighted" disableImage:@"add_disabled" frame:CGRectMake(30, 30, 50, 50) action:@selector(add)];
    [self addButtonWithImage:@"remove" highImage:@"remove_highlighted" disableImage:@"remove_disabled" frame:CGRectMake(270, 30, 50, 50) action:@selector(remove)];


}

结果如图所示 两张简单的图片展示,但是主要是用了一个最简单的封装,方便多次调用,避免重复造轮子。

  1. 实现button中两个监听方法
#pragma mark 添加
- (void)add {
    NSLog(@"add---");
}

#pragma mark 删除
- (void)remove {
    NSLog(@"remove--");
}

这样第一个简单的UI程序就写出来了


方法总结 - UIButton中常用的方法

  • [btn setBackgroundImage:<#(nullable UIImage *)#> forState:<#(UIControlState)#>]; // 设置button上背景图片,有多中不同的状态
    
  • [btn setTitle:<#(nullable NSString *)#> forState:<#(UIControlState)#>]; // 设置button上的字体 ,有多种不同的状态,默认文字是在右边,图片在左边
    
  • [btn setImage:<#(nullable UIImage *)#> forState:<#(UIControlState)#>]; // 设置button上的图片,哟多种不同的状态,默认图片在左边
    

UIButton再次封装

  1. 添加add方法
- (void)add {
    // 添加图片
    UIImageView *iconView = [[UIImageView alloc] init];
    iconView.image = [UIImage imageNamed:@"danjianbao"];
    iconView.frame = CGRectMake(0, 0, 50, 70);
    [self.shopsView addSubview:iconView];

    // 添加文字
    UILabel *label = [[UILabel alloc] init];
    label.text = @"单肩包";
    label.frame = CGRectMake(0, 50, 50, 20);
    label.font = [UIFont systemFontOfSize:10];
    label.textAlignment = NSTextAlignmentCenter;
    [self.shopsView addSubview:label];
}
  • 点击add按钮之后出现的效果 此时无论点击多少次都只会有这个一个效果,因为我们已经在add方法内部写死了他的位置和尺寸

  • 我们需要重新改进add方法 解决思路为,每次点击添加之后计算位置,假设每行有4个商品,每次点击商品数量+1 , 每次点击添加之后当前商品的索引为其控件中的所有子控件 例如:当前shopsView中有5件商品,那么点击之后的商品数量应该为6个,其商品下表为index=5,根据这个思路我们可以继续下面的步骤了(注:每次商品跟商品名称同时出现,我们可以将之封装在同一个view上)

- (void)add {
    // 商品的大小
    CGFloat shopW = 50;
    CGFloat shopH = 70;

    // 每行商品有5个
    int cols = 5;

    // 每行商品间距
    CGFloat rowMargin = 10;
    // 每列商品间距
    CGFloat colMargin = (self.shopsView.bounds.size.width - shopW * cols)/(cols - 1);

    // 单一商品容器
    UIView * shopView = [[UIView alloc] init];

    // 商品索引
    NSUInteger index = self.shopsView.subviews.count;
    // 商品索引x值
    NSUInteger shopIndexX = index % cols;
    // 商品索引y值
    NSUInteger shopIndexY = index / cols;

    //商品x,y坐标
    CGFloat shopX = shopIndexX * (colMargin + shopW);
    CGFloat shopY = shopIndexY * (rowMargin + shopH);

    // 设置商品容器frame
    shopView.frame = CGRectMake(shopX, shopY, shopW, shopH);
    [self.shopsView addSubview:shopView];

    // 添加图片
    UIImageView *iconView = [[UIImageView alloc] init];
    iconView.image = [UIImage imageNamed:@"danjianbao"];
    iconView.frame = CGRectMake(0, 0, shopW, shopH);
    [shopView addSubview:iconView];

    // 添加文字
    UILabel *label = [[UILabel alloc] init];
    label.text = @"单肩包";
    label.frame = CGRectMake(0, shopW, shopW, shopH - shopW);
    label.font = [UIFont systemFontOfSize:10];
    label.textAlignment = NSTextAlignmentCenter;
    [shopView addSubview:label];
}

注意:其中商品容器 shopView添加到self.shopsView上这一步骤需要在计算商品索引之后进行,否则会出现添加商品第一位空缺的情况。

UIButton封装数据存储

思考:每次我使用在shopsView中放数据,都需要重新设置一个UIImageView以及一个UILabel.我们可以将之封装到一个单独的shopView中,然后导入shopView 头文件来使用它。而且一般我们使用这些数据的时候都是从服务器下载,一般下载的格式都是字典形式。

我们可以改进代码

//
//  ViewController.m
//  01-UI基础
//
//  Created by 王加祥 on 16/4/10.
//  Copyright © 2016年 Wangjiaxiang. All rights reserved.
//

#import "ViewController.h"

@interface ViewController ()

/** 图片仓库 */
@property (nonatomic,strong) UIView * shopsView;

/** 添加按钮 */
@property (nonatomic,weak) UIButton * addBtn;

/** 删除按钮 */
@property (nonatomic,weak) UIButton * removeBtn;

/** 商品数据 */
@property (nonatomic,strong) NSArray * shops;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // 数据
    self.shops = @[
                        @{
                            @"icon":@"danjianbao",
                            @"name":@"单肩包"
                            },
                        @{
                            @"icon":@"liantiaobao",
                            @"name":@"聊天包"
                            },
                        @{
                            @"icon":@"shubao",
                            @"name":@"包"
                            },
                        @{
                            @"icon":@"danjianbao",
                            @"name":@"单肩包"
                            },
                        @{
                            @"icon":@"danjianbao",
                            @"name":@"单肩包"
                            },
                        @{
                            @"icon":@"danjianbao",
                            @"name":@"单肩包"
                            }

                        ];


    [self.view addSubview:self.shopsView];
    self.addBtn = [self addButtonWithImage:@"add" highImage:@"add_highlighted" disableImage:@"add_disabled" frame:CGRectMake(30, 30, 50, 50) action:@selector(add)];
    self.removeBtn = [self addButtonWithImage:@"remove" highImage:@"remove_highlighted" disableImage:@"remove_disabled" frame:CGRectMake(270, 30, 50, 50) action:@selector(remove)];
    self.removeBtn.enabled = NO; // 刚进来的时候商品为空,此控件为禁用状态、


}

/**
 *  创建添加按钮
 *
 *  @param image        按钮图片
 *  @param highImage    高亮状态下的图片
 *  @param disableImage 禁用状态下的图片
 *  @param frame        位置和尺寸
 *  @param action       监听按钮点击事件
 */
- (UIButton *)addButtonWithImage:(NSString *) image highImage:(NSString *)highImage disableImage:(NSString *)disableImage frame:(CGRect)frame action:(SEL)action {
    // 创建按钮
    UIButton * btn = [[UIButton alloc] init];
    // 设置背景图片

    [btn setBackgroundImage:[UIImage imageNamed:image] forState:UIControlStateNormal];
    [btn setBackgroundImage:[UIImage imageNamed:highImage] forState:UIControlStateHighlighted];
    [btn setBackgroundImage:[UIImage imageNamed:disableImage] forState:UIControlStateDisabled];
    // 设置尺寸
    btn.frame = frame;
    // 监听按钮点击事件
    [btn addTarget:self action:action forControlEvents:UIControlEventTouchUpInside];
    // 添加按钮
    [self.view addSubview:btn];

    return btn;
}

#pragma mark 添加
- (void)add {
    // 商品的大小
    CGFloat shopW = 50;
    CGFloat shopH = 70;

    // 每行商品有5个
    int cols = 5;

    // 每行商品间距
    CGFloat rowMargin = 10;
    // 每列商品间距
    CGFloat colMargin = (self.shopsView.bounds.size.width - shopW * cols)/(cols - 1);

    // 单一商品容器
    UIView * shopView = [[UIView alloc] init];

    // 商品索引
    NSUInteger index = self.shopsView.subviews.count;
    // 商品索引x值
    NSUInteger shopIndexX = index % cols;
    // 商品索引y值
    NSUInteger shopIndexY = index / cols;

    //商品x,y坐标
    CGFloat shopX = shopIndexX * (colMargin + shopW);
    CGFloat shopY = shopIndexY * (rowMargin + shopH);

    // 设置商品容器frame
    shopView.frame = CGRectMake(shopX, shopY, shopW, shopH);
    [self.shopsView addSubview:shopView];


    // 添加图片
    UIImageView *iconView = [[UIImageView alloc] init];

    iconView.image = [UIImage imageNamed:self.shops[index][@"icon"]];
    iconView.frame = CGRectMake(0, 0, shopW, shopH);
    [shopView addSubview:iconView];

    // 添加文字
    UILabel *label = [[UILabel alloc] init];
    label.text = self.shops[index][@"name"];
    label.frame = CGRectMake(0, shopW, shopW, shopH - shopW);
    label.font = [UIFont systemFontOfSize:10];
    label.textAlignment = NSTextAlignmentCenter;
    [shopView addSubview:label];
    [self btnState];
}

#pragma mark 删除
- (void)remove {
    [self.shopsView.subviews.lastObject removeFromSuperview];
    [self btnState];
}

#pragma mark - layzingLoad
- (UIView *)shopsView {
    if (_shopsView == nil) {
        _shopsView = [[UIView alloc] init];
        _shopsView.frame = CGRectMake(10, 100, 400, 400);
    }
    return _shopsView;
}

#pragma mark 按钮状态
- (void)btnState {
    self.removeBtn.enabled = (self.shopsView.subviews.count != 0);
    self.addBtn.enabled = (self.shopsView.subviews.count != self.shops.count);
}
@end

说明

  • 首先将数据抽离出来,在viewDidLoad中加载,这样就只加载一次,不用每次都要加载。
  • 将封装的button中接口返回button用来设置每次每个不同状态下的button的状态
  • 设置按钮状态 当self.shopsView.subviews.count != 0的时候此时删除按钮是禁用状态 同理可设定添加按钮
  • 将设置按钮状态抽离出一个单独的方法 改进之后的效果如图

设置提示按钮

当商品添加结束或者是商品完全删除,我们友好的界面应该是给用户提示,我们可以直接设置label来给用户提示,直接上代码

//
//  ViewController.m
//  01-UI基础
//
//  Created by 王加祥 on 16/4/10.
//  Copyright © 2016年 Wangjiaxiang. All rights reserved.
//

#import "ViewController.h"

@interface ViewController ()

/** 图片仓库 */
@property (nonatomic,strong) UIView * shopsView;

/** 添加按钮 */
@property (nonatomic,weak) UIButton * addBtn;

/** 删除按钮 */
@property (nonatomic,weak) UIButton * removeBtn;

/** 商品数据 */
@property (nonatomic,strong) NSArray * shops;

/** HUD */
@property (nonatomic,strong) UILabel * label;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // 数据
    self.shops = @[
                        @{
                            @"icon":@"danjianbao",
                            @"name":@"单肩包"
                            },
                        @{
                            @"icon":@"liantiaobao",
                            @"name":@"聊天包"
                            },
                        @{
                            @"icon":@"shubao",
                            @"name":@"包"
                            },
                        @{
                            @"icon":@"danjianbao",
                            @"name":@"单肩包"
                            },
                        @{
                            @"icon":@"danjianbao",
                            @"name":@"单肩包"
                            },
                        @{
                            @"icon":@"danjianbao",
                            @"name":@"单肩包"
                            }

                        ];


    [self.view addSubview:self.shopsView];
    [self.view addSubview:self.label];
    self.label.alpha = 0;
    self.addBtn = [self addButtonWithImage:@"add" highImage:@"add_highlighted" disableImage:@"add_disabled" frame:CGRectMake(30, 30, 50, 50) action:@selector(add)];
    self.removeBtn = [self addButtonWithImage:@"remove" highImage:@"remove_highlighted" disableImage:@"remove_disabled" frame:CGRectMake(270, 30, 50, 50) action:@selector(remove)];
    self.removeBtn.enabled = NO;


}

/**
 *  创建添加按钮
 *
 *  @param image        按钮图片
 *  @param highImage    高亮状态下的图片
 *  @param disableImage 禁用状态下的图片
 *  @param frame        位置和尺寸
 *  @param action       监听按钮点击事件
 */
- (UIButton *)addButtonWithImage:(NSString *) image highImage:(NSString *)highImage disableImage:(NSString *)disableImage frame:(CGRect)frame action:(SEL)action {
    // 创建按钮
    UIButton * btn = [[UIButton alloc] init];
    // 设置背景图片

    [btn setBackgroundImage:[UIImage imageNamed:image] forState:UIControlStateNormal];
    [btn setBackgroundImage:[UIImage imageNamed:highImage] forState:UIControlStateHighlighted];
    [btn setBackgroundImage:[UIImage imageNamed:disableImage] forState:UIControlStateDisabled];
    // 设置尺寸
    btn.frame = frame;
    // 监听按钮点击事件
    [btn addTarget:self action:action forControlEvents:UIControlEventTouchUpInside];
    // 添加按钮
    [self.view addSubview:btn];

    return btn;
}

#pragma mark 添加
- (void)add {
    // 商品的大小
    CGFloat shopW = 50;
    CGFloat shopH = 70;

    // 每行商品有5个
    int cols = 5;

    // 每行商品间距
    CGFloat rowMargin = 10;
    // 每列商品间距
    CGFloat colMargin = (self.shopsView.bounds.size.width - shopW * cols)/(cols - 1);

    // 单一商品容器
    UIView * shopView = [[UIView alloc] init];

    // 商品索引
    NSUInteger index = self.shopsView.subviews.count;
    // 商品索引x值
    NSUInteger shopIndexX = index % cols;
    // 商品索引y值
    NSUInteger shopIndexY = index / cols;

    //商品x,y坐标
    CGFloat shopX = shopIndexX * (colMargin + shopW);
    CGFloat shopY = shopIndexY * (rowMargin + shopH);

    // 设置商品容器frame
    shopView.frame = CGRectMake(shopX, shopY, shopW, shopH);
    [self.shopsView addSubview:shopView];


    // 添加图片
    UIImageView *iconView = [[UIImageView alloc] init];

    iconView.image = [UIImage imageNamed:self.shops[index][@"icon"]];
    iconView.frame = CGRectMake(0, 0, shopW, shopH);
    [shopView addSubview:iconView];

    // 添加文字
    UILabel *label = [[UILabel alloc] init];
    label.text = self.shops[index][@"name"];
    label.frame = CGRectMake(0, shopW, shopW, shopH - shopW);
    label.font = [UIFont systemFontOfSize:10];
    label.textAlignment = NSTextAlignmentCenter;
    [shopView addSubview:label];
    [self btnState];
}

#pragma mark 删除
- (void)remove {
    [self.shopsView.subviews.lastObject removeFromSuperview];
    [self btnState];
}

#pragma mark - layzingLoad
- (UIView *)shopsView {
    if (_shopsView == nil) {
        _shopsView = [[UIView alloc] init];
        _shopsView.frame = CGRectMake(10, 100, 400, 400);
    }
    return _shopsView;
}

- (UILabel *)label {
    if (_label == nil) {
        _label = [[UILabel alloc] init];
        _label.frame = CGRectMake(0, 300, 400, 20);
        _label.textAlignment = NSTextAlignmentCenter;
    }
    return _label;
}

#pragma mark 按钮状态
- (void)btnState {
    self.removeBtn.enabled = (self.shopsView.subviews.count != 0);
    self.addBtn.enabled = (self.shopsView.subviews.count != self.shops.count);

    if (self.removeBtn.enabled == NO) {
        self.label.alpha = 1;
        self.label.text = @"没有东西可删除了";

        /**
         *  隐藏HUD
         *  @selector(hideHUD) 调用方法å
         *  withObject : 传入参数
         *  afterDelay :多长时间之后调用
         */
//        [self performSelector:@selector(hideHUD) withObject:nil afterDelay:1.5];

        /**  多线程方法调用 */
//        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
//            
//            self.label.alpha = 0.0;
//        });

        /**
         *  定时器调用方法
         */
        [NSTimer scheduledTimerWithTimeInterval:1.5 target:self selector:@selector(hideHUD) userInfo:nil repeats:NO];
    } else if (self.addBtn.enabled == NO) {
        self.label.alpha = 1;
        self.label.text = @"没有东西可添加了";
        [self performSelector:@selector(hideHUD) withObject:nil afterDelay:1.5];
    }
}

/**
 *  隐藏HUD
 */

- (void)hideHUD {

    self.label.alpha = 0.0;
}
@end
  • 首先在self.view 中添加一个label,我们用懒加载的方式来实现
  • 半透明HUD,将背景颜色设置为半透明
  • 设置label的显示可以有两种方法,一种是设置透明度,一种是直接隐藏,还有一种可以直接删除(在本工程中我们不提倡)
  • 设置label提示之后需要隐藏 有三种方法
    1. [self performSelector:@selector(hideHUD) withObject:nil afterDelay:1.5];
      
    1. 
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            self.label.alpha = 0.0;
        });
      
    1. [NSTimer scheduledTimerWithTimeInterval:1.5 target:self selector:@selector(hideHUD) userInfo:nil repeats:NO];
      
  • 项目中添加的所有资源都会在主资源包中
  • 项目中有出现一个类无法顶底的错误,可能是没有加载到资源包中。需要在target Build Phases 中Compile Sources 检查是否加入

封装模型

新建一个类,继承NSObject,模型累不结构改变的时候外部调用方法不需要改变

  • 新建Shop类
//
//  Shop.h
//  01-UI基础
//
//  Created by 王加祥 on 16/4/10.
//  Copyright © 2016年 Wangjiaxiang. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface Shop : NSObject
/** 商品图片 */
@property (nonatomic,strong) NSString * icon;
/** 商品名称 */
@property (nonatomic,strong) NSString * name;

/** 类方法:直接将字典传入参数 */
+ (instancetype)shopWithDictionary:(NSDictionary *)dict;
/** 对象方法:直接将字典传入参数 */
- (instancetype)initWithDictionary:(NSDictionary *)dict;
@end
//  Shop.m
//  01-UI基础
//
//  Created by 王加祥 on 16/4/10.
//  Copyright © 2016年 Wangjiaxiang. All rights reserved.
//

#import "Shop.h"

@implementation Shop

+ (instancetype)shopWithDictionary:(NSDictionary *)dict {

    return [[self alloc] initWithDictionary:dict];
}

- (instancetype)initWithDictionary:(NSDictionary *)dict {
    if (self = [super init]) {
        self.name = dict[@"name"];
        self.icon = dict[@"icon"];
    }
    return self;
}
@end

使用方法就是将字典直接转为模型。

改进add方法

 - (void)add {
    // 商品的大小
    CGFloat shopW = 50;
    CGFloat shopH = 70;

    // 每行商品有5个
    int cols = 5;

    // 每行商品间距
    CGFloat rowMargin = 10;
    // 每列商品间距
    CGFloat colMargin = (self.shopsView.bounds.size.width - shopW * cols)/(cols - 1);

    // 单一商品容器
    UIView * shopView = [[UIView alloc] init];

    // 商品索引
    NSUInteger index = self.shopsView.subviews.count;
    // 商品索引x值
    NSUInteger shopIndexX = index % cols;
    // 商品索引y值
    NSUInteger shopIndexY = index / cols;

    //商品x,y坐标
    CGFloat shopX = shopIndexX * (colMargin + shopW);
    CGFloat shopY = shopIndexY * (rowMargin + shopH);

    // 设置商品容器frame
    shopView.frame = CGRectMake(shopX, shopY, shopW, shopH);
    [self.shopsView addSubview:shopView];

    Shop * shop = self.shops[index];


    // 添加图片
    UIImageView *iconView = [[UIImageView alloc] init];

    iconView.image = [UIImage imageNamed:shop.icon];
    iconView.frame = CGRectMake(0, 0, shopW, shopH);
    [shopView addSubview:iconView];

    // 添加文字
    UILabel *label = [[UILabel alloc] init];
    label.text = shop.name;
    label.frame = CGRectMake(0, shopW, shopW, shopH - shopW);
    label.font = [UIFont systemFontOfSize:10];
    label.textAlignment = NSTextAlignmentCenter;
    [shopView addSubview:label];
    [self btnState];
}

重写懒加载数组方法

- (NSArray *)shops {
    if (_shops == nil) {
        // 加载数据
        NSString * file = [[NSBundle mainBundle] pathForResource:@"shops" ofType:@"plist"];
        _shops = [NSArray arrayWithContentsOfFile:file];

        NSMutableArray * shopArray = [NSMutableArray array];
        for (NSDictionary * dict  in _shops) {
            Shop * shop = [Shop shopWithDictionary:dict];
            [shopArray addObject:shop];
        }
        _shops = shopArray;
    }
    return _shops;
}

这样整个项目就暂时封装完成

results matching ""

    No results matching ""