1. 程式人生 > >IOS開發學習筆記十一 使用xlib檔案實現GridView的效果

IOS開發學習筆記十一 使用xlib檔案實現GridView的效果

效果圖:
效果圖

  • 在專案中資源素材檔案

  • 新增plist檔案

  • 新增名叫AFGridItem的model物件,用來代替我們從plist檔案中解析得到的字典資料,並新增通過字典獲取物件例項和初始化物件的方法。

#import <Foundation/Foundation.h>

@interface AFGridItem : NSObject
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *icon;


- (instancetype)initWithDict:(NSDictionary
*)dict; + (instancetype)appWithDict:(NSDictionary *)dict; @end
#import "AFGridItem.h"

@implementation AFGridItem
- (instancetype)initWithDict:(NSDictionary *)dict
{
    if (self = [super init]) {
        self.name = dict[@"name"];
        self.icon = dict[@"icon"];
    }
    return self;
}

+ (instancetype)appWithDict:(NSDictionary
*)dict { return [[self alloc] initWithDict:dict]; } @end
  • 為專案新建名叫AFGridItemView.xlib檔案,xlib檔案中新增一個空的View控制元件,併為這個空的View控制元件新增UIImageView,UIButton,UILabel控制元件,為UIButton新增點選響應事件,戶點選下載,在介面中間出現一個類似於Android上面的toast提示

新增AFGridItemView.xlib檔案

  • 為AFGridItemView.xlib檔案中的View控制元件新增一個對應的類AFGridItemView,為View中的UIImageView,UIButton,UILabel新增對應的變數,併為UIButton新增點選響應事件,並新增通過傳入AFGridItem物件來初始化的方法。
#import <UIKit/UIKit.h>
@class AFGridItem;
@interface AFGridItemView : UIView
@property (nonatomic, strong) AFGridItem *model;

// 為自定義view封裝一個類方法, 這個類方法的作用就是建立一個view物件
+ (instancetype)appView;
@end
#import "AFGridItem.h"
#import "AFGridItemView.h"

@interface AFGridItemView ()

@property (weak, nonatomic) IBOutlet UIImageView *imgViewIcon;
@property (weak, nonatomic) IBOutlet UILabel *lblName;
@property (weak, nonatomic) IBOutlet UIButton *btnDownload;

- (IBAction)btnDownloadClick:(UIButton *)sender;
- (IBAction)down:(id)sender;

@end
@implementation AFGridItemView

+ (instancetype)appView
{
    // 1. 通過xib建立每個應用(UIView)
    // 通過動態載入xib檔案建立裡面的view
    // 1.1> 找到應用的根目錄
    NSBundle *rootBundle = [NSBundle mainBundle]; // //NSLog(@"%@", [mainBundle bundlePath]);
    // 1.2> 在應用程式根目錄下取搜尋對應的Xib(nib)檔案
    return [[rootBundle loadNibNamed:@"AFGridItemView" owner:nil options:nil] lastObject];
}



// 重寫model屬性的set方法
- (void)setModel:(AFGridItem *)model
{
    // 先賦值
    _model = model;


    // 解析模型資料, 把模型資料賦值給UIView中的各個子控制元件
    self.imgViewIcon.image = [UIImage imageNamed:model.icon];
    self.lblName.text = model.name;
}



