UIKit之九宫格

轻量级xib和重量级storyboard提高开发效率。
在这里插入图片描述

需求分析:

  1. 需要实现一个宫格自定义类,该宫格包含:图片、文字、按钮。分别对应组件:UIImageView、UILabel、UIButton。其中,点击后按钮变为不可选状态。
  2. 在点击下载后弹出的消息框,该框还需要一个渐变出现和渐变消失的动画。
  3. 需要创建数据:plist。

实现:

本案例由三部分组成:调用、组件、数据。
代码的实现思路是:

  1. 在调用处创建plist总条数个组件,然后添加到View上。此外,消息提示框的实现也放在调用处。
  2. 组件的布局也放在调用处。动画也在调用处

调用处代码实现:

包含了创建多个组件、排列多个组件、数据读取。

  1. 在ViewController处声明数据成员变量,并用懒加载方式初始化数据。
@interface ViewController ()
// 九宫格Demo的plist信息
@property (nonatomic, strong) NSArray * apps;
@end
// 数据
- (NSArray *) apps
{
    if(_apps == nil)
    {
        // 1. 获取app.plist文件
        NSString *path = [[NSBundle mainBundle] pathForResource:@"app.plist" ofType:nil];
        // 2. 根据路径加载数据
        _apps = [NSArray arrayWithContentsOfFile:path];
    }
    return _apps;
}

  1. 布局:通过父视图来计算每个组件中的横纵坐标。同时绑定按钮的点击事件。
- (void)viewDidLoad {
    [super viewDidLoad];
    // 九宫格:其实有12格
    [self testsquare];
}

- (void) testsquare{
    // 设置上下边距、坐标、大小放在创建View处,如果封装在视图类中,还得传参
    CGFloat appW = 75;
    CGFloat appH = 90;
    // App距离手机顶部的边距
    CGFloat marginTop = 100;
    CGFloat bgView = self.view.frame.size.width;
    // 九宫格4行3列
    int columns = 3;
    // 整个屏幕的宽度 - 一行宫格View的宽度 / 宫格数+1,因为间隔总比宫格数多1
    CGFloat marginX = (bgView -  columns * appW) / (columns+1);
    // 令行间距等于列间距
    CGFloat marginY = marginX;
    for (int i = 0; i < 12; i++)
    {
        // 读取plist数据
        // 获取当前的kv:字典中存着 图标名和图片名
        NSDictionary *appDict = self.apps[i];
        
        // 0~2=0行, 3~5 = 1行,所以行号除以3即可
        // 0、3、6、9->0列,1、4、7、10->1列 列号取模
        int row = i / 3;
        int col = i % 3;
        // 动态计算每个宫格的X、Y坐标:
        // x:(列号+1)*列边距     上述计算的行列边距值一样
        // X坐标:左边距+列号*边距
        CGFloat appX = marginX + (marginX+appW) * col;
        // y:行号*列边距 + 到顶部距离, 上述计算的行列边距值一样
        CGFloat appY = marginTop + row * (marginY+appH);
        squaredDemo *sqview = [[squaredDemo alloc] init];
        sqview.frame = CGRectMake(appX, appY, appW, appH);
        // sqview.backgroundColor = [UIColor blueColor];
        // 设置宫格视图中的组件样式 imgview的icon
        // icon大小占宫格一半:
        // 不必addSub 因已add
        CGFloat iconW = 45;
        CGFloat iconH = 45;
        CGFloat iconX = (sqview.frame.size.width-iconW) / 2;  // 居中
        CGFloat iconY = 0;  // icon紧贴顶部,Y为0
        // sqview.imgview.backgroundColor = [UIColor yellowColor];
        sqview.imgview.frame = CGRectMake(iconX, iconY, iconW, iconH);
        // 设置label
        CGFloat nameW = sqview.frame.size.width;    // 紧贴label
        CGFloat nameH = 20; //
        CGFloat nameX = 0;  // Label贴着View
        CGFloat nameY = iconY+iconH;  // name紧贴图标icon底部,iconY=0
        
        // 设置label的颜色:
        // label文字需要设置居中,默认是左对齐,注意背景色的函数和字体颜色的函数
        //sqview.label.backgroundColor = [UIColor redColor];
        // 如果找不到某个控件,很可能是你的坐标给错了:之前错误地把宫格view中label的坐标给成了view的宽度,位置直接到了宫格view以外,所以看不见
        sqview.label.frame = CGRectMake(nameX, nameY, nameW, nameH);
        // 设置btn
        CGFloat btnW = iconW;    // 和icon一致
        CGFloat btnH = 20; //
        CGFloat btnX = iconX;  // 居中
        CGFloat btnY = nameY+nameH;  // name紧贴图标icon底部,iconY=0
        sqview.btn.frame = CGRectMake(btnX, btnY, btnW, btnH);
        
        
        //  = = = = =  = =   数据填充、格式设置  =  = =  = = =  =
        // 设置宫格view的数据
        sqview.imgview.image = [UIImage imageNamed:appDict[@"icon"]];
        sqview.label.text = appDict[@"icon"];
        sqview.label.font = [UIFont systemFontOfSize:12];
        // 设置文字居中对齐
        sqview.label.textAlignment = NSTextAlignmentCenter;
        // 按钮背景
        [sqview.btn setBackgroundImage:[UIImage imageNamed:@"buttongreen.png"] forState:UIControlStateNormal];
        [sqview.btn setBackgroundImage:[UIImage imageNamed:@"buttongreen_highlighted.png"] forState:UIControlStateHighlighted];
        // btn title设置
        [sqview.btn setTitle:@"下载" forState:UIControlStateNormal];
        // 已安装状态是不可点击时
        [sqview.btn setTitle:@"已安装" forState:UIControlStateDisabled];
        // btn title 大小
        sqview.btn.font = [UIFont systemFontOfSize:14];
        
        // 按钮绑定单击事件
        [sqview.btn addTarget:self action:@selector(btnDownClick:) forControlEvents:UIControlEventTouchUpInside];
        
        //
        [self.view addSubview: sqview];
    }
}





  1. 点击弹出消息并实现动画的显示和消失:
    消息提示框动画逻辑稍微复杂一点,思路是:先设置不透明度为0值,即初始完全透明,随后设置动画中不透明度变为0.6,接着实现消息框的消失效果,通过再把透明度设置为0的方式,最后移除该消息框,通过removeFromSuperview()来实现。
