zoukankan      html  css  js  c++  java
  • [iOS基础控件

    A.概述
         在"[iOS基础控件 - 4.4] APP列表 进一步封装,初见MVC模式”上进一步改进,给“下载”按钮加上效果、功能
         1.按钮点击后,显示为“已下载”,并且不可以再按
         2.在屏幕中间弹出一个消息框,通知消息“xx已经被安装”,慢慢消失
         3.消息框样式为圆角半透明
     
    Image(67)
     
     
    B.不使用代理模式,使用app空间组和主View之间的父子View关系
    1.在主View中创建一个消息框
     
    主View控制器:ViewController.m
       
     1  // 创建下载成功消息框
     2     CGFloat labelWidth = 200;
     3     CGFloat labelHeight = 50;
     4     CGFloat labelX = (self.view.frame.size.width - labelWidth) / 2;
     5     CGFloat labelY = (self.view.frame.size.height - labelHeight) / 2;
     6     UILabel *successMsgLabel = [[UILabel alloc] initWithFrame:CGRectMake(labelX, labelY, labelWidth, labelHeight)];
     7    
     8     // 设置圆角矩形样式
     9     successMsgLabel.layer.cornerRadius = 10.0;
    10     successMsgLabel.layer.masksToBounds = YES;
    11    
    12     // 设置全透明隐藏
    13     successMsgLabel.alpha = 0;
    14    
    15     successMsgLabel.textColor = [UIColor whiteColor];
    16     successMsgLabel.backgroundColor = [UIColor grayColor];
    17     [successMsgLabel setTextAlignment:NSTextAlignmentCenter];
    18     successMsgLabel.tag = 10;
    19   
    20     [self.view addSubview:successMsgLabel];
     
    2.直接在app空间组的控制器中操作消息框,加入到父控件(主View)
     
    app控件组View:AppView.m
     1 // 点击下载按钮
     2 - (IBAction)onDownloadButtonClick {
     3     // 更改“下载”按钮样式
     4     [self.downloadButton setTitle:@"已下载" forState:UIControlStateDisabled];
     5     self.downloadButton.enabled = NO;
     6   
     7     // 拿到消息框
     8     UILabel *successMsgLabel = [self.superview viewWithTag:10];
     9     successMsgLabel.text = [NSString stringWithFormat:@"成功安装了%@", self.appData.name];
    10     successMsgLabel.alpha = 0.7;
    11    
    12     // 使用动画
    13     [UIView beginAnimations:nil context:nil];
    14     [UIView setAnimationDuration:2];
    15     successMsgLabel.alpha = 0;
    16     [UIView commitAnimations];
    17 }
     
    缺点:view的父子关系规定了这两个view的层次关系,依赖性、耦合性太强,导致各个view都不能自由修改
     
    C.不使用代理模式,在app控件组的view中将主View作为一个成员
    1.在控件组AppView中创建主View的引用
    控件组 AppView.h
    1 // 存储主View的引用
    2 @property (nonatomic, weak) UIView *vcView;
     
    2.在主View逐个加载控件组的时候,设置主View的引用
    ViewController.m
     1  for (int index=0; index<self.apps.count; index++) {
     2         App *appData = self.apps[index];
     3 
     4         // 1.创建View
     5         AppView *appView = [AppView appViewWithApp:appData];
     6        
     7         // 2.定义每个app的位置、尺寸
     8         CGFloat appX = marginX + column * (marginX + APP_WIDTH);
     9         CGFloat appY = marginY + row * (marginY + APP_HEIGHT);
    10         appView.frame = CGRectMake(appX, appY, APP_WIDTH, APP_HEIGHT);
    11        
    12         // 设置每个app控件view的主view引用
    13         appView.vcView = self.view;
    14        
    15         // 3.加入此app信息到总view
    16         [self.view addSubview:appView];
    17        
    18         column++;
    19         if (column == appColumnCount) {
    20             column = 0;
    21             row++;
    22         }
     
    3.控件组AppView使用主View引用代替父控件引用
    AppView.m
     1 // 点击下载按钮
     2 - (IBAction)onDownloadButtonClick {
     3     // 更改“下载”按钮样式
     4     [self.downloadButton setTitle:@"已下载" forState:UIControlStateDisabled];
     5     self.downloadButton.enabled = NO;
     6    
     7     // 创建消息框
     8     UILabel *successMsgLabel = [self.vcView viewWithTag:10];
     9     successMsgLabel.text = [NSString stringWithFormat:@"成功安装了%@", self.appData.name];
    10     successMsgLabel.alpha = 0.7;
    11    
    12     // 使用动画
    13     [UIView beginAnimations:nil context:nil];
    14     [UIView setAnimationDuration:2];
    15     successMsgLabel.alpha = 0;
    16     [UIView commitAnimations];
    17 }
     
    缺点:控件组AppView的下载事件中取得控制器来弹出消息框,还是依赖于主View,耦合性强
     
     
    D.暴露控件组AppView的“下载”按钮,在主控制器中编写“下载”事件方法,绑定方法
    1.AppView暴露“下载”按钮控件给外部
    AppView.h
    1 // 将“下载”按钮控件移到 .h 文件中暴露
    2 @property (weak, nonatomic) IBOutlet UIButton *downloadButton;
     
    2.在控制器中编写“下载”单击事件方法
    ViewController.m
     1 // 控制器创建“下载”按钮点击事件
     2 - (IBAction)onAppViewDownloadButtonClick:(UIButton *) downloadButton {
     3     // 更改“下载”按钮样式
     4     [downloadButton setTitle:@"已下载" forState:UIControlStateDisabled];
     5     downloadButton.enabled = NO;
     6    
     7     // 创建消息框
     8     UILabel *successMsgLabel = [self.view viewWithTag:99];
     9    
    10     App *app = self.apps[downloadButton.tag];
    11     successMsgLabel.text = [NSString stringWithFormat:@"成功安装了%@", app.name];
    12     successMsgLabel.alpha = 0.7;
    13    
    14     // 使用动画
    15     [UIView beginAnimations:nil context:nil];
    16     [UIView setAnimationDuration:2];
    17     successMsgLabel.alpha = 0;
    18     [UIView commitAnimations];
    19 }
    20 
    21 @end
     
    3.给每个AppView的“下载”按钮绑定方法
       
     1  for (int index=0; index<self.apps.count; index++) {
     2         App *appData = self.apps[index];
     3 
     4         // 1.创建View
     5         AppView *appView = [AppView appViewWithApp:appData];
     6        
     7         // 2.定义每个app的位置、尺寸
     8         CGFloat appX = marginX + column * (marginX + APP_WIDTH);
     9         CGFloat appY = marginY + row * (marginY + APP_HEIGHT);
    10         appView.frame = CGRectMake(appX, appY, APP_WIDTH, APP_HEIGHT);
    11        
    12         // 存储每个AppView对应的AppData数据索引在tag中
    13         appView.downloadButton.tag = index;
    14        
    15         // 绑定每个AppView中的“下载”按钮点击事件
    16         [appView.downloadButton addTarget:self action:@selector(onAppViewDownloadButtonClick:) forControlEvents:UIControlEventTouchUpInside];
    17  
    18         // 3.加入此app信息到总view
    19         [self.view addSubview:appView];
    20        
    21         column++;
    22         if (column == appColumnCount) {
    23             column = 0;
    24             row++;
    25         }
    26     }
     
    缺点:依赖于AppView暴露的“下载”按钮,不能被修改
     
     
    E.代理模式
    1.原则:谁拥有资源,谁调用
         添加label到控制器的逻辑:控制器来做
         当点击“下载”按钮的时候,控件组AppView的按钮点击事件应该通知控制器,要执行添加label到控制器view的操作
         控制器监听控件组AppView的下载按钮的点击
     
    1.声明代理
    AppView.h
    1 // 定义代理的协议
    2 @protocol AppViewDelegate <NSObject>
    3 // “下载”按钮被点击事件
    4 @optional
    5 - (void) appViewClickedDownloadButton:(AppView *) appView;
    6 @end
     
    2.在AppView中创建代理引用
    AppView.h
    1 @interface AppView : UIView
    2 // 代理
    3 @property(nonatomic, weak) id<AppViewDelegate> delegate;
    4 ...
    5 @end
     
    3.控制器遵守AppViewDelegate,使其拥有称为代理的资格
    1 ViewController.m
    2 @interface ViewController () <AppViewDelegate>
    3 ...
    4 @end
     
    4.实现代理方法
    ViewController.m
     1 // “下载”按钮点击的代理方法
     2 - (void)appViewClickedDownloadButton:(AppView *)appView {
     3     // 创建下载成功消息框
     4     CGFloat labelWidth = 200;
     5     CGFloat labelHeight = 50;
     6     CGFloat labelX = (self.view.frame.size.width - labelWidth) / 2;
     7     CGFloat labelY = (self.view.frame.size.height - labelHeight) / 2;
     8     UILabel *successMsgLabel = [[UILabel alloc] initWithFrame:CGRectMake(labelX, labelY, labelWidth, labelHeight)];
     9    
    10     // 设置圆角矩形样式
    11     successMsgLabel.layer.cornerRadius = 10.0;
    12     successMsgLabel.layer.masksToBounds = YES;
    13    
    14     // 设置全透明隐藏
    15     successMsgLabel.alpha = 0;
    16    
    17     successMsgLabel.textColor = [UIColor whiteColor];
    18     successMsgLabel.backgroundColor = [UIColor grayColor];
    19     [successMsgLabel setTextAlignment:NSTextAlignmentCenter];
    20 
    21     successMsgLabel.text = [NSString stringWithFormat:@"成功安装了%@", appView.appData.name];
    22     successMsgLabel.alpha = 0.7;
    23    
    24     // 使用动画
    25     [UIView beginAnimations:nil context:nil];
    26     [UIView setAnimationDuration:2];
    27     successMsgLabel.alpha = 0;
    28     [UIView commitAnimations];
    29    
    30     [self.view addSubview:successMsgLabel];
    31 }
     
    5.给每一个AppView设置代理
    ViewController.m
      
     1   for (int index=0; index<self.apps.count; index++) {
     2         App *appData = self.apps[index];
     3 
     4         // 1.创建View
     5         AppView *appView = [AppView appViewWithApp:appData];
     6        
     7         // 2.定义每个app的位置、尺寸
     8         CGFloat appX = marginX + column * (marginX + APP_WIDTH);
     9         CGFloat appY = marginY + row * (marginY + APP_HEIGHT);
    10         appView.frame = CGRectMake(appX, appY, APP_WIDTH, APP_HEIGHT);
    11        
    12         // 设置代理
    13         appView.delegate = self;
    14        
    15         // 3.加入此app信息到总view
    16         [self.view addSubview:appView];
    17        
    18         column++;
    19         if (column == appColumnCount) {
    20             column = 0;
    21             row++;
    22         }
    23     }
     
    6.点击“下载”按钮的时候,通知代理
    AppView.m
     1 // 点击下载按钮
     2 - (IBAction)onDownloadButtonClick {
     3     // 更改“下载”按钮样式
     4     [self.downloadButton setTitle:@"已下载" forState:UIControlStateDisabled];
     5     self.downloadButton.enabled = NO;
     6 
     7     // 通知代理
     8     // 检查是否实现了代理方法
     9     if ([self.delegate respondsToSelector:@selector(appViewClickedDownloadButton:)]) {
    10         [self.delegate appViewClickedDownloadButton:self];
    11     }
    12 }
     
    主要代码:
    Model:
     1 App.h
     2 //
     3 //  App.h
     4 //  01-应用管理
     5 //
     6 //  Created by hellovoidworld on 14/11/25.
     7 //  Copyright (c) 2014年 hellovoidworld. All rights reserved.
     8 //
     9 
    10 #import <Foundation/Foundation.h>
    11 
    12 @interface App : NSObject
    13 
    14 /**
    15 copy : NSString
    16 strong: 一般对象
    17 weak: UI控件
    18 assign: 基本数据类型
    19 */
    20 
    21 /**
    22 名称
    23 */
    24 @property(nonatomic, copy) NSString *name;
    25 
    26 /**
    27 图标
    28 */
    29 @property(nonatomic, copy) NSString *icon;
    30 
    31 /**
    32 自定义构造方法
    33 通过字典来初始化模型对象
    34 */
    35 - (instancetype) initWithDictionary:(NSDictionary *) dictionary;
    36 
    37 + (instancetype) appWithDictionary:(NSDictionary *) dictionary;
    38 
    39 @end
     
    App.m
     1 //
     2 //  App.m
     3 //  01-应用管理
     4 //
     5 //  Created by hellovoidworld on 14/11/25.
     6 //  Copyright (c) 2014年 hellovoidworld. All rights reserved.
     7 //
     8 
     9 #import "App.h"
    10 
    11 #define ICON_KEY @"icon"
    12 #define NAME_KEY @"name"
    13 
    14 @implementation App
    15 
    16 - (instancetype) initWithDictionary:(NSDictionary *) dictionary {
    17     if (self = [super init]) {
    18         self.name = dictionary[NAME_KEY];
    19         self.icon = dictionary[ICON_KEY];
    20     }
    21    
    22     return self;
    23 }
    24 
    25 
    26 + (instancetype) appWithDictionary:(NSDictionary *) dictionary {
    27     // 使用self代表类名代替真实类名,防止子类调用出错
    28     return [[self alloc] initWithDictionary:dictionary];
    29 }
    30 
    31 @end
     
    View:
     1 AppView.h
     2 //
     3 //  AppView.h
     4 //  01-应用管理
     5 //
     6 //  Created by hellovoidworld on 14/11/25.
     7 //  Copyright (c) 2014年 hellovoidworld. All rights reserved.
     8 //
     9 
    10 #import <UIKit/UIKit.h>
    11 
    12 @class App, AppView;
    13 
    14 // 定义代理的协议
    15 @protocol AppViewDelegate <NSObject>
    16 // “下载”按钮被点击事件
    17 @optional
    18 - (void) appViewClickedDownloadButton:(AppView *) appView;
    19 @end
    20 
    21 @interface AppView : UIView
    22 
    23 // 代理
    24 @property(nonatomic, weak) id<AppViewDelegate> delegate;
    25 
    26 // 在Controller和View之间传输的Model数据
    27 @property(nonatomic, strong) App *appData;
    28 
    29 
    30 // 自定义将Model数据加载到View的构造方法
    31 - (instancetype) initWithApp:(App *) appData;
    32 // 自定义构造的类方法
    33 + (instancetype) appViewWithApp:(App *) appData;
    34 // 返回一个不带Model数据的类构造方法
    35 + (instancetype) appView;
    36 
    37 
    38 @end
     
    AppView.m
     1 //
     2 //  AppView.m
     3 //  01-应用管理
     4 //
     5 //  Created by hellovoidworld on 14/11/25.
     6 //  Copyright (c) 2014年 hellovoidworld. All rights reserved.
     7 //
     8 
     9 #import "AppView.h"
    10 #import "App.h"
    11 
    12 // 封装私有属性
    13 @interface AppView()
    14 
    15 // 封装View中的控件,只允许自己访问
    16 @property (weak, nonatomic) IBOutlet UIImageView *iconView;
    17 @property (weak, nonatomic) IBOutlet UILabel *nameLabel;
    18 @property (weak, nonatomic) IBOutlet UIButton *downloadButton;
    19 
    20 
    21 
    22 - (IBAction)onDownloadButtonClick;
    23 
    24 @end
    25 
    26 @implementation AppView
    27 
    28 - (void)setAppData:(App *)appData {
    29     // 1.赋值Medel成员
    30     _appData = appData;
    31    
    32     // 2.设置图片
    33     self.iconView.image = [UIImage imageNamed:appData.icon];
    34     // 3.设置名字
    35     self.nameLabel.text = appData.name;
    36 }
    37 
    38 // 自定义将Model数据加载到View的构造方法
    39 - (instancetype) initWithApp:(App *) appData {
    40     // 1.从NIB取得控件
    41     UINib *nib = [UINib nibWithNibName:@"app" bundle:[NSBundle mainBundle]];
    42     NSArray *viewArray = [nib instantiateWithOwner:nil options:nil];
    43     AppView *appView = [viewArray lastObject];
    44    
    45     // 2.加载Model
    46     appView.appData = appData;
    47    
    48     return appView;
    49 }
    50 
    51 // 自定义构造的类方法
    52 + (instancetype) appViewWithApp:(App *) appData {
    53     return [[self alloc] initWithApp:appData];
    54 }
    55 
    56 // 返回一个不带Model数据的类构造方法
    57 + (instancetype) appView {
    58     return [self appViewWithApp:nil];
    59 }
    60 
    61 // 点击下载按钮
    62 - (IBAction)onDownloadButtonClick {
    63     // 更改“下载”按钮样式
    64     [self.downloadButton setTitle:@"已下载" forState:UIControlStateDisabled];
    65     self.downloadButton.enabled = NO;
    66 
    67     // 通知代理
    68     // 检查是否实现了代理方法
    69     if ([self.delegate respondsToSelector:@selector(appViewClickedDownloadButton:)]) {
    70         [self.delegate appViewClickedDownloadButton:self];
    71     }
    72 }
    73 
    74 @end
     
    Controller:
    ViewController.m
      1 //
      2 //  ViewController.m
      3 //  01-应用管理
      4 //
      5 //  Created by hellovoidworld on 14/11/24.
      6 //  Copyright (c) 2014年 hellovoidworld. All rights reserved.
      7 //
      8 
      9 #import "ViewController.h"
     10 #import "App.h"
     11 #import "AppView.h"
     12 
     13 #define ICON_KEY @"icon"
     14 #define NAME_KEY @"name"
     15 #define APP_WIDTH 85
     16 #define APP_HEIGHT 90
     17 #define MARGIN_HEAD 20
     18 #define ICON_WIDTH 50
     19 #define ICON_HEIGHT 50
     20 #define NAME_WIDTH APP_WIDTH
     21 #define NAME_HEIGHT 20
     22 #define DOWNLOAD_WIDTH (APP_WIDTH - 20)
     23 #define DOWNLOAD_HEIGHT 20
     24 
     25 @interface ViewController () <AppViewDelegate>
     26 
     27 /** 存放应用信息 */
     28 @property(nonatomic, strong) NSArray *apps; // 应用列表
     29 
     30 @end
     31 
     32 @implementation ViewController
     33 
     34 - (void)viewDidLoad {
     35     [super viewDidLoad];
     36     // Do any additional setup after loading the view, typically from a nib.
     37    
     38     [self loadApps];
     39 }
     40 
     41 - (void)didReceiveMemoryWarning {
     42     [super didReceiveMemoryWarning];
     43     // Dispose of any resources that can be recreated.
     44 }
     45 
     46 #pragma mark 取得应用列表
     47 - (NSArray *) apps {
     48     if (nil == _apps) {
     49         // 1.获得plist的全路径
     50         NSString *path = [[NSBundle mainBundle] pathForResource:@"app.plist" ofType:nil];
     51        
     52         // 2.加载数据
     53         NSArray *dictArray  = [NSArray arrayWithContentsOfFile:path];
     54        
     55         // 3.将dictArray里面的所有字典转成模型,放到新数组中
     56         NSMutableArray *appArray = [NSMutableArray array];
     57         for (NSDictionary *dict in dictArray) {
     58             // 3.1创建模型对象
     59             App *app = [App appWithDictionary:dict];
     60            
     61             // 3.2 添加到app数组中
     62             [appArray addObject:app];
     63         }
     64        
     65         _apps = appArray;
     66     }
     67 
     68     return _apps;
     69 }
     70 
     71 #pragma mark 加载全部应用列表
     72 - (void) loadApps {
     73     int appColumnCount = [self appColumnCount];
     74     int appRowCount = [self appRowCount];
     75    
     76     CGFloat marginX = (self.view.frame.size.width - APP_WIDTH * appColumnCount) / (appColumnCount + 1);
     77     CGFloat marginY = (self.view.frame.size.height - APP_HEIGHT * appRowCount) / (appRowCount + 1) + MARGIN_HEAD;
     78    
     79     int column = 0;
     80     int row = 0;
     81     for (int index=0; index<self.apps.count; index++) {
     82         App *appData = self.apps[index];
     83 
     84         // 1.创建View
     85         AppView *appView = [AppView appViewWithApp:appData];
     86        
     87         // 2.定义每个app的位置、尺寸
     88         CGFloat appX = marginX + column * (marginX + APP_WIDTH);
     89         CGFloat appY = marginY + row * (marginY + APP_HEIGHT);
     90         appView.frame = CGRectMake(appX, appY, APP_WIDTH, APP_HEIGHT);
     91        
     92         // 设置代理
     93         appView.delegate = self;
     94        
     95         // 3.加入此app信息到总view
     96         [self.view addSubview:appView];
     97        
     98         column++;
     99         if (column == appColumnCount) {
    100             column = 0;
    101             row++;
    102         }
    103     }
    104    
    105 }
    106 
    107 
    108 #pragma mark 计算列数
    109 - (int) appColumnCount {
    110     int count = 0;
    111     count = self.view.frame.size.width / APP_WIDTH;
    112    
    113     if ((int)self.view.frame.size.width % (int)APP_WIDTH == 0) {
    114         count--;
    115     }
    116    
    117     return count;
    118 }
    119 
    120 #pragma mark 计算行数
    121 - (int) appRowCount {
    122     int count = 0;
    123     count = (self.view.frame.size.height - MARGIN_HEAD) / APP_HEIGHT;
    124    
    125     if ((int)(self.view.frame.size.height - MARGIN_HEAD) % (int)APP_HEIGHT == 0) {
    126         count--;
    127     }
    128    
    129     return count;
    130 }
    131 
    132 // “下载”按钮点击的代理方法
    133 - (void)appViewClickedDownloadButton:(AppView *)appView {
    134     // 创建下载成功消息框
    135     CGFloat labelWidth = 200;
    136     CGFloat labelHeight = 50;
    137     CGFloat labelX = (self.view.frame.size.width - labelWidth) / 2;
    138     CGFloat labelY = (self.view.frame.size.height - labelHeight) / 2;
    139     UILabel *successMsgLabel = [[UILabel alloc] initWithFrame:CGRectMake(labelX, labelY, labelWidth, labelHeight)];
    140    
    141     // 设置圆角矩形样式
    142     successMsgLabel.layer.cornerRadius = 10.0;
    143     successMsgLabel.layer.masksToBounds = YES;
    144    
    145     // 设置全透明隐藏
    146     successMsgLabel.alpha = 0;
    147    
    148     successMsgLabel.textColor = [UIColor whiteColor];
    149     successMsgLabel.backgroundColor = [UIColor grayColor];
    150     [successMsgLabel setTextAlignment:NSTextAlignmentCenter];
    151 
    152     successMsgLabel.text = [NSString stringWithFormat:@"成功安装了%@", appView.appData.name];
    153     successMsgLabel.alpha = 0.7;
    154    
    155     // 使用动画
    156     [UIView beginAnimations:nil context:nil];
    157     [UIView setAnimationDuration:2];
    158     successMsgLabel.alpha = 0;
    159     [UIView commitAnimations];
    160    
    161     [self.view addSubview:successMsgLabel];
    162 }
    163 
    164 @end
     
  • 相关阅读:
    HTML标签,简单归纳
    表单<form></form>提交方式的区别
    Angular实战记录
    JavaScript常用编程问题记录
    Observable 的 Operators集合
    一些重要的学习资料
    周末
    vue2.0传值问题
    javascript日常学习小记
    web前端经典小题
  • 原文地址:https://www.cnblogs.com/hellovoidworld/p/4131631.html
Copyright © 2011-2022 走看看