// 下載按鈕的單擊事件
- (IBAction)btnDownloadClick:(UIButton *)sender {
    // 1. 禁用當前被點選的按鈕
    sender.enabled = NO;

    // 2. 彈出一個訊息提醒框(這個訊息提醒框其實就是一個UILabel)
    UILabel *lblMsg = [[UILabel alloc] init];
    // 2.1 設定lblMsg的顯示文字
    lblMsg.text = @"正在下載...";
    // 2.2 設定lblMsg的背景色
    lblMsg.backgroundColor = [UIColor blackColor];
    // 2.3 設定lblMsg的frame
    CGFloat viewW = self.superview.frame.size.width;
    CGFloat viewH = self.superview.frame.size.height;
    CGFloat msgW = 200;
    CGFloat msgH = 30;
    CGFloat msgX = (viewW - msgW) / 2;
    CGFloat msgY = (viewH - msgH) * 0.5;
    lblMsg.frame = CGRectMake(msgX, msgY, msgW, msgH);
    // 2.4 設定label的文字顏色
    lblMsg.textColor = [UIColor redColor];
    // 2.5 設定label居中顯示
    lblMsg.textAlignment = NSTextAlignmentCenter;
    // 2.6 設定文字粗體
    lblMsg.font = [UIFont boldSystemFontOfSize:17];
    // 2.7 設定Label的透明度
    lblMsg.alpha = 0.0; // 一開始把透明度設定為0, 然後通過動畫的方式慢慢的改變透明度
    // 2.8 設定Label為"圓角"
    // 設定四個角的“半徑”
    lblMsg.layer.cornerRadius = 10;
    // 把多餘的部分裁剪掉
    lblMsg.layer.masksToBounds = YES;

    // 2.9通過動畫的方式來顯示Label
    //    [UIView animateWithDuration:2.0 animations:^{
    //        lblMsg.alpha = 0.6;
    //    }];


    // 開啟一個動畫, 這個動畫要執行1.5秒鐘
    [UIView animateWithDuration:1.5 animations:^{
        // 動畫程式碼: 將透明度變成0.6
        lblMsg.alpha = 0.6;

    } completion:^(BOOL finished) {
        // 當上面的動畫執行完畢以後執行這個程式碼

        if (finished) {
            // 這個程式碼的含義是, 隔一段時間後再啟動另外一個動畫
            // 這個動畫的執行時間是1.5秒鐘, 但是這個動畫會在1.0秒之後再開始執行
            // UIViewAnimationOptionCurveLinear表示是勻速執行動畫
            [UIView animateWithDuration:1.5 delay:1.0 options:UIViewAnimationOptionCurveLinear animations:^{
                // 這個動畫的程式碼
                lblMsg.alpha = 0;

            } completion:^(BOOL finished) {
                if (finished) {
                    // 當Label的透明度變成0以後, 再把這個Label從view中移除
                    [lblMsg removeFromSuperview];
                }
            }];
        }
    }];



    // 3. 把lblMsg加到控制器所管理的那個view上
    [self.superview addSubview:lblMsg];

}

- (IBAction)down:(id)sender {
    // 1. 禁用當前被點選的按鈕
    //sender.enabled = NO;

    // 2. 彈出一個訊息提醒框(這個訊息提醒框其實就是一個UILabel)
    UILabel *lblMsg = [[UILabel alloc] init];
    // 2.1 設定lblMsg的顯示文字
    lblMsg.text = @"正在下載...";
    // 2.2 設定lblMsg的背景色
    lblMsg.backgroundColor = [UIColor blackColor];
    // 2.3 設定lblMsg的frame
    CGFloat viewW = self.superview.frame.size.width;
    CGFloat viewH = self.superview.frame.size.height;
    CGFloat msgW = 200;
    CGFloat msgH = 30;
    CGFloat msgX = (viewW - msgW) / 2;
    CGFloat msgY = (viewH - msgH) * 0.5;
    lblMsg.frame = CGRectMake(msgX, msgY, msgW, msgH);
    // 2.4 設定label的文字顏色
    lblMsg.textColor = [UIColor redColor];
    // 2.5 設定label居中顯示
    lblMsg.textAlignment = NSTextAlignmentCenter;
    // 2.6 設定文字粗體
    lblMsg.font = [UIFont boldSystemFontOfSize:17];
    // 2.7 設定Label的透明度
    lblMsg.alpha = 0.0; // 一開始把透明度設定為0, 然後通過動畫的方式慢慢的改變透明度
    // 2.8 設定Label為"圓角"
    // 設定四個角的“半徑”
    lblMsg.layer.cornerRadius = 10;
    // 把多餘的部分裁剪掉
    lblMsg.layer.masksToBounds = YES;

    // 2.9通過動畫的方式來顯示Label
    //    [UIView animateWithDuration:2.0 animations:^{
    //        lblMsg.alpha = 0.6;
    //    }];


    // 開啟一個動畫, 這個動畫要執行1.5秒鐘
    [UIView animateWithDuration:1.5 animations:^{
        // 動畫程式碼: 將透明度變成0.6
        lblMsg.alpha = 0.6;

    } completion:^(BOOL finished) {
        // 當上面的動畫執行完畢以後執行這個程式碼

        if (finished) {
            // 這個程式碼的含義是, 隔一段時間後再啟動另外一個動畫
            // 這個動畫的執行時間是1.5秒鐘, 但是這個動畫會在1.0秒之後再開始執行
            // UIViewAnimationOptionCurveLinear表示是勻速執行動畫
            [UIView animateWithDuration:1.5 delay:1.0 options:UIViewAnimationOptionCurveLinear animations:^{
                // 這個動畫的程式碼
                lblMsg.alpha = 0;

            } completion:^(BOOL finished) {
                if (finished) {
                    // 當Label的透明度變成0以後, 再把這個Label從view中移除
                    [lblMsg removeFromSuperview];
                }
            }];
        }
    }];



    // 3. 把lblMsg加到控制器所管理的那個view上
    [self.superview addSubview:lblMsg];
}
@end
  • 在ViewController裡面載入AFGridItemView.xlib檔案,使用AFGridItemView來接受其中的View控制元件,把之前解析plist檔案得到的AFGridItem資料賦值給對應的AFGridItemView物件的UIImageView,UILabel控制元件上。

