QMUI / QMUI_iOS框架学习(二)

RxSwiftProject:迅捷RxSwift + Moya + MVVM RxSwift + Moya + MVVM 项目使用了QMUI框架 ,使用时的配置: 查看“如何使用配置表”一栏 如果报错 "No type or protocol named 'QMUIConfigurationTemplateProtocol'", 请在QMUIConfigurationTemplate.h中#import <QMUIKit> 立即下载

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来实现的。先不深究QMUIOrderedDictionary 和QMUIGridView 这两个自定义类,在实现里面具体看这两个类的使用。

#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 取最大值,很多地方都有类似处理

QMUI iOS功能 作者QMUI,源码QMUI_iOS,QMUI iOS——致力于提高项目 UI 开发效率的解决方案 http://qmuiteam.com/ios 立即下载

相关推荐

PopupMenuView-master:点击弹出popwindow

PopupMenuView 此库主要实现了一个类似iOS中的UIMenuController控件的Popup控件。 主要控件如下: PopLayout继承自FrameLayout,用于实现控件的气泡化。 OptionMenuView继承自LinearLayout,用于实现Menu控件。 PopupView继承自PopupWindow,用于实现控件的指定方位弹出效果。 PopupMenuView是上述三者的集合,实现了弹出气泡菜单的功能。 Demo 安装 文件预览效果,或者通过下面二维码去下载安装: Usage Use Gradle: compile 'me.kareluo.ui:popmenu:1.1.0' Or Maven: <dependency> <groupId>me.kareluo.ui</groupId> <artifactId>popmenu</artifactId

推荐开源项目:QMUI_iOS —— 腾讯出品的高效iOS开发框架

QMUI_iOS 是腾讯推出的一款强大的 iOS 开发框架,旨在提升开发者们在构建用户界面时的效率和质量。 提供了丰富的 UI 组件、工具类以及设计模式,帮助开发者快速构建出美观且统一的应用界面。 ## 技术分析 ### 1. 组件丰富 QMUI_iOS 包含了大量的 UI 控件,如表格视图、导航栏、标签页等,它们都经过精心设计和优化,易于集成,且性能优良。这些组件不仅可以节省开发时间,还能...

gitblog_00053的博客 895

QMUI iOS——致力于提高项目 UI 开发效率的解决方案.zip

IOS开发

QMUI / QMUI_iOS框架学习(六)

微信的导航条的中心栏是可以处理多种状态的显示,有导航栏的界面都可以使用,研究一下他的源码。 拆出来花了很大的功夫,原因是相互之间层级引用太复杂了 。 有个QMUICommonViewController 类 里面引用了#import "QMUINavigationController.h" QMUINavigationTitleView 其中 QMUINavigationController 不

github_35041937的博客 1580

MATLAB2021b详细安装教程

1.下载 2.安装 下载安装包后打开iso文件,若是无法打开请用解压软件打开。 ①打开MATLAB_R2021b_win64,双击软件开始安装 ② 一直点击下一步,直到步骤③ ③选择我已有我的许可证的文件密钥,并输入62551-02011-26857-57509-64399-54230-13279-37181-62117-65158-40352-64197-45508-24369-45954-39446-39538-16936-10698-58393-44718-32560-10501-40

惜洛-Jankin的博客 9万+

保姆级教程:用WorkVisual 6.0给你的KUKA机器人硬件做一次‘全身体检’与配置检查

本文详细介绍了如何使用WorkVisual 6.0对KUKA机器人进行全面的硬件诊断与配置检查。从环境准备到核心硬件模块检查,再到安全系统合规性验证,提供了保姆级教程,帮助技术团队快速掌握数字化诊断方案,提升工业机器人的健康管理效率。

weixin_27298377的博客 279

SQL Server中 Case When 函数 与 Access中 IIF 函数的应用

SQL Server中的判断语句: case  判断对象  when   判断条件   then   条件为真的场合返回的结果  else  其他的场合返回的结果 end  首先让我们看一下 CASE 的语法。在一般的 SELECT 中,其语法如下: SELECT myColumnSpec> = CASE WHEN A> THEN something

