QMUI / QMUI_iOS框架学习(二)

lauch图加载完成后,开始做tabbar控制器的部分

- (void)createTabBarController {
    UIViewController *viewController = [[UIViewController alloc] init];
    viewController.view.backgroundColor = [UIColor whiteColor];
    self.window.rootViewController = viewController;
    [self.window makeKeyAndVisible];
}

将这个view 改成tabbarcontroller,发现tabbar控制器放在子文件夹里面,于是创建所有必须的文件夹,并add到项目里面去,将QMUIConfigurationTemplate 也移动到configure文件夹下

新建 QDTabBarViewController 继承自 QMUITabBarViewController 使用的是QMUI的模板 发现里面没写什么内容 。还需要添加一个导航控制器QDNavigationController ,注意到也是一行没写。
然后是导航栏下的根控制器 QDUIKitViewController

发现继承关系

  1. QMUICommonViewController
    1. – QDCommonViewController
      1. – QDCommonGridViewController
        1. – QDUIKitViewController

于是按顺序创建 这三个子类 控制器
首先是 QDCommonViewController
只设置了背景色 self.view.backgroundColor = UIColorWhite;
然后是QDCommonGridViewController

#import "QDCommonViewController.h"

@interface QDCommonGridViewController : QDCommonViewController

@property(nonatomic, strong) QMUIOrderedDictionary *dataSource;//重写字典做数据源
@property(nonatomic, strong, readonly) QMUIGridView *gridView; //九宫格图表


@end

@interface QDCommonGridViewController (UISubclassingHooks) //子类钩子类别
// 子类继承,可以不调super
- (void)initDateSource;//初始化数据源
- (void)didSelectCellWithTitle:(NSString *)title;//选中cell以及cell的标题
@end

这是通用九宫格的父类,可以看到数据源是自定义的字典,ui是自定义view,使用方式应该是依靠子类调用category来实现的。先不深究QMUIOrderedDictionaryQMUIGridView 这两个自定义类,在实现里面具体看这两个类的使用。

#import "QDCommonGridViewController.h"

@interface QDCommonGridViewController ()
@property(nonatomic, strong) UIScrollView *scrollView;
@end

@interface QDCommonGridButton : QMUIButton

@end

@implementation QDCommonGridViewController

- (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
    if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {
        [self initDateSource];
    }
    return self;
}

- (void)initSubviews {
    [super initSubviews];
    self.scrollView = [[UIScrollView alloc] init];
    [self.view addSubview:self.scrollView];

    _gridView = [[QMUIGridView alloc] init];
    for (NSInteger i = 0 , I = self.dataSource.count; i<I; i++) {
        [self.gridView addSubview:[self generateButtonAtIndex:i]];
    }
    [self.scrollView addSubview:self.gridView];
}

- (QDCommonGridButton *)generateButtonAtIndex:(NSInteger)index{
    NSString *keyName = self.dataSource.allKeys[index]; //key数组
    NSAttributedString *attributedString = [[NSAttributedString alloc] initWithString:keyName attributes:
                                            @{NSForegroundColorAttributeName: UIColorGray, NSFontAttributeName: UIFontMake(11), NSParagraphStyleAttributeName: [NSMutableParagraphStyle qmui_paragraphStyleWithLineHeight:12 lineBreakMode:NSLineBreakByTruncatingTail textAlignment:NSTextAlignmentCenter]}];
    UIImage *image = (UIImage *)[self.dataSource objectForKey:keyName];

    QDCommonGridButton *button = [[QDCommonGridButton alloc] init];
    [button setAttributedTitle:attributedString forState:UIControlStateNormal];
    [button setImage:image forState:UIControlStateNormal];
    button.tag = index;
    [button addTarget:self action:@selector(handleGirdButtonEvent:) forControlEvents:UIControlEventTouchUpInside];
    return button;

}

- (void)handleGirdButtonEvent:(QDCommonGridButton *)button {
    NSString *keyName = self.dataSource.allKeys[button.tag]; //key数组
    [self didSelectCellWithTitle:keyName];
}

以上代码是初始化界面,初始化子界面,初始化子界面的button,给button添加响应事件,其中

[self initDateSource];
[self didSelectCellWithTitle:keyName];

都调用了QDCommonGridViewController (UISubclassingHooks)分类的方法,虽然方法还没实现,不影响调用。

@implementation QDCommonGridViewController (UISubclassingHooks)

- (void)initDataSource {

}

- (void)didSelectCellWithTitle:(NSString *)title {

}

这个分类写法很特别,先是给控制器添加分类,同时在分类实现中不添加任何代码。应该是要子类化中重写实现,看方法名很容易理解到,是要在这两个方法里面设置数据源,以及点击回传的事件,这样就实现了界面和逻辑的分离。这种写法和直接写方法又有什么不同呢?

NSString *keyName = self.dataSource.allKeys[index]; //key数组` 

说明数据源的keyname就是title,index是数据源的第几个,

`UIImage *image = (UIImage *)[self.dataSource objectForKey:keyName];`

说明title 对应的value是image的对象。

然后是创建自定义button