具體程式碼如下

#import "ViewController.h"
#import "AFGridItem.h"
#import "AFGridItemView.h"

@interface ViewController ()


// 用來儲存所有應用的資料
@property (nonatomic, strong) NSArray *apps;

@end

@implementation ViewController

// shift + option + command + 左 (摺疊所有的程式碼)
// shift + option + command + 右 (展開所有的程式碼)

// 重寫apps屬性的get方法, 進行懶載入資料
- (NSArray *)apps
{
    if (_apps == nil) {
        // 載入資料
        // 1. 獲取app.plist檔案在手機上的路徑
        NSString *path = [[NSBundle mainBundle] pathForResource:@"app.plist" ofType:nil];

        // 2. 根據路徑載入資料
        NSArray *arrayDict = [NSArray arrayWithContentsOfFile:path];

        // 3. 建立一個可變資料用來儲存一個一個的模型物件
        NSMutableArray *arrayModels = [NSMutableArray array]; // 一個空的可變陣列

        // 4. 迴圈字典陣列, 把每個字典物件轉換成一個模型物件
        for (NSDictionary *dict in arrayDict) {
            // 建立一個模型
            AFGridItem *model = [AFGridItem appWithDict:dict];

            // 把模型加到arrayModels中
            [arrayModels addObject:model];
        }

        _apps = arrayModels;
    }
    return _apps;
}


- (void)viewDidLoad {
    [super viewDidLoad];

    // 假設每行的應用的個數
    int columns = 3;

    // 獲取控制器所管理的view的寬度
    CGFloat viewWidth = self.view.frame.size.width;

    // 每個應用的寬和高
    CGFloat appW = 75;
    CGFloat appH = 90;
    CGFloat marginTop = 30; // 第一行距離頂部的距離
    CGFloat marginX = (viewWidth - columns * appW) / (columns + 1);
    CGFloat marginY = marginX; // 假設每行之間的間距與marginX相等

    for (int i = 0; i < self.apps.count; i++) {

        // 獲取當前這個應用的資料字典
        AFGridItem *appModel = self.apps[i];



        // 1. 通過xib建立每個應用(UIView)
        // 通過動態載入xib檔案建立裡面的view
        // 1.1> 找到應用的根目錄
        NSBundle *rootBundle = [NSBundle mainBundle]; // //NSLog(@"%@", [mainBundle bundlePath]);
        // 1.2> 在應用程式根目錄下取搜尋對應的Xib(nib)檔案
        AFGridItemView *appView = [[rootBundle loadNibNamed:@"AFGridItemView" owner:nil options:nil] lastObject];










        // 2.2 設定appView的frame屬性
        // 計算每個單元格所在的列的索引
        int colIdx = i % columns;
        // 計算每個單元格的行索引
        int rowIdx = i / columns;

        CGFloat appX = marginX + colIdx * (appW + marginX);
        CGFloat appY = marginTop + rowIdx * (appH + marginY);
        appView.frame = CGRectMake(appX, appY, appW, appH);




        // 3. 將appView加到self.view(控制器所管理的那個view)
        [self.view addSubview:appView];


//        // 4. 設定appView中的子控制元件的資料
//                UIImageView *imgViewIcon = (UIImageView *)[appView viewWithTag:1000];
//                imgViewIcon.image = [UIImage imageNamed:appModel.icon];

        //        UILabel *lblName = (UILabel *)[appView viewWithTag:2000];
        //        lblName.text = appModel.name;


        //        appView.imgViewIcon.image = [UIImage imageNamed:appModel.icon];
        //        appView.lblName.text = appModel.name;

        // 設定資料
        // 把模型資料設定給“自定義view”的model屬性
        // 然後重寫model屬性的set方法, 在set方法中解析模型物件中的屬性, 並把屬性值設定給自定義view的各個子控制元件
        appView.model = appModel;

    }



}

// 按鈕的單擊事件
- (void)btnDownloadClick
{
    NSLog(@"下載按鈕被點選了。。。。");
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end