高效的iOS布局框架

2019-10-22  本文已影响0人  Milker

介绍

MKYogaLayout是一个布局工具, 布局引擎是Facebook开发的Yoga跨平台布局框架.
使用该框架进行iOS上的布局搭建,能够具备高效和维护方便等特点

为什么要开发这个?

该框架的特点

GitHub传送门

集成方式

// pods

使用

基本使用

/// 定义Layout结构
NSDictionary *layout = @{
        kLView: UIView.class, // 指定视图类型
        kLBg: @"#00FF00",     // 视图属性
        kLPadding: @20,       // 视图布局属性
        kLSubviews: @[        // 子视图
                @{
                        kLView: UILabel.class,
                        kLAlias: @"userName", // 视图注入别名
                        kLStyle: @"button1",  // 样式名称
                        kLText: @"{{name}}",  // 数据绑定
                }
        ]
};
// 在 self.view 内创建视图
[UIView createSubViewsByLayout:layout rootView:self.view context:self style:nil data:nil];

// 上述代码将在self.view中创建一个Label, 并且设置self.view的背景色和内边距

样式表

将同样的属性进行先声明,然后使用的时候指定样式名称即可;
样式表可以统一多个页面或整个App的UI效果,也可让布局代码更加的简短,方便后期进行整体修改。
样式表分为局部样式表和全局样式表。

全局样式表声明

// Key: 值为样式名称
// Value: 样式集合
NSDictionary *styles = @{  
        @"item": @{
                kLBg: @"#eeeeee",
                kLBg_Highlight: @"#999999",
                kLPaddingVertical: @30,
                kLAlignItems: @(YGAlignCenter),
                kLTextAlignment: @(NSTextAlignmentCenter),
        },
        @"item2": @{
               ...
        }
};

[MKYoga registerStyle:styles];

样式表使用

NSDictionary *layout = @{
        ...
        kLSubviews: @[        // 子视图
                @{
                        kLView: UILabel.class,
                        kLStyle: @"item ",  //  指定单个样式
                },
                @{
                        kLView: UILabel.class,
                        kLStyle: @"item item2",  // 指定多个样式
                }
        ]
};

局部样式表

/// 声明
NSDictionary *mPageStyles = @{
        @"nickname": @{
            ...
        }
};

NSDictionary *layout = @{
        ...
        kLSubviews: @[
                @{
                        kLView: UILabel.class,
                        kLStyle: @"nickname", // 指定局部样式表名称
                },
                @{
                        kLView: UILabel.class,
                        kLStyle: @"item",  //  指定单个样式
                },
                @{
                        kLView: UILabel.class,
                        kLStyle: @"item item2 nickname",  // 混合指定多个样式
                }]
};

[UIView createSubViewsByLayout:layout rootView:self.view context:self style:mPageStyles data:nil];

样式表生效优先级

若指定了多个样式表,且多个样式表存在同样属性的设置,此时优先级规则如下:

布局内样式 > kLStyle 声明的样式表;
若kLStyle是多个样式,则靠后的样式覆盖前面样式。

View注入

使用MKYogaLayout时,子视图是不需要我们初始化的,但很多业务还是会用到子视图,就可以使用视图注入的方式进行操作

@interface ViewController ()
@property (nonatomic, strong) UILabel *nickname;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    NSDictionary *layout = @{
            ...
            kLSubviews: @[
                    @{
                            kLView: UILabel.class,
                            kLAlias: @"nickname", // 将这个UILabel 注入到 self.nickname 内
                            ...
                    },
                    ...
            ]
    };
    [UIView createSubViewsByLayout:layout rootView:self.view context:self style:nil data:nil];

    // some code
    self.nickname.hidden = YES;
}

注入时,一定要传入context对象

事件

使用MKYogaLayout时,所有视图都将具有点击事件

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    NSDictionary *layout = @{
            ...
            kLSubviews: @[
                    @{
                            kLView: UILabel.class,
                            kLBindTap: @"gotoUserPage" // 绑定事件名,这里没有 ":"
                            ...
                    },
                    ...
            ]
    };
    [UIView createSubViewsByLayout:layout rootView:self.view context:self style:nil data:nil];
}

// 事件执行, sender 为事件发送的视图
- (void)gotoUserPage:(id)sender {
    // some code
}

@end

绑定事件时,一定要传入context对象

图片代理 & 路由代理

如果您的App使用的第三方的图片加载器/路由框架,可以在初始化MKYoga的时候,设置代理,进行图片加载,该代理为全局代理。


@interface AppDelegate () <MKYogaDelegate> // 代理
@end

@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    ...
    [[MKYoga shareInstance] setDelegate:self];
    return YES;
}

// value: 为配置的图片地址
// style: 为该视图的样式集合
- (void)mkYogaNetworkImageLoader:(UIView *)view value:(NSString *)value style:(NSDictionary *)style {
    // 进行图片加载
}

- (void)mkYogaRouterEvent:(UIView *)view value:(NSURL *)value {
    // 进行路由跳转
}
@{
        kLView: UIImageView.class,
        kLUri : @"app://module/fun1?xx1=1", // 配置路由
        kLImagePath: @"https://xxxxx.jpg",   // 设置图片地址
        ...
}

视图附加对象

有些业务开发时,多个视图会配置同一个点击事件,但是由于视图不一样,会做不同的处理,此时可以给视图绑定附加对象

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    NSDictionary *layout = @{
            ...
            kLSubviews: @[
                    @{
                            kLView: UILabel.class,
                            kLBindTap: @"gotoUserPage",
                            kLObj: @"101"
                            ...
                    },
                    @{
                            kLView: UILabel.class,
                            kLBindTap: @"gotoUserPage"
                            kLObj: @"102"
                            ...
                    },
                    ...
            ]
    };
    [UIView createSubViewsByLayout:layout rootView:self.view context:self style:nil data:nil];
}

// 事件执行, sender 为事件发送的视图
- (void)gotoUserPage:(id)sender {
    NSString *uId = sender.view.obj;
    // do some biz
}

@end

数据绑定

使用{{ expression }},用以区分是普通文字还是表达式。

NSDictionary *layout = @{
        ...
        kLSubviews: @[
                @{
                        kLView: UILabel.class,
                        kLText: @"{{title}}",
                        kLMarginLeft: @20,
                },
                @{
                        kLView: UILabel.class,
                        kLText: @"{{age}}",
                        kLMarginLeft: @20,
                },
                @{
                        kLView: UILabel.class,
                        kLText: @"{{info.school.name}}",
                        kLMarginLeft: @20,
                }
        ]
};

model = [MPDataModel new];
model.title = @"Milker";
model.age = 12;
model.info = @{
        @"school": @{
                @"name": @"MIT",
                @"address": @"USA"
        }
};
[UIView createSubViewsByLayout:layout rootView:self.view context:self style:nil data:model];

常用表达式:

视图更新:

model.title = @"Milker"; = @"Jack";
[self.view updateViewWithData:model];

常用属性说明

FlexBox布局属性

通用属性

UIView

UILabel

UIButton

UIImageView

UIScrollView

由于UIScrollView的特殊性,封装了一层,可以方便使用

...

很简单的效果

image.png
上一篇 下一篇

猜你喜欢

热点阅读