本分享是iOS開發中有趣的UI模塊的相關內容技術點分享。如果您是一位已經有C基礎了的iOS愛好者,但還未接觸Objectiov C語言,您需要學習我之前分享的 iOS開發核心語言Objective C 系列
如果您是零基礎,建議您從我之前分享的iOS開發分分鐘搞定C語言 系列開始學習。另外將無償分享自己整理出來的大概400G iOS學習視頻及學習資料,都是乾貨哦!可以新浪微博私信➕關注極客James,期待與您的共同學習和探討!!由於時間有限,每天在工作之餘整理的學習分享,難免有不足之處,也希望各路大神指正!
本次分享內容 made by 極客James
一、如何在Xcode開始UI的使用?
開始UI學習第一步
二、常見UI控件及案例
1.UIView
蘋果將控件的共同屬性都抽取到父類UIView中,所有的控件最終都繼承自UIView,所以說UIView是UI控件的父類。
2.UIView的常見屬性
@property(nonatomic,readonly) UIView *superview;
獲得自己的父控件對象
@property(nonatomic,readonly,copy) NSArray *subviews;
獲得自己的所有子控件對象
@property(nonatomic) NSInteger tag;
控件的ID(標識),父控件可以通過tag來找到對應的子控件
@property(nonatomic) CGAffineTransform transform;
控件的形變屬性(可以設置旋轉角度、比例縮放、平移等屬性)
@property(nonatomic,readonly) UIView *superview;
獲得自己的父控件對象
@property(nonatomic,readonly,copy) NSArray *subviews;
獲得自己的所有子控件對象
@property(nonatomic) NSInteger tag;
控件的ID(標識),父控件可以通過tag來找到對應的子控件
@property(nonatomic) CGAffineTransform transform;
控件的形變屬性(可以設置旋轉角度、比例縮放、平移等屬性)
@property(nonatomic) CGRect frame;
控件矩形框在父控件中的位置和尺寸(以父控件的左上角爲座標原點)
@property(nonatomic) CGRect bounds;
控件矩形框的位置和尺寸(以自己左上角爲座標原點,所以bounds的x、y一般爲0)
@property(nonatomic) CGPoint center;
控件中點的位置(以父控件的左上角爲座標原點)
3.UIKit的座標
左上角爲(0,0)原點,x軸向右爲x軸正方向,y軸向下爲正方向。
二、UIViewController
UIViewController是視圖控制器,也就是說UI控件一般都要在這裏進行加載創建和顯示。
三、UIImageView與拳皇案例
UIImageView極其常用,功能比較專一:顯示圖片。
1.常見屬性
UIImageView極其常用,功能比較專一:顯示圖片
@property(nonatomic,retain) UIImage *image;
顯示的圖片
@property(nonatomic,copy) NSArray *animationImages;
顯示的動畫圖片
@property(nonatomic) NSTimeInterval animationDuration;
動畫圖片的持續時間
@property(nonatomic) NSInteger animationRepeatCount;
動畫的播放次數(默認是0,代表無限播放)
2.通過UIImageView實現的經典案例 拳皇
實現效果圖:
項目需求:點擊相應的按鈕,實現相應的動畫,在動畫結束後讓它站立並且一直進行站立的動畫。
實現思路:
需要用到的控件:UIImageView UIImage Button
實現方式:通過StoryBoard 和代碼的方式完成
主要涉及內容:圖片的幀動畫
實現步驟:
1> 導入項目所需素材到Supporting File文件下
2> 在StoryBoard 中通過拖控件的方式搭建界面
3>搭建完界面之後通過StoryBoard和UIViewController建立相應的聯繫
通過IBOutlet讓視圖與UIViewController建立關係
@property (weak, nonatomic) IBOutlet UIImageView *imageView;
通過IBAction讓StoryBoard中的UIButton和UIViewController建立相應的聯繫。
4>分析實現過程。
幀動畫的整體思路爲:在特定時間內圖片的連續展示。
以下是過程:
在整個實現過程中由於是動畫幀的實現方式,所有的點擊事件接受的內容除了圖片不一樣之外其他的都一樣,所有采用抽取封裝的思想,將它抽取爲一個方法,後面有需要用到的直接調用,然後傳入相應的參數就可以。
- (void)play:(int)count prefixname:(NSString *)prename{
// (1)創建一個可變的空數組,用來後面裝加載好的圖片
NSMutableArray *images = [NSMutableArray array];
// (2) 通過for循環來遍歷文件中的圖片
for (int i = 1; i <= count; i++) {
// (3) 用以下圖片加載方式,能避免圖片產生緩存
NSString *filename = [NSString stringWithFormat:@"%@_%d",prename,i];
NSString *file = [[NSBundle mainBundle]pathForResource: filename ofType:@"png"];
// (4) 初始化一個UIImage
UIImage *image = [UIImage imageWithContentsOfFile:file];
// (5) 將加載後的圖片添加到可變數組中
[images addObject:image];
}
// (6)設置動畫
self.imageView.animationImages = images;
// (7)設置播放次數 和stand做對比(讓動畫完成後就站立)
self.imageView.animationRepeatCount = [prename isEqualToString:@"stand"]? 0 :1;
// (8)設置動畫完成後顯示的圖片
self.imageView.image = [UIImage imageNamed:@"stand_1"];
// (9)設置動畫時間
self.imageView.animationDuration = 10 * 0.09;
// (10)開始動畫
[self.imageView startAnimating];
// (11)判斷
if ([prename isEqualToString:@"stand"]) {
return;
}
// (12)播放完動畫,讓它一直動
[self performSelector:@selector(stand) withObject:nil afterDelay:self.imageView.animationDuration];
}
點擊相應的按鈕進行相應素材的加載例如:
// 跑步事件
- (IBAction)run {
// 圖片數量6張 圖片名前綴 run
[self play:6 prefixname:@"run"];
}
5>音頻的添加
點擊相應的圖標就會有相應的動畫和音效,上面只是完成了動畫的特效,下面來實現音頻的添加。
(1)首先導入音頻文件到 Supporting File文件下
(2)然後在頭文件中導入音頻的框架(必須導入,否則無法播放)
// 音視頻頭文件
#import <AVFoundation/AVFoundation.h>
(3)創建音視頻的方法,由於每個控件事件除了音頻路徑不一樣之外,其他的都一樣,所以我們採用封裝抽取的思想。
// 音頻方法
-(void)audioWithName:(NSString *)name {
// 音頻的路徑及音頻的格式
NSURL *url = [[NSBundle mainBundle]URLForResource:name withExtension:@"mp3"];
// 創建一個播放器
self.player = [AVPlayer playerWithURL:url];
// 播放
[self.player play];
}
九宮格實現及購物車案例
九宮格佈局,用手機輸入法時經常見到。先按3行3列寫。
代碼的實現主要是計算插入圖片的位置。
每一張圖片的位置和所在的行列密切相關。分析過程如下:
九宮格購物車項目分析:
實現效果:
項目需求:通過按鈕進行商品的添加和刪除,當商品爲0時,刪除按鈕不能觸發事件,當商品全部添加完成後,增加按鈕不能觸發事件。
**需要用到的控件:**UIImageView UIImage Button UILabel
實現方式:通過StoryBoard 和代碼的方式完成
主要涉及內容:九宮格 label 按鈕數據處理
實現步驟:
基本界面及點擊事件實現
1>將所用到的素材導入到Supporting File文件中
2> 在storyboard中拖一個大小爲300*300的UIView
3>在.m文件中進行類擴展以下方法
@property (weak, nonatomic)UIButton *addBtn;
@property (weak, nonatomic)UIButton *removeBtn;
@property (strong,nonatomic)NSArray *shop;
4>增加按鈕和刪除按鈕的代碼實現
由於增加按鈕和刪除按鈕具有相同的屬性,僅是圖片,位置,以及點擊時觸發的事件不一樣所有我們採用方法抽取及封裝的思想來做。
代碼如下:
// 增加和刪除按鈕的方法
- (UIButton *)addButtonWithImage:(NSString *)image hightImage:(NSString *)hightImage disableImage:(NSString *)disableImage frame:(CGRect)frame action:(SEL)action{
// 創建按鈕
UIButton *btn = [[UIButton alloc]init];
// 設置背景圖片正常下顯示
[btn setBackgroundImage:[UIImage imageNamed:image] forState:UIControlStateNormal];
// 設置背景圖片在高亮下顯示
[btn setBackgroundImage:[UIImage imageNamed:hightImage] forState:UIControlStateHighlighted];
// 設置背景圖片在啊不選中樣式下顯示
[btn setBackgroundImage:[UIImage imageNamed:disableImage] forState:UIControlStateDisabled];
// 設置尺寸
btn.frame = frame;
// 監聽按鈕點擊
[btn addTarget:self action:action forControlEvents:UIControlEventTouchUpInside];
// 將按鈕增加到視圖上
[self.view addSubview:btn];
return btn;
}
由於本項目需要數據,爲了程序的拓展性和可維護性,我們採用數據轉模型的方式進行操作。
數據轉模型實現步驟:
1>導入.plist文件
2>創建shopsModel文件(MVC思想)
在shopsModel.h文件中聲明如下:
// 將數據中的屬性進行定義和重寫
/**
* 商品名稱
*/
@property (nonatomic,strong)NSString *name;
/**
* 商品圖標
*/
@property (nonatomic,strong)NSString *icon;
// 初始化
- (instancetype)initWithDict:(NSDictionary *)dict;
+ (instancetype)shopWithDict:(NSDictionary *)dict;
在shopsModel.m中實現如下
- (instancetype)initWithDict:(NSDictionary *)dict{
if (self = [super init]) {
self.name = dict[@"name"];
self.icon = dict[@"icon"];
}
return self;
}
+ (instancetype)shopWithDict:(NSDictionary *)dict{
return [[self alloc] initWithDict:dict];
}
3>將創建好的數據模型的頭文件導入ViewController.m中
聲明一個數組
@property (strong,nonatomic)NSArray *shop;
4>對數組進行懶加載(在需要的時候進行在調用)
- (NSArray *)shop{
if (_shop == nil) {
// 加載plist文件
NSArray *dictArray =[NSArray arrayWithContentsOfFile:[[NSBundle mainBundle]pathForResource:@"shops" ofType:@"plist"]];
// 創建一個空得可變數組
NSMutableArray *shopArray = [NSMutableArray array];
// 遍歷字典
for (NSDictionary *dict in dictArray) {
shopsModel *shop = [shopsModel shopWithDict:dict];
[shopArray addObject:shop];
}
_shop = shopArray;
}
return _shop;
}
5>讓視圖一加載完就調用以下方法
- (void)viewDidLoad {
[super viewDidLoad];
// 增加按鈕
self.addBtn = [self addButtonWithImage:@"add" hightImage:@"add_highlighted"disableImage:@"add_disabled" frame:CGRectMake(30, 30, 50, 50) action:@selector(add)];
// 刪除按鈕
self.removeBtn = [self addButtonWithImage:@"remove" hightImage:@"remove_highlighted"
disableImage:@"remove_disabled" frame:CGRectMake(270, 30, 50, 50) action:@selector(remove)];
self.removeBtn.enabled = NO;
}
6.>增加按鈕
- (void)add{
self.shopView.clipsToBounds = YES;
// 設置每個商品的尺寸
CGFloat shopW = 80;
CGFloat shopH = 90;
// 設置顯示的列數
int cols = 3;
// 設置每一列之間的間距
CGFloat colMargin = (self.shopView.frame.size.width - cols * shopW) / (cols -1);
// 設置每一行之間的間距
CGFloat rowMargin = 10;
// 創建一個父控件(用來存放圖片和文字)
UIView *shopView = [[UIView alloc]init];
shopView.backgroundColor = [UIColor redColor];
// 商品的索引
NSUInteger index = self.shopView.subviews.count;
// 商品的x值(取餘運算,將算出商品在第幾列)
NSUInteger col = index % cols;
CGFloat shopX = col * (shopW + colMargin);
// 商品的y值(除法運算,將算出商品在第幾行)
NSUInteger row = index / cols;
CGFloat shopY = row * (shopH + rowMargin);
shopView.frame = CGRectMake(shopX, shopY, shopW, shopH);
// 添加到視圖上
[self.shopView addSubview:shopView];
// 獲得index位置對應的商品數據
shopsModel *shops = self.shop[index];
// 添加圖片
UIImageView *iconView = [[UIImageView alloc]init];
iconView.image = [UIImage imageNamed:shops.icon];
// 設置位置
iconView.frame = CGRectMake(0, 0, shopW, shopW);
iconView.backgroundColor = [UIColor blueColor];
[shopView addSubview:iconView];
// 添加文字
UILabel *label = [[UILabel alloc]init];
label.text = shops.name;
label.frame = CGRectMake(0, shopW, shopW, shopH - shopW );
label.font = [UIFont systemFontOfSize:11];
label.textAlignment = NSTextAlignmentCenter;
[shopView addSubview:label];
// 按鈕點擊事件是否可以繼續點擊的判斷
[self checkState];
}
7>刪除按鈕
- (void)remove{
self.shopView.clipsToBounds = YES;
[[self.shopView.subviews lastObject]removeFromSuperview];
[self checkState];
}
8>按鈕點擊狀態的狀態監聽(優化部分)
要在類擴展中進行label的聲明並且和storyboard建立聯繫
@property (weak, nonatomic) IBOutlet UILabel *hud;
- (void)checkState{
// 刪除按鈕什麼時候可以點擊
self.removeBtn.enabled = (self.shopView.subviews.count > 0);
// 增加按鈕什麼時候可以點擊
self.addBtn.enabled = (self.shopView.subviews.count < self.shop.count);
// 先將hud清0
NSString *text = nil;
if (self.removeBtn.enabled == NO) {
text = @"已經全部刪除";
}
else if(self.addBtn.enabled == NO){
text = @"所有物品已加入";
}
if (text == nil) return;
self.hud.text = text;
self.hud.alpha = 1.0;
// 通過多線程來做時間的延遲
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
self.hud.alpha = 0.0;
});
}