IOS开发笔记26-代码创建控件

来源:互联网 发布:mac qq只能发离线文件 编辑:程序博客网 时间:2024/06/08 18:05

1、 代码创建控件过程


所有控件都是类的对象,不同的类创建可以不同类型的控件。也是就说创建一个控件其实就是创建一个对应类的对象。

常用控件类型

UIButton:按钮,界面上可点击的大都是按钮

UILabel:标签,界面上只显示文字不能点击大都是标签

UITextField:文本框,界面上可输入数据的文本框

UIImageView:图片框,界面上不可点击的图片大都是图片框

使用代码创建控件的过程

//创建对象(控件),比如创建一个按钮(UIButton)UIButton *btn = [[UIButton alloc] init]; //设置这个对象(控件)的frame属性,也是控件的坐标、大小。必须给控件设置frame才能看得到btn.frame = CGRect(50,50,100,30);//坐标为50,50 宽、高为100、30 //设置对象(控件)的一些属性//默认、高亮状态下的按钮文字[btn setTitle:@"登陆" forState:UIControlStateNormal];[btn setTitle:@"点击了登陆" forState:UIControlStateHighlighted];//默认、高亮状态下的按钮背景颜色[btn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];[btn setTitleColor:[UIColor greenColor] forState:UIControlStateHighlighted];//默认、高亮状态下的按钮背景图[btnLogin setBackgroundImage:[UIImage imageNamed:@"buttongreen"] forState:UIControlStateNormal];[btnLogin setBackgroundImage:[UIImage imageNamed:@"buttongreen_highlighted"] forState:UIControlStateHighlighted]; //最后将创建好的对象(控件)添加到他的父容器(父视图)中[self.view addSubview:btn];//一定要将创建好的对象添加到父容器,否则无法显示

注意

一定不要使用titleLabel去设置文本内容和颜色,因为按钮是有状态的。而状态的文本值是title里面取。所以如果为titleLabel设置文本,那和以系统不知道这个文本是那一种状态下显示的文本,干脆不显示。


2、 代码实现QQ登陆界面


我们通过一个实例来对常用控件的基本属性、方法做个了解,和昨晚写的案例一样都是QQ登陆界面,不过这次使用纯代码的方式来实现。最终效果如下图:


首先还是先创建一个Single View Application,设置界面尺寸,导入案例需要用到的素材,本次素材就两个按钮背景图,自行网上搜索素材。搞好相关设置然后就可以开始编写代码了。

具体实现代码如下

#import "ViewController.h" @interface ViewController () //QQ、密码文本框(UITextField)控件@property (strong, nonatomic) UITextField *txtQQ;@property (strong, nonatomic) UITextField *txtPassword;@end @implementation ViewController //控制器加载后会立即调此方法- (void)viewDidLoad {    [super viewDidLoad];        //添加QQ、密码的Label    [self addQQLabel];    [self addPasswordLabel];        //添加QQ、密码的文本框    [self addQQTextField];    [self addPasswordTextField];        //添加登陆按钮    [self addLoginButton];} - (void)didReceiveMemoryWarning {    [super didReceiveMemoryWarning];} //创建QQ标签(UILabel)的方法- (void)addQQLabel {    //创建控件对象    UILabel *lblQQ = [[UILabel alloc] init];        //设置控件的frame属性    lblQQ.frame = CGRectMake(50, 50, 50, 21);        //设置标签文本文字、字体、文字对齐方式    lblQQ.text = @"QQ";    lblQQ.font = [UIFont fontWithName:@"Arial" size:14];    lblQQ.textAlignment = NSTextAlignmentLeft;        //将创建好的对象添加到当前控制器    [self.view addSubview:lblQQ];} //创建密码标签(UILabel)的方法- (void)addPasswordLabel {    //创建控件对象    UILabel *lblPassword = [[UILabel alloc] init];        //设置控件的frame属性    lblPassword.frame = CGRectMake(50, 90, 50, 21);        //设置标签文本文字、字体、文字对齐方式    lblPassword.text = @"密码";    lblPassword.font = [UIFont fontWithName:@"Arial" size:14];    lblPassword.textAlignment = NSTextAlignmentLeft;        //将创建好的对象添加到当前控制器    [self.view addSubview:lblPassword];} //创建QQ文本框(UITextField)的方法- (void)addQQTextField {    //创建控件对象,因为文本框中的数据需要在其他地方访问,所以就设置为属性    self.txtQQ = [[UITextField alloc] init];        //设置控件的frame属性    self.txtQQ.frame = CGRectMake(100, 45, 250, 30);        //设置文本框边框样式、默认文本框内文字、清除文本内容按钮    self.txtQQ.borderStyle = UITextBorderStyleRoundedRect;    self.txtQQ.placeholder = @"请输入QQ";    self.txtQQ.clearButtonMode = UITextFieldViewModeWhileEditing;        //设置键盘类型    self.txtQQ.keyboardType = UIKeyboardTypeNumberPad;        //将创建好的对象添加到当前控制器    [self.view addSubview:self.txtQQ];} //创建密码文本框(UITextField)的方法- (void)addPasswordTextField {    //创建控件对象,因为文本框中的数据需要在其他地方访问,所以就设置为属性    self.txtPassword = [[UITextField alloc] init];        //设置控件的frame属性    self.txtPassword.frame = CGRectMake(100, 85, 250, 30);        //设置文本框边框样式、默认文本框内文字、清除文本内容按钮    self.txtPassword.borderStyle = UITextBorderStyleRoundedRect;    self.txtPassword.placeholder = @"请输入密码";    self.txtPassword.clearButtonMode = UITextFieldViewModeWhileEditing;        //设置密码文本框的数据密文显示(密码看不到明文文字)    [self.txtPassword setSecureTextEntry:YES];        //将创建好的对象添加到当前控制器    [self.view addSubview:self.txtPassword];} //创建登陆按钮(UIButton)的方法- (void)addLoginButton {    //按钮的UIButtonType属性是只读的,只能在创建的时候初始化,如果没有设置,默认是UIButtonTypeCustom。    UIButton *btnLogin = [UIButton buttonWithType:UIButtonTypeCustom];        //设置控件的frame属性    btnLogin.frame = CGRectMake(170, 130, 100, 30);        //分别设置按钮默认、高亮状态下的文字、文字颜色、背景图片    [btnLogin setTitle:@"登陆" forState:UIControlStateNormal];    [btnLogin setTitle:@"点击了登陆" forState:UIControlStateHighlighted];    [btnLogin setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];    [btnLogin setTitleColor:[UIColor greenColor] forState:UIControlStateHighlighted];    //背景图先拖到Assets.xcassets或者Images.xcassets里,注意是.png格式的图片    [btnLogin setBackgroundImage:[UIImage imageNamed:@"buttongreen"] forState:UIControlStateNormal];    [btnLogin setBackgroundImage:[UIImage imageNamed:@"buttongreen_highlighted"] forState:UIControlStateHighlighted];        //设置按钮背景颜色,有背景图了背景颜色就可以不用设置了    [btnLogin setBackgroundColor:[UIColor grayColor]];        //为按钮添加绑定事件(单击事件),让按钮被点击后执行click方法    /*     第一个参数:调用谁的方法,让谁进行处理.往往就是self     第二个参数:调用的方法     第三个参数:事件类型     可以让多个按钮绑定同一个事件,通过tag值进行按钮的区分     */    [btnLogin addTarget:self action:@selector(click) forControlEvents:UIControlEventTouchUpInside];        //将创建好的对象添加到当前控制器    [self.view addSubview:btnLogin];} //登陆按钮的单击事件- (void)click {    //点击登录按钮后收起键盘    [self.view endEditing:YES];        NSString *msg = [NSString stringWithFormat:@"QQ:%@ 密码:%@",self.txtQQ.text,self.txtPassword.text];    //在控制台输出用户输入的QQ号、密码    NSLog(@"%@",msg);}@end

总结

要学会如何使用代码创建控件,首先得了解代码创建控件的基本过程(创建对象、设置对象的属性、添加对象到父容器)。并且还应该了解不同控件的一些必要属性和方法,这和我们前面OC中学习的创建对象、调用方法是没有任何区别的。



3、 图片浏览器


这个案例的主要目的是熟悉UIButtonUIImageView的使用,通过这个案例要全面了按钮的常用属性的设置,添加的业务逻辑也会提升我们对代码的熟练程度。同时加强封装的思想,初步使用外部的plist文件,这在之后plist文件会频繁的使用。

UIButton:当点击图片后能够有相应操作,或者点击后有高亮效果就使用UIButton。

UIImageView:当仅仅是静态展示图片,不需要对图片进行相应的操作就使用UIImageView。

下图就是我们案例完成后的样子,点击左右按钮能够切换图片、图片对应标题和索引,第一张和最有一张有按钮禁用。


创建好项目导入需要用到的图片素材,再次强调Assets.xcassets中只能放png格式的图片,在使用时省略扩展名。


拖拽两个Label控件、两个Button控件、一个Image View控件,并调整到尺寸、按钮默认、高亮背景图等等。


通过控件连线,定义好对应属性、方法,还有数组和图片索引用于操作我们的图片资源。


新建一个Property List(.plist)文件,用于封装数据。


然后选择创建好的img.plist文件,创建如下图所示的plist文件。一个数组里有5个字典,每个字典有两个键值对,img、title是键,分别对应图片名称、图片文字描述内容。


图片浏览器代码实现

#import "ViewController.h" @interface ViewController ()//存储图片资源的数组@property (strong, nonatomic) NSArray *arrayImgs;//图片@property (weak, nonatomic) IBOutlet UIImageView *img;//图片顶部标签@property (weak, nonatomic) IBOutlet UILabel *topTitle;//图片底部标签@property (weak, nonatomic) IBOutlet UILabel *downTitle; //上下页按钮@property (weak, nonatomic) IBOutlet UIButton *preBtn;@property (weak, nonatomic) IBOutlet UIButton *nextBtn; //图片索引@property (assign, nonatomic) int index; //上一页按钮- (IBAction)pre;//下一页按钮- (IBAction)next; @end @implementation ViewController - (void)viewDidLoad {    [super viewDidLoad];    //初始化让下标等于-1    self.index = -1;    //然后调用next方法,下标增加1。并显示下标为0的图片    [self next];} - (void)didReceiveMemoryWarning {    [super didReceiveMemoryWarning];    // Dispose of any resources that can be recreated.} //懒加载- (NSArray *)loadImgs {    if (_arrayImgs == nil) {        //如果_arrayImgs为nil则加载img.plist文件中的数组赋值给属性        //plist文件是物理文件,所以需要获取文件目录,通过目录+文件名进行数据读取        _arrayImgs = [NSArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"img.plist" ofType:nil]];        /*         [NSBundle mainBundle] 返回app安装后的根目录         arrayWithContentsOfFile:pathForResource:ofType:方法读取plist文件,返回一个数组         */    }    return _arrayImgs;} //上一页按钮- (IBAction)pre {    //数组下标自减,并调用方法显示图片等信息    self.index--;    [self showImg];} //下一页按钮- (IBAction)next {    //数组下标自增,并调用方法显示图片等信息    self.index++;    [self showImg];} //显示图片- (void)showImg {    //调用loadImgs方法初始化arrayImgs,并取出对应下标的字典    NSDictionary *dict = self.loadImgs[self.index];        //设置图片    self.img.image = [UIImage imageNamed:dict[@"img"]];        //设置图片顶部标题    self.topTitle.text = [NSString stringWithFormat:@"%d/%lu",self.index + 1,self.arrayImgs.count];        //设置图片底部标题    self.downTitle.text = dict[@"title"];        //判断按钮是否可点击    //如果下标不为0,则返回YES给上一页按钮的enabled属性,否则反之    self.preBtn.enabled = self.index != 0;    //如果下标不等于数组最大下标,则返回YES给下一页按钮的enabled属性,否则反之    self.nextBtn.enabled = self.index != self.arrayImgs.count - 1;    }@end

使用plist文件的好处

1.数据被封装,不再暴露在外面。

2.如果想修改或者添加删除数据,不需要修改源代码,只需要修改外部的plist文件。

3.plist文件的本质就是XML文件,所以后期可以通过对XML文件的读写操作来完成一些数据持久化操作。

创建plist文件的注意事项

1.一个字典中可以有多个key—value,多个字典包含在一个数组中。

2.plist文件名称最好不要包含info,否则会认为是系统的plist文件。

3.plist文件是物理文件,所以需要获取文件目录,通过目录+文件名进行数据读取。

获取plist文件所在的文件全路径

NSString *path = [[NSBundle mainBundle] pathForResource:@"img.plist" ofType:nil];

读取plist中的数据存储到数组中

self.arrayImgs = [NSArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"img.plist" ofType:nil]];

4、 汤姆猫小游戏


这个案例的主要目的是了解什么是帧动画,同时掌握UIImageView的使用方式,为UIImageView控件添加动画效果和一般动画效果的添加及相关的参数设置。

png图片:一般存放在Images.xcassets中,同时在使用图片的时候不需要添加扩展名。

JPG图片:一般图片存储在Supporting Files下面,在使用jpg图片的时候一般添加扩展名。

创建项目并拖拽好各种控件,这里是先拖一个UIImageView控件占满整个屏幕,然后再为Image属性设置一张默认图片。然后拖拽6个图片按钮、3个没有任何样式的按钮(头部、双脚),并设置相关属性。


将Button用到的png格式图片拖拽到Images.xcassets,其他图片拖拽到Supporting Files,这些文件夹里包含了大量图片。


实现代码如下

#import "ViewController.h" @interface ViewController ()@property (weak, nonatomic) IBOutlet UIImageView *imageViewCat; - (IBAction)drink;//喝牛奶- (IBAction)fart;//放屁- (IBAction)eat;//吃鸟- (IBAction)scratch;//爪子挖屏幕- (IBAction)pie;//扔馅饼- (IBAction)cymbal;//敲锣- (IBAction)knockout;//摸头- (IBAction)footRight;//摸右脚- (IBAction)footLeft;//摸左脚 @end @implementation ViewController - (void)viewDidLoad {    [super viewDidLoad];} - (void)didReceiveMemoryWarning {    [super didReceiveMemoryWarning];} //每一个按钮所触发的动画效果类似,只有图片名称及数量不一样,所以将其封装为方法- (void)showImageDataswithCount:(int)count andImageName:(NSString *)imageName {    //判断当前是否正在运行另外一个动画    if (self.imageViewCat.isAnimating) {        return;    }    /*     将图片资源存储到数组中     UIImageView动画效果需要为其animationImages属性指定包含图片路径或者文件名的数组     所以我们首先需要获取到图片资源数组     */    NSMutableArray *arrayM = [[NSMutableArray alloc] init];    for (int i = 0; i < count; i++) {        //拼接每一张图片名称        NSString *imgName = [NSString stringWithFormat:@"%@_%02d.jpg",imageName,i];                /*         使用包含图片名称的数组做为动画的数据源会将图片资源生成缓存,占用系统内存,这样不合理.         应该使用图片的全路径数组,这样不会生成缓存,同时还应该在一个动画播放完毕后将其及时释放         */        //UIImage *img = [UIImage imageNamed:imgName];                //图片资源放在Supporting Files        NSString *path = [[NSBundle mainBundle] pathForResource:imgName ofType:nil];                //这种方式加载的图片不会有缓存,每次用完就清空        UIImage *img = [UIImage imageWithContentsOfFile:path];                //存储到可变数组中        [arrayM addObject:img];    }    //将图片资源数组赋值给animationImages属性    self.imageViewCat.animationImages = arrayM;        //设置UIImageView的一些相关的动画属性    //设置动画时间    self.imageViewCat.animationDuration = arrayM.count * 0.1;    //动画循环次数    self.imageViewCat.animationRepeatCount = 1;    //动画开始播放    [self.imageViewCat startAnimating];        //动画播放完销毁,延迟执行代码    [self.imageViewCat performSelector:@selector(setAnimationImages:) withObject:nil afterDelay:arrayM.count * 0.1];    }//吃鸟- (IBAction)eat {    [self showImageDataswithCount:40 andImageName:@"eat"];} //喝牛奶- (IBAction)drink {    [self showImageDataswithCount:81 andImageName:@"drink"];} //放屁- (IBAction)fart {    [self showImageDataswithCount:28 andImageName:@"fart"];} //爪子挖屏幕- (IBAction)scratch {    [self showImageDataswithCount:56 andImageName:@"scratch"];} //扔馅饼- (IBAction)pie {    [self showImageDataswithCount:24 andImageName:@"pie"];} //敲锣- (IBAction)cymbal {    [self showImageDataswithCount:13 andImageName:@"cymbal"];} //摸头- (IBAction)knockout {    [self showImageDataswithCount:81 andImageName:@"knockout"];} //摸右脚- (IBAction)footRight {    [self showImageDataswithCount:30 andImageName:@"footRight"];} //摸左脚- (IBAction)footLeft {    [self showImageDataswithCount:30 andImageName:@"footLeft"];}@end

最终效果如下图,由于动画图片太大就么有整动态图:


常见错误

1. jpg文件没有添加扩展名。

2. 读取全路径的jpg素材文件的时候却没有将jpg没有添加到 Supporting Files造成无法获取到。

3. 清空资源的时候没有关注self是实际含义.

注意事项

1. 使用图片文件全路径而不是使用图片名称。

2. 动画播放完毕之后及时将当前图片资源释放。

3. 拼接生成正确的文件名。

4. 在制作动画的时候,如果想设置其它属性注意要先设置好其它属性再开始动画,否则可能动画没有效果。


1 0