IOS开发基础—简单的qq表情排列app

作者声明

因个人能力问题,文中不免有错误之处,欢迎各位读者交流,批评,指正!

摘要

本文通过一个实例:将qq表情按不同的列排序,并实现表情添加功能,学习控件segment的基本用法。

实例

viewController h代码

//
//  ViewController.h
//  简单的表情排列app
//
//  Created by dqw on 15/5/7.
//  Copyright (c) 2015年 itcast. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController

@property (weak, nonatomic) IBOutlet UIView *iconsView;

@property (weak, nonatomic) IBOutlet UISegmentedControl *segment;

- (IBAction)setColumns:(UISegmentedControl *)sender;


@end

viewController m代码

//
//  ViewController.m
//  简单的表情排列app
//
//  Created by dqw on 15/5/7.
//  Copyright (c) 2015年 itcast. All rights reserved.
//

#import "ViewController.h"

@interface ViewController ()

{
    // 定义供多个方法使用的成员变量。
    NSArray *_iconViews;
    CGFloat _width;
    CGFloat _height;
    CGFloat _x;
    CGFloat _y;
    NSUInteger _count;  // 表情图片的个数。
    int _n; // 添加的表情个数。

}

@end

@implementation ViewController

#pragma mark 1. 初始化加载表情。
- (void)viewDidLoad {

    [super viewDidLoad];

    // 初始化。
    _n = 0;

    // 给_width和_height赋值。
     UIImage *icon = [UIImage imageNamed:@"0.png"];

    _width = icon.size.width;

    _height = icon.size.height;

    // 定义变量。
    NSString *iconName;
    UIImageView *iconView;

    for (int i = 0; i < 10; i++) {

        // 创建图片实例。
        iconName = [NSString stringWithFormat:@"%d.png",i];

        UIImage *icon = [UIImage imageNamed:iconName];

        // 创建图片视图。        
        iconView = [[UIImageView alloc]init];

        // 定义各图片控件的位置。
        _x = (_iconsView.frame.size.width - _width * 2) * 0.5 + _width * (i % 2);

        _y = _height * (i / 2);

        // 设置图片控件
        iconView.frame = CGRectMake(_x, _y,_width,_height);

        iconView.image = icon;

        if (i == 9) {

#pragma mark 重点:uiimageview不能调用addtargetxx方法。
            // 添加uicontrol类型的控件,因为uiimageview类型的控件不可以添加监听事件。addtatget不是uiview的方法,而是其子类uicontrol的方法。
            UIButton *addBut = [[UIButton alloc]init];

            addBut.frame = CGRectMake(_x, _y,_width,_height);

            [addBut setBackgroundImage:icon forState:UIControlStateNormal];

            [_iconsView addSubview:addBut];
        }
        else{
        // 添加图片控件。
            [_iconsView addSubview:iconView];
        }

    }

    // 提取图片框中的所有子控件到数组内。注意体会:@property(nonatomic,readonly,copy) NSArray *subviews;
    _iconViews = _iconsView.subviews;

    _count = _iconViews.count;

#pragma mark 为最后一个button控件添加监听事件。
    // 为最后一个控件添加监听事件。
    [_iconViews[_count -1] addTarget:self action:@selector(addIcon) forControlEvents:UIControlEventTouchUpInside];
}

#pragma mark 2. 定义监听事件调用的添加表情方法。
- (void)addIcon{

    // 更新_count数值。
    _iconViews = _iconsView.subviews;

    _count = _iconViews.count;

#pragma mark 重点2:不能通过数组元素来访问frame变量。
    // 因为不能通过数组元素得到frame属性。所以通过一个相同类型的指针temp来得到其frame属性。
    UIImageView *temp =  _iconViews[_count -1];

    UIImageView *temp1 = [[UIImageView alloc]init];

    // 深刻体会。
    temp1.frame = temp.frame;

    NSString *iconName = [NSString stringWithFormat:@"%d.png",(_n++ % 9)];

    temp1.image = [UIImage imageNamed:iconName];

#pragma mark 重点3:insert  below 。
    // 在最后一个元素前面插入新元素,注意用的是below。
    [_iconsView insertSubview:temp1 belowSubview:_iconViews[_count - 1]];

    // 插入新元素后更新_count值。
    _iconViews = _iconsView.subviews;

    int index  = _iconViews.count -1;

    // 为了得到列数,引入了segment成员变量。
    int column = _segment.selectedSegmentIndex + 2 ;

    // 更改最后一个元素的位置。
    _x = (_iconsView.frame.size.width - _width * column) * 0.5 + _width * (index % column);

    _y = _height * (index / column);

    temp.frame = CGRectMake(_x, _y, _width, _height);

}

#pragma mark 3. 按列排序。
- (IBAction)setColumns:(UISegmentedControl *)sender{

    [UIView beginAnimations:nil context:nil];
    [UIView setAnimationDuration:1.0];

    // 获取列数。
    int column = sender.selectedSegmentIndex + 2;

    // 更新_count。
    _iconViews = _iconsView.subviews;

    _count = _iconViews.count;

#pragma mark 重点3:不能通过数组元素来访问frame变量。
    // 此处需注意:不能通过数组访问subview的frame成员变量(即_iconView[i].frame 是错误的表达,编译不通过),所以要新建一个临时的UIImageView temp 来作为过渡。个人认为:可能是因为_iconView是个不可变数组.但是把其中的元素提取出来后,更改其属性,实际的元素属性的确被更改了,这是不是代表着该数组是深复制的不可变数组(uiview的subviews变量是用copy修饰的),但是其中的元素时浅复制,所以单独更改后,真实的元素属性也被更改了。虽然temp是通过赋值得到的元素,但是temp和xx[]都是指针,所以都指向的时同样的元素。
#pragma mark 疑问1 subviews copy修饰??
    // @property(nonatomic,readonly,copy) NSArray *subviews;还不是理解?

    UIImageView *temp;

    for (int i = 0; i < _count; i++) {

        // 对应temp。
        temp = _iconViews[i];

        // 让图片位于左右的中间,注意取余数和取商的用法。
        _x = (_iconsView.frame.size.width - _width * column) * 0.5 + _width * (i % column);

        _y = _height * (i / column);

        temp.frame= CGRectMake(_x, _y, _width, _height);
    }

    [UIView commitAnimations];

}
@end

重点 难点 注意点

  1. uiimageview不能调用addtarget方法,将最后的加号图片设置为uibutton类型。
  2. 在uiimageview中最后一个subview前面插入subview ,是用的below,而不是above。
  3. 不能通过数组访问subview的frame成员变量(即_iconView[i].frame 是错误的表达,编译不通过),所以要新建一个临时的UIImageView temp 来作为过渡。个人认为:可能是因为_iconView是个不可变数组.但是把其中的元素提取出来后,更改其属性,实际的元素属性的确被更改了,这是不是代表着该数组是深复制的不可变数组(uiview的subviews变量是用copy修饰的),但是其中的元素时浅复制,所以单独更改后,真实的元素属性也被更改了。虽然temp是通过赋值得到的元素,但是temp和xx[]都是指针,所以都指向的时同样的元素。
  4. 既然是排列,类似于矩阵,为了得到其行数和列数,用取余数和取商是个很好的方法。

疑问

  1. @property(nonatomic,readonly,copy) NSArray *subviews;还不是理解?其中的copy??

待完善的内容

  1. 更深入了解一下segment的用法。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值