bigheadsheep的专栏 1839

shader基于高度的权重混合

效果图: 基于高度的权重混合 , 效果描述: (1)混合:三层混合, 例如 第一层是草,第二层是石头,第三层是沙子,三者混合显示 (2)权重: 三层的权重的和 为1, 三者是此消彼长的关系 (3)高度:高度会限制或者说是 束缚 着 效果 关于混合,再多说几句: (1)基于权重的混合:权重 ,跟顺序没有关系 只跟权重的大小有关系(在一层一层界限不清晰的地方,特别适用!!效果极好!!!!) (2)基于叠加的混合: 叠加 就是 一层一层的往上加。。。。 所以顺序特别重要(在雪地等效果中使用:因为

木马人 1119

accesd和mysql语法区别_SQL Server和Access中的条件判断语法(case when和iff)

很多时候为了程序的可扩展性和准确性等我们会在数据库中把对应bool类型或string类型的字段设置为int型。但是在程序中显示的时候我们希望能显示用户友好的内容,这个时候我们就需要把查找到的结果转换成用户友好的结果。要达到这个目的有几种方法可行,可以在很多时候为了程序的可扩展性和准确性等我们会在数据库中把对应bool类型或string类型的字段设置为int型。但是在程序中显示的时候我们希望能显示用...

weixin_30365817的博客 517

电机驱动技术中关于磁阻转矩生成的理解

正交在物理学和数学中指的是两个方向或两个向量之间的夹角为90°(直角)。在图中,当气隙磁场的轴线与转子轴线的夹角为90°时,我们称它们为正交。转子磁极的方向。通常由转子的磁极中心指向另一极的连线表示。转子轴线用图示中的d 轴表示。通过对定子、转子、气隙磁场、磁力线的理解,我们可以清晰地分析不同角度下电磁转矩的方向。这种分析不仅有助于电机的理论学习,还能为实际设计提供重要参考。掌握这些基础知识后,可以更好地理解电机工作原理及优化其性能。

weixin_48327795的博客 2076

大模型——CoPaw:阿里云通义推出的个人智能体工作台,让 AI 助理真正落地

阿里云通义实验室于2026年2月发布CoPaw个人智能助理,采用"本地+云端"双部署模式,支持多平台接入和技能扩展。该产品基于AgentScope多智能体生态构建,具备极简部署、长期记忆系统和灵活的技能插件体系三大核心特性。用户可通过简单命令快速安装,并通过记忆文件系统实现个性化交互体验。CoPaw还支持钉钉、飞书等主流平台接入,并开源了模块化架构,允许本地模型接入。技术架构采用多频道对话网关与可插拔Skills系统,为用户提供真正的AI助理服务体验。

2137

SQL Server数据库和Access数据库的"DECODE"函数问题

作为长期在Oracle下开发的程序员来说,没有DECODE是非常可怕的事情。正巧最近做的自己的小工具的时候,需要在SQL Server和Access实现DECODE函数的功能。查了一下资料,汇总如下: 在SQL Server环境下,使用CASE ... WHEN ... END 进行处理,例子如下:     SELECT 'Price Category' =

大蚂蚁的技术窝 1741

使用verilog设计实现QR分解

QR(正交三角)分解法是求一般矩阵全部特征值的最有效并广泛应用的方法,一般矩阵先经过正交相似变化成为Hessenberg矩阵,然后再应用QR方法求特征值和特征向量。 使用verilog对QR实现方法进行设计并进行功能仿真: 如下: 顶层模块代码: module TOP( H1R, H1I, H2R, H2I, H3R, H3I, H4R, H4I, clk, rst_n, Y1R, Y1I, Y2R, Y2I, X1R, X1I, X2R, X2I ); parameter width = 16; // I

QQ_778132974的博客 2152

access转sql iif_Access中IIF,SWITCH,CHOOSE的使用技巧

在Access数据库中,很多SQL语句都是和sqlServer通用的。但是也有部分不能使用的函数两者是不相通的。例如:SELECT UserPassportID as PassportID, UserID CaseObjectTypeID When1 thenObjectIDEnd as TerminalID, Invalidate From UserPassport此语句在SQL里是能运行的,...

weixin_33235339的博客 618

工业仪表读数识别:YOLO目标检测 + OCR混合方案实战

仪表整体(meter):粗定位整只仪表,用于快速裁剪、排除背景干扰表盘区域(dial):精确的圆形/方形表盘区域,用于后续矫正和读数数字区域(display)/指针(pointer):数显表定位数码管区域,指针表可辅助定位指针为什么要分三级?因为现场仪表安装角度、距离、光照差异极大。先粗检再精检,比一步到位的准确率高很多,也方便后续做透视变换。工业仪表读数识别,技术路线的选择比算法精度更重要。选对了路线,事半功倍;选错了,怎么调都达不到验收标准。几条落地建议:指针表优先传统算法。

专注于Python爬虫开发,分享爬虫技巧、项目实战与反爬经验,使用Scrapy、BeautifulSoup等工具,解决数据抓取难题。 96

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

SQLServer VS Access常用SQL函数区别

SQLServer                   AccessCASE...WHEN...             IIF()   SUBSTRING()                 MID()   ISNULL()                       IIF(IS NULL) SQLServer:select * from [user] wher

870

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

sql 按字段指定值排序

比如数据库表table1中有为A1的字段名,A1中的值只有如下几种情况:a1,a2,a3,现需按a2,a3,a1的顺序排序在MSSQL支持CASE,使用以下语句实现SELECT 表1.id, 表1.nFROM 表1ORDER BY CASE n WHEN 'a2' THEN 1 WHEN 'a1' THEN 2 WHEN 'a3' THEN 3 END;在Access中使用IIF来实现,如下:SE...

weixin_34010949的博客 573

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

Access与Sql Server之ASP代码比较

后台数据库: [Microsoft Access] 与 [Microsoft Sql Server] 更换之后,ASP代码应注意要修改的一些地方: [一]连接问题(举例) [Microsoft Access] constr = "DBQ=c:/data/clwz.mdb; DRIVER={Microsoft Access Driver (*.mdb)}" [Microsoft Sql Server

太阳星辰.优快云 1245

ACCESS/SQLSERVER SQL语句语法对照

          SQL 语句 描述 SQL SERVER ACCESS 截取字符串 SUBSTRING MID 查询判断字段是否为NULL,若为NULL值则显示规定值,非NULL值显示其本身值 ISNULL(FRM_M3_40,'1') IIF...

weixin_30906701的博客 105

ACCESS改为SQL需要注意哪几个地方(转)

Access与Sql Server之ASP代码比较 后台数据库: [Microsoft Access] 与 [Microsoft Sql Server] 更换之后,ASP代码应注意要修改的一些地方: [一]连接问题(举例) [Microsoft Access] constr = "DBQ=c:/data/clwz.mdb; DRIVER={Microsoft Access Dr

zhanghq1的专栏 1240

一个按年季度查询数据的SQL语句

chinmo的收藏 1万+

Access与SQL Server

Access与SQL Server 假如表M中的字段A中是这样的字符串:'YYUU;GGKK'在Access中这样得到YYUU与GGKKiif(InStr(A,';')=0, A, Left(A,InStr(A,';')-1))Right(A,Len(A)-InStr(A,';'))在SQL Server中这样得到YYUU与GGKKCASE W...

weixin_30511039的博客 75

Sql语句在Access数据库中能查到结果, 写在程序中查不到结果(或者得到的结果全是0) --- 通配符的问题, Access的"case when"...

Access中的语句: Sql Server通配符: % 多个    _1个 Accesss通配符: *多个    ?1个 ------- Access中能执行 SELECT T_StockNoticeInfo.StockID, IIf(CreateTime Like '2011/10/14 ??:??:??',format(LeadingStockIndex,'0.00'),forma...

weixin_34006965的博客 380
上一篇: xcode 代码块永久保留
下一篇: ios 跳转safari
csdn_Damon
博客等级 码龄11年 37粉丝 143原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值