Okogeki'sブログ

デキるエンジニアを目指すOkogekiのブログ

Bootstrapのグリッドシステム実現をObjective-Cで頑張る

BootstrapのGridってすごく便利ですよね。

一方Objective-CはいちいちCGRectmakeでx,y,width,height指定しーので面倒です。
頼みのAutolayoutもユニバーサルアプリだと逆に実装に時間がかかったり、
制約も多くて面倒です。

Bootstrapくらい気軽にできたらなーっと思ったので先ほどさくっと
BootstrapGridSystem風UIViewのGridViewクラスを作ってみました。

クラス実装部

GirdView.h
#import <UIKit/UIKit.h>
typedef enum : NSInteger {
    COL_01 = 1,
    COL_02 = 2,
    COL_03 = 3,
    COL_04 = 4,
    COL_05 = 5,
    COL_06 = 6,
    COL_07 = 7,
    COL_08 = 8,
    COL_09 = 9,
    COL_10 = 10,
    COL_11 = 11,
    COL_12 = 12
} COL;

@interface GridView : UIView
-(void)addSubview:(UIView *)view viewHeight:(CGFloat)height usingGridNum:(COL)gridNum margin:(COL)margin;

@end
GirdView.m
#import "GridView.h"

@implementation GridView{

    NSInteger totalCol;
    CGFloat heightMax;
    CGFloat currentYposition;

}

- (id)init {
    self = [super init];
    if (!self){
        return nil;
    }
    
    totalCol = 0;
    heightMax = 0;
    currentYposition = 0;
    
    return self;
}

-(void)addSubview:(UIView*)view viewHeight:(CGFloat)height usingGridNum:(COL)gridNum margin:(COL)margin{
    
    //前処理
    if((totalCol+gridNum+margin) > 12){
        currentYposition += heightMax;
        totalCol = 0;
        heightMax = 0;
    }
    totalCol += margin;
    
    //リサイズ実行
    view.frame = CGRectMake(totalCol*(self.frame.size.width/12), currentYposition, (self.frame.size.width/12)*gridNum,height);
    
    //後処理
    totalCol += gridNum;
    if(heightMax <= height){
        heightMax = height;
    }
    
    //Viewに追加
    [self addSubview:view];
   
}

@end

使い方例

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    
    CGRect rect = CGRectMake(0, self.navigationController.navigationBar.frame.size.height+22, self.view.frame.size.width, self.view.frame.size.height);
    
    GridView*mainView = [[GridView alloc]initWithFrame:rect];
    [self.view addSubview:mainView];
    GridView*subView1 = [[GridView alloc]init];
    subView1.backgroundColor = [UIColor grayColor];
    GridView*subView2 = [[GridView alloc]init];
    subView2.backgroundColor = [UIColor yellowColor];
    GridView*subView3 = [[GridView alloc]init];
    subView3.backgroundColor = [UIColor redColor];
    GridView*subView4 = [[GridView alloc]init];
    subView4.backgroundColor = [UIColor blueColor];
    UILabel* label = [[UILabel alloc]init];
    label.text = @"test";
    
    [mainView addSubview:subView1 viewHeight:200 usingGridNum:COL_04 margin:COL_02];
    [subView1 addSubview:subView2 viewHeight:50 usingGridNum:COL_06 margin:COL_01];
    [mainView addSubview:subView3 viewHeight:30 usingGridNum:COL_11 margin:COL_01];
    [mainView addSubview:label viewHeight:50 usingGridNum:COL_12 margin:0];
    [mainView addSubview:subView4 viewHeight:200 usingGridNum:COL_12 margin:0];
    
}


こんな感じで書くと実際にはこんな画面になります。
f:id:okogeki:20150205001344p:plain





GirdSystem風に配置できてます。入れ子もできてますね。
例ではLabelも入れてますが、実際にはAddsubViewできるものならUIbuttonでも何でも大丈夫です。
こいつらも入れ子にして入れてもオーケー。

ただし、今回の例の場合、子要素が親要素より大きい高さを指定された時は考慮してませんし、
マージンと使用グリッド数が12を超えた場合も考慮してません。
レスポンシティブ対応もしてません。
レスポンシティブ以外はすぐにでも書けそうですが、まとめて対応したいので
今度ゆっくり考えてみます。

とはいうものの、
静的な利用であれば今回のものでも十分使い物になるかと思います。
ちょっとしたもの書きたいだけなのに毎回CGRectMakeだのAutoLayout設定だのが面倒な方には
おすすめです。