- (void) btnDownClick:(UIButton *)sender{
    NSLog(@"点击了下载");
    // 先禁用按钮
    sender.enabled = NO;
    
    CGFloat viewW = (self.view.frame.size.width);
    CGFloat viewH = (self.view.frame.size.height);
    
    // 点击下载后,创建UILabel,并添加动画:需要init,不然好像直接报错了
    UILabel *labMsg = [[UILabel alloc] init];
    
    CGFloat msgW = 200;
    CGFloat msgH = 30;
    CGFloat msgX = (viewW - msgW) / 2;  // 横纵坐标就用屏幕的宽高来求
    CGFloat msgY = (viewH - msgH) * 0.5;
    labMsg.frame = CGRectMake(msgX, msgY, msgW, msgH);
    [labMsg setBackgroundColor:[UIColor blackColor]];
    labMsg.textColor = [UIColor redColor];
    labMsg.text = @"正在下载...";
    labMsg.font = [UIFont boldSystemFontOfSize:17];
    // 初始透明度为0,即:全透明不显示
    labMsg.alpha = 0.0;
    // 设置圆角半径
    labMsg.layer.cornerRadius = 10;
    // 裁剪半径外部分
    labMsg.layer.masksToBounds = YES;
    
    // 设置消息提示框逐渐变黑并显示:
    [UIView animateWithDuration:1.5 animations:^{
        labMsg.alpha = 0.6;
    }completion:^(BOOL finished) {
        // 如果执行完了,则启动变暗消失动画
        if(finished){
            // 代码含义:执行完,再执行以下:透明度变0,即:消失
            [UIView animateWithDuration:1.5 delay:1.0 options:UIViewAnimationOptionCurveLinear animations:^{
                // 变化内容是:透明度变0,即隐藏
                labMsg.alpha = 0;
            } completion:^(BOOL finished) {
                if(finished){
                    // 当Label透明度变0后,把Label从view移除
                    [labMsg removeFromSuperview];
                }
            }];
        }
    }];
    // 加入视图
    [self.view addSubview: labMsg];
    
}

  1. 自定义宫格组件视图
// 宫格
@interface squaredDemo : UIView
// App的展示图标
// 可点击的按钮
// 显示名称的UILabel
@property(strong, nonatomic) UIImageView *imgview;
@property(strong, nonatomic) UILabel *label;
@property(strong, nonatomic) UIButton *btn;
@end

```objectivec
@implementation squaredDemo


-(instancetype) initWithFrame:(CGRect)frame{
    // 整个视图
    self = [super initWithFrame:frame];
    if(self){
        
        // 循环创建
        _btn = [[UIButton alloc]init];
        
        // 按钮文字
        //[_btn setTitleColor:[UIColor blackColor]  forState:UIControlStateNormal];
        
        
        _imgview = [[UIImageView alloc] init];
        /*_imgview = [[UIImageView alloc] initWithFrame:CGRectMake(appW, appH, appX, appY)]*/
        // UILabel:
        _label = [[UILabel alloc] init];
        
        //_label.text = @"123";
        
        
        // 添加到子View
        [self addSubview:_btn];
        [self addSubview:_label];
        [self addSubview:_imgview];
        
    }
    return self;
}
@end

遇到的错误和注意点:

  1. 组件没显示,且报错bad thread的原因是

没有把视图View添加成功,组件创建后除了要用alloc,还要用init。

  1. 添加UILabel没显示:

UILabe的背景颜色没设置,文字也没设置。故添加subView后没看到效果

  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值