@implementation QDCommonGridButton
- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        self.contentEdgeInsets = UIEdgeInsetsMake(0, 10, 0, 10);
        self.imageView.contentMode = UIViewContentModeCenter;
        self.titleLabel.numberOfLines = 2;
        self.highlightedBackgroundColor = TableViewCellSelectedBackgroundColor;
        self.qmui_needsTakeOverTouchEvent = YES; // 解决滚动视图和点击视图延时问题
        self.qmui_borderPosition = QMUIBorderViewPositionRight | QMUIImageBorderPositionBottom;
    }
    return self;
}

- (void)layoutSubviews {
    // 不用父类的, 自己计算
    [super layoutSubviews];

    if (CGRectIsEmpty(self.bounds)) {
        return;
    }

    CGSize contentSize = CGSizeMake(CGRectGetWidth(self.bounds) - UIEdgeInsetsGetVerticalValue(self.contentEdgeInsets),
                                    CGRectGetHeight(self.bounds) - UIEdgeInsetsGetVerticalValue(self.contentEdgeInsets));
    CGPoint center = CGPointMake(flat(self.contentEdgeInsets.left + contentSize.width/2),flat(self.contentEdgeInsets.top + contentSize.height / 2));
    self.imageView.center = CGPointMake(center.x, center.y - 12);

    CGSize titleLabelSize = [self.titleLabel sizeThatFits:contentSize];
    self.titleLabel.frame = CGRectFlatMake(self.contentEdgeInsets.left, center.y + PreferredVarForDevices(27, 27, 21, 21), contentSize.width, titleLabelSize.height);

}

这里有两个关键点

        self.qmui_needsTakeOverTouchEvent = YES; // 解决滚动视图和点击视图延时问题

进去看了一下是对button的很多事件做了优化,防止二次点击,手势响应冲突等,没有细看

    CGSize contentSize = CGSizeMake(CGRectGetWidth(self.bounds) - UIEdgeInsetsGetHorizontalValue(self.contentEdgeInsets), CGRectGetHeight(self.bounds) - UIEdgeInsetsGetVerticalValue(self.contentEdgeInsets));

重新设置了label的contsize 应该是保证label和父类的边距问题。

    CGPoint center = CGPointMake(flat(self.contentEdgeInsets.left + contentSize.width / 2), flat(self.contentEdgeInsets.top + contentSize.height / 2));
    CGSize titleLabelSize = [self.titleLabel sizeThatFits:contentSize];

重新设置了contentsize以后的中心点

 self.titleLabel.frame = CGRectFlatMake(self.contentEdgeInsets.left, center.y + PreferredVarForDevices(27, 27, 21, 21), contentSize.width, titleLabelSize.height);

然后重写了frame 这里注意到 有用到flat 里面是像素级的适配,具体还要再细看,可以看出对适配的严谨。

- (void)viewDidLayoutSubviews {
    [super viewDidLayoutSubviews];
    self.scrollView.frame = self.view.bounds;

    if(CGRectGetWidth(self.view.bounds) <= [QMUIHelper screenSizeFor55Inch].width){
        self.gridView.columnCount = 3;
        CGFloat itemWidth = flat(CGRectGetWidth(self.scrollView.bounds) / self.gridView.columnCount);
        self.gridView.rowHeight = itemWidth;
    } else {
        CGFloat minimumItemWidth = flat([QMUIHelper screenSizeFor55Inch].width /3.0);
        CGFloat maximumItemWidth = flat(CGRectGetWidth(self.view.bounds))/5.0;
        CGFloat freeSpacingWhenDisplayingMinimumItemCount = CGRectGetWidth(self.scrollView.bounds) / maximumItemWidth - floor(CGRectGetWidth(self.scrollView.bounds)/maximumItemWidth);
        CGFloat freeSpacingWhenDisplayingMaximumItemCount = CGRectGetWidth(self.scrollView.bounds) / minimumItemWidth - floor(CGRectGetWidth(self.scrollView.bounds)/minimumItemWidth);
        if (freeSpacingWhenDisplayingMinimumItemCount < freeSpacingWhenDisplayingMaximumItemCount) {
            // 按照每行最少item的情况来布局的话,空间利用率会更高,所以按照最少item来
            self.gridView.columnCount = floor(CGRectGetWidth(self.scrollView.bounds) / maximumItemWidth);
            CGFloat itemWidth = floor(CGRectGetWidth(self.scrollView.bounds) / self.gridView.columnCount);
            self.gridView.rowHeight = itemWidth;
        } else {
            self.gridView.columnCount = floor(CGRectGetWidth(self.scrollView.bounds) / minimumItemWidth);
            CGFloat itemWidth = floor(CGRectGetWidth(self.scrollView.bounds) / self.gridView.columnCount);
            self.gridView.rowHeight = itemWidth;
        }
    }

    CGFloat gridViewHeight = [self.gridView sizeThatFits:CGSizeMake(CGRectGetWidth(self.scrollView.bounds), CGFLOAT_MAX)].height;
    self.gridView.frame = CGRectMake(0, 0, CGRectGetWidth(self.scrollView.bounds), gridViewHeight);
    self.scrollView.contentSize = CGSizeMake(CGRectGetWidth(self.scrollView.bounds), CGRectGetMaxY(self.gridView.frame));
}

这段代码设置了self.gridView 的子视图的一些参数

[QMUIHelper screenSizeFor55Inch].width

这是适配竖屏手机,直接设置,其余部分应该是适配横屏和ipad,

使用了floor 向下取整 CGFLOAT 取最大值,CGRectGetMaxY 取最大值,很多地方都有类似处理

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值