• ios开发-UI基础-应用管理(单纯界面)


      功能分析

    • 以九宫格的形式展示应用信息
    • 点击下载按钮后,做出相应操作(弹出一个提示"正在下载",相应应用的下载按钮变为"已下载")

      步骤分析

    • 搭建UI界面
    • 加载应用信息
    • 根据应用的个数创建对应的view
    • 监听下载按钮的点击

    应用截图:

    应用管理界面

      这个小的综合实例涉及到的知识点:

    • UIView的常见属性和方法
    • 九宫格的计算方法
    • 字典转模型
    • xib的使用
    • view的封装
    • 简单的MVC

      九宫格分析:

      

      搭建九宫格的步骤

    • 明确每一块用的是什么view
    • 明确每个view之间的父子关系
    • 先尝试逐个添加格子,最后考虑使用for循环
    • 加载app数据,根据数据的长度创建对应个数的格子
    • 添加格子内部的子控件
    • 给格子内部的子控件装载数据

    使用到的一些控件的常用方法

      1.UILabel的常用属性:  

    //显示的文字
    @property(nonatomic,copy) NSString *text;
    
    //字体
    @property(nonatomic,retain) UIFont *font;
    
    //文字颜色
    @property(nonatomic,retain) UIColor *textColor;
    
    //对齐模式(比如左对齐、居中对齐、右对齐)
    @property(nonatomic) NSTextAlignment textAlignment;

      2.UIFont的常见设置方法

    //系统默认字体
    + (UIFont *)systemFontOfSize:(CGFloat)fontSize;
    //粗体
    + (UIFont *)boldSystemFontOfSize:(CGFloat)fontSize;
    //斜体
    + (UIFont *)italicSystemFontOfSize:(CGFloat)fontSize;

      3.UIButton的常见方法

    //设置按钮的文字
    - (void)setTitle:(NSString *)title forState:(UIControlState)state;
    
    //设置按钮的文字颜色
    - (void)setTitleColor:(UIColor *)color forState:(UIControlState)state;
    
    //设置按钮内部的小图片
    - (void)setImage:(UIImage *)image forState:(UIControlState)state;
    
    //设置按钮的背景图片
    - (void)setBackgroundImage:(UIImage *)image forState:(UIControlState)state;
    
    
    //设置按钮的文字字体(需要拿到按钮内部的label来设置)
    //btn.titleLabel.font = [UIFont systemFontOfSize:13];

      整个应用的思路分析:

      

      1 /************************ "应用管理"思路分析************************/
      2 
      3 1. 功能分析
      4 * 以九宫格的方式展示应用信息
      5 * 点击"下载"按钮做出相应操作
      6 
      7 
      8 2. 步骤分析
      9 * 从对应的app.plist文件中加载数据("应用信息")
     10 * 根据加载好的"应用信息"的数据创建对应的view
     11 * 监听"下载"按钮的点击事件
     12 
     13 
     14 3. 开始编写代码
     15 
     16   1> 根据apps中的数据, 创建相应的view并展示到屏幕上
     17     一、分析:
     18         * 在界面一加载完毕就看到应用, 所以要在viewDidLoad方法中创建应用
     19         * 分析每个一个应用中都包含了一个UIImageView、UILabel、UIButton
     20         * 为了便于统一管理, 为每一个应用封装一个UIView, 然后在该UIView内部再放上面3个子控件
     21 
     22     二、创建UIView, 并添加到屏幕上
     23         * 通过代码实现,一个一个的创建UIView
     24         * 保证每行的应用之间的间距相等, 所以要计算每行的应用之间的间距{间距 = (屏幕宽度 - (3 * 每个应用的宽度)) / 4}
     25             
     26          1. 添加一个UIView
     27 /*       //    添加第一个格子
     28          UIView *appView = [[UIView alloc]init];//创建
     29          CGFloat appViewX = 20;
     30          CGFloat appViewY = 30;
     31          CGFloat appViewW = 100;
     32          CGFloat appViewH = 120;
     33          appView.frame = CGRectMake(appViewX, appViewY, appViewW, appViewH);//设置frame
     34          [self.view addSubview:appView];
     35          appView.backgroundColor = [UIColor redColor];//设置背景色
     36 */
     37          2. 通过循环根据app的个数添加多个UIView, 但是会覆盖, 因为frame相同
     38          for循环的次数取决于应用的个数(这里读取plist文件的数据,根据数据的长度确定循环的次数)
     39          
     40          2> 懒加载数据
     41          * 通过懒加载的方式加载app.plist中的数据到NSArray中
     42 /*         - (NSArray *)apps{
     43          
     44          if (_apps == nil) {
     45             //1.获取plis文件的路径
     46             NSString *path =   [[NSBundle mainBundle]pathForResource:@"app.plist" ofType:nil];
     47             //2.读取文件
     48             _apps =  [NSArray arrayWithContentsOfFile:path];
     49          
     50          }
     51             return  _apps;
     52          }
     53 
     54 */
     55          
     56          3. 计算第一个UIView的x和y(注意将里面的具体数字提取出来,便于后面使用和扩展)leftMargin ,topMaring,spacexMarign,spaceyMargrin
     57             
     58          4. 然后分析每个UIView的x和y,找出规律:
     59             x = leftMargin +列号 *(spacexMargin + appViewW);
     60             Y = topMargin +  行号*(spaceyMargin + appViewH);
     61 )
     62          
     63          5. 引入需要基础每个UIView所在的行的索引和列的索引
     64          int row = i /3;//行号
     65          int col = i % 3;//列号
     66          
     67          6.设置view的frame
     68          CGFloat appViewX = leftMargin + (appViewW + spaceX)*col;
     69          CGFloat appViewY = topMargin + (appViewH + spaceY )*row;
     70          //        2.2设置frame
     71          appView.frame = CGRectMake(appViewX, appViewY, appViewW, appViewH);
     72 
     73          
     74          
     75          */
     76 
     77 
     78 4.  在每个UIView中创建3个子元素: UIImageView、UILabel、UIButton
     79 * UIImageView:
     80     CGFloat iconW = 60;
     81     CGFloat iconH = 60;
     82     CGFloat iconX = (appView.frame.size.width - iconW) * 0.5;
     83     CGFloat iconY = 0;)
     84 
     85 * UILabel:
     86     CGFloat titleW = appW;
     87     CGFloat titleH = 20;
     88     CGFloat titleX = 0;
     89     CGFloat titleY = iconY + iconH;
     90 
     91 * UIButton
     92     CGFloat downloadW = appViewW - downLoadBtnX *2;
     93     CGFloat downloadH = 30;
     94     CGFloat downloadX = 10;
     95     CGFloat downloadY = nameLabelY + nameLabelH + 10;
     96     downloadBtn.frame = CGRectMake(downloadX, downloadY, downloadW, downloadH);
     97 
     98 
     99 5> 向UIImageView、UILabel、UIButton中添加数据
    100  1.取得字典
    101 NSDictionary *dict = self.apps[i];
    102 head.image = [UIImage imageNamed:dict[@"icon"]];//图片赋值数据
    103  nameLabel.text = dict[@"name"];//名字赋值数据
    104 [downLoadBtn setTitle:@"下载" forState:UIControlStateNormal];//设置文字
    105 
    106 
    107 
    108 
    109 
    110 6> 修改Label的字体、文字居中显示、按钮背景图片、设置按钮的字体大小。
    111 //       2.5.2设置文字大小
    112 nameLabel.font = [UIFont systemFontOfSize:13];
    113 //        2.5.3设置文字居中
    114 nameLabel.textAlignment = NSTextAlignmentCenter;
    115 downLoadBtn setBackgroundImage:[UIImage imageNamed:@"buttongreen"] forState:UIControlStateNormal];
    116 [downLoadBtn setBackgroundImage: [UIImage imageNamed:@"buttongreen_highlighted"] forState:UIControlStateHighlighted];
    117 
    118 
    119 
    120 * 了解按钮的内部结构:按钮至少有两个控件,一个label,一个imageView;
    121 *修改按钮文字的大小直接拿到他的对应的label进行设置即可
    122 downLoadBtn.titleLabel.font = [UIFont systemFontOfSize:14];
    123 
    124 
    125 * 注意: 修改按钮的文字的时候还是通过setTitle:来修改(这个方法可以设置不同状态), 不要直接通过titleLabel来修改文字。
    126 //* UIImageView设置图片居中:contentMode属性
    127 
    128 
    129 
    130 7. 字典转模型
    131   0> 字典:用来存储数据的,用键值对存储数据,是一个nsdictionary ,(不好处:key值容易写错)
    132   模型: 用来存储数据的,一个字典对应一个模型,模型用属性来存储数据,是以纯洁的object对象
    133   @property(nonatomic,copy)NSString *name;
    134   @property(nonatomic,copy)NSString *icon;
    135 
    136 字典转模型:一个字典对应一个模型,把键值对转化模型的属性,就是把键值对的value赋值给模型的属性
    137 //            appViewModel.name = dict[@"name"];
    138 //            appViewModel.icon = dict[@"icon"];
    139 
    140 属性的类型和名称:属性的类型和键值对的key值的类型是一样,最好名称也和key值的名称一样
    141 1> 为什么要把字典转成模型?
    142 * 字典缺陷:
    143 0> 写代码的时候字典的键没有智能提示, 但是模型的属性可以有智能提示
    144 1> ""是字符串, 如果写错了, 编译器不报错(在编译的时候不报错), 运行时可能出错, 出错了很难找错。
    145 
    146 
    147 
    148 
    149 
    150 
    151 
    152 * 把字典转模型的过程封装到"模型"内部
    153 * 原因: 将来的这个"模型"可能会在很多地方被用到(比如有很多个控制器都会使用这个模型), 那么每次用到模型的地方都需要写一次把字典中的数据赋给模型属性的代码, 此时如果把这些赋值语句封装到模型内部, 会大大简化了使用复杂度与代码量。
    154 * 思路:
    155 1> 在模型中接收一个NSDictionary的参数, 然后在模型内部把NSDictioanry中的键值对数据赋值给模型的属性。
    156 2> 封装一个initWithDict方法和一个appWithDict方法(规范)
    157 - (id)initWithDict:(NSDictionary *)dict{
    158     
    159     
    160     
    161     if (self = [super init]) {
    162         self.name = dict[@"name"];
    163         self.icon = dict[@"icon"];
    164         
    165     }
    166     return self;
    167     
    168     
    169 }
    170 
    171 + (id)appViewWithDict:(NSDictionary *)dict{
    172     //    AppViewModel *appViewModel = [[AppViewModel alloc]initWithDict:dict];
    173     //
    174     //    return  appViewModel;
    175     return  [[self alloc ]initWithDict:dict];//必须用self,因为这样创建出来的对象才是真实我们需要的对象,
    176     回忆:GoodApp;
    177 }
    178 
    179 
    180 
    181 * id与instancetype的介绍
    182 1. 使用id作为方法返回值的问题:
    183 1> 在接收方法的返回值的时候可以使用任何类型来接收, 编译都不报错, 但是运行时可能出错。
    184 
    185 2. instancetype需要注意的点
    186 1> instancetype在类型表示上, 与id意思一样, 都表示任何对象类型
    187 2> instancetype只能用作返回值类型, 不能向id一样声明变量、用作参数等
    188 3> 使用instancetype, 编译器会检测instancetype的真实类型, 如果类型不匹配, 编译时就警告了。(instancetype出现在哪个类型中就表示对应的类型)
    189 
    190 2> xib与storyboard既然都是描述软件界面的, 有什么区别吗?
    191 * xib 一般只用来描述一个界面中的某部分内容(用来描述局部UI界面)。
    192 
    193 * storyboard 一般用来描述软件的多个界面, 以及不同界面之间的跳转关系。
    194 
    195 
    196 7.使用xib精简代码。
    197 1> 什么是xib? xib能做什么?
    198 * 用来描述软件的局部界面的文件。
    199 * 如果没有xib, 所有的界面都需要通过代码来手动创建。
    200 * 进行创建xib,command +n ->user interface -> view;
    201 * 有了xib以后, 可以在xib中进行可视化开发,进行拖拽三个小的控件
    202 * 然后加载xib文件的.
    203  UIView *appView = [[NSBundle mainBundle]loadNibNamed:@"appView" owner:nil options:nil][0];
    204 
    205 8.  自定义View。创建属性、传递Model进去。
    206 *自定义一个appview用来描述xib,然后我们需要把xib的真实类型改变为appview(必须有这一步)
    207 *用拖线的方式拿到里面的三个小的控件
    208 *给这些控件进行赋数据,数据在模型中,我们拥有一个模型属性,为了从控制器中拿到模型,我们重写模型的set方法,
    209 这样我们就可以通过set方法把控制器中的模型数据赋值给我们内部的模型,拿到模型后我们进行控件的赋值,
    210 //重写模型的set方法
    211 - (void)setAppViewModel:(AppViewModel *)appViewModel{
    212     _appViewModel = appViewModel;
    213     
    214     
    215     self.head.image = [UIImage imageNamed:appViewModel.icon];
    216     self.nameLabel.text = appViewModel.name;
    217     
    218     
    219 }
    220 *这样我们就可以在控制器中直接赋值模型,然后显示数据
    221 //        2.4赋值
    222 AppViewModel *appViewModel = self.apps[i];
    223 
    224 
    225 appOldView.appViewModel = appViewModel;
    226 
    227 
    228 
    229 
    230 
    231 9. 封装创建View的代码, 让用户不知道是通过xib创建的还是通过代码创建的,安全,扩展性比较好。
    232 * 封装一个类方法
    233 + (instancetype )loadNib{
    234     return  [[NSBundle mainBundle]loadNibNamed:@"appView" owner:nil options:nil][0];
    235     
    236     
    237     
    238 }
    239 
    240 10.下载按钮的操作
    241 //    1.让按钮不能点击
    242 
    243 btn.enabled = NO;
    244 //    2.添加一个label
    245 //       2.1创建一个label
    246 UILabel *msgLabel = [[UILabel alloc]init];
    247 //       2.2设中label的frame
    248 CGFloat msgLabelW = 150;
    249 CGFloat msgLabelH = 30;
    250 CGFloat msgLabelX =  (self.superview.frame.size.width - msgLabelW)*0.5;
    251 CGFloat msgLabelY =  (self.superview.frame.size.height - msgLabelH)*0.5;
    252 msgLabel.frame = CGRectMake(msgLabelX, msgLabelY, msgLabelW, msgLabelH);
    253 //       2.3设置背景色
    254 msgLabel.backgroundColor = [UIColor blackColor];
    255 //       2.4添加
    256 [self.superview addSubview:msgLabel];
    257 //       2.5设置文字
    258 msgLabel.text = @"正在下载";
    259 //       2.6设置文字颜色
    260 msgLabel.textColor = [UIColor redColor];
    261 //       2.7让文字居中
    262 msgLabel.textAlignment = NSTextAlignmentCenter;
    263 //       2.8设置label为圆角
    264 //        2.8.1设置圆角的半径
    265 msgLabel.layer.cornerRadius = 8;
    266 //        2.8.2多余的部分切掉
    267 msgLabel.layer.masksToBounds = YES;
    268 //       2.9设置透明度,0~1,0代表完全透明,1代表完全不透明
    269 msgLabel.alpha = 0.0;
    270 //       2.10设置动画,(block式动画)
    271 //    animateWithDuration:动画执行的时间
    272 //    animations:执行动画的代码
    273 //    completion:动画完成后执行的代码
    274 [UIView animateWithDuration:3 animations:^{
    275     
    276     msgLabel.alpha = 0.5;
    277 } completion:^(BOOL finished) {
    278     if (finished) {
    279         // delay:延迟:表示动画动画延迟多长时间以后执行
    280         [UIView animateWithDuration:3 delay:0.5 options:UIViewAnimationOptionCurveLinear animations:^{
    281             msgLabel.alpha = 0.0;
    282         } completion:^(BOOL finished) {
    283             //                让msgLabel这个控件从父类中移除
    284             [msgLabel removeFromSuperview];
    285         }];
    286     }
    287 }];
    288 *注意动画的使用:不是头尾式,用的是block,block可以在动画执行后做一些事情.
    289 
    290 11.xib文件的加载过程。
    291 0> 根据路径, 搜索对应的xib文件(nib文件)
    292 1> 加载xib文件的时候, 会按顺序加载xib文件中的每个控件。
    293 2> 对于每个控件, 创建的时候都会查找对应的Class属性中配置的是那个类, 那么就创建对应的类的对象。
    294 3> 获取到某个视图以后, 按照在xib中配置的属性的值, 放在数组中,
    295 4> 最后返回一个数组, 这个数组中包含创建的所有元素对象。
    296 
    297 12.使用xib封装一个自定义view的步骤
    298 1> 新建一个AppView.xib文件来描述AppView内部的结构
    299 2> 新建一个继承UIView的自定义view,假设类名叫做(appView)
    300 3> 修改UIView的类型为appView真实类型
    301 4> 将内部的子控件跟appView进行属性连线
    302 5> appView提供一个模型属性
    303 6> 重写模型属性的set方法,因为在set方法中可以拿到外界控制器传递的模型数据
    304 7> 把模型数据拆开,分别设置数据到对应的子控件中
    305 8> 补充:提供一个创建AppView的类方法,将读取xib文件的代码屏蔽起来
    306 
    307 
    308 
    309 
    310 
    311 
    312 
    313 ------------ 补充两个知识点------------
    314 1. 根据subViews[index]获取子元素
    315 2. 通过[appView viewWithTag:10]根据tag的值来获取对应的子元素。
    316 以上两种方式返回值都是UIView将来还需要强制类型转换。
    317 
    318 
    319 
    320 3. 设置Label的圆角效果
    321 // 4. 设置Label为圆角
    322 // 设置四周圆角的半径
    323 lblMsg.layer.cornerRadius = 5;
    324 // 把多余的部分裁剪掉。
    325 lblMsg.layer.masksToBounds = YES;
  • 相关阅读:
    解析·玄学 模拟退火
    NOIP2018 集训(三)
    NOIP2018 集训(二)
    NOIP2018 集训(一)
    动画制作-cartoon
    视频压缩-video cutter
    [里程碑]media pro sdk 1.0 finished
    图像去水印-image inpainting
    地平线检测horizon line detection
    二维数据缺失补全
  • 原文地址:https://www.cnblogs.com/hukezhu/p/4504757.html
Copyright © 2020-2023  润新知