文章目录

摘要:

####一、业务需求
年后回来,公司的一个项目要在系统设置添加“切换主题”(后来改为在首页导航栏右侧)的功能,就是点进去后可以选择App的主题颜色,并且立即生效。对这个需求,公司的其他项目都还没有实现过。

####二、准备和寻求帮助
在接手第一个项目之前,看代码时就看到过交易控制器里面有一段有关切换主题颜色的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
-(NSArray *)listNotificationInter {
NSMutableArray *list = [NSMutableArray arrayWithArray:[super listNotificationInter]];
[list addObject:NOTE_THEME_CHANGED];
return list;
}
-(void)handleNotification:(NSNotification *)notification{
NSString *name = notification.name;
if ([name isEqualToString:NOTE_THEME_CHANGED]) {
NSString *theme = notification.object;
NSInteger skin = 0 ;
if ([theme isEqualToString:@"theme1"]||[theme isEqualToString:@"theme3"]) {
skin = 1;
}
[_tradeH5Service iosCallJsToChangeSkin:@"trade" theme:skin callBackFunc:^(ResultVo *resultVo) {
}];
} else {
[super handleNotification:notification];
}
}

再加上,公司基本上所有项目都是标准版拿过来进行定制化改造的,然后标准版都有/TKApp/resource/theme/这个目录,这个目录下有commontheme1theme2theme3等文件夹,文件夹下面就是2、3个.css文件,里面都是颜色值和图片名称。所以我猜测,公司iOS框架是支持换肤的!

####三、执行与效果
很显然,上面的代码是调用接口来通知trade模块去改变主题的。

但是框架是如何改变原生控件的颜色的呢?

  • 【1】

首先我们注意到,框架的Configuration_xxx.xml配置文件设置了一个默认的主题:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?xml version="1.0" encoding="UTF-8"?>
<system>
<catalog name="system" description="系统配置">
//... ...
<item name="theme" value="theme1" description="默认主题名称" />
//... ...
</catalog>
//... ...
<catalog name="theme" description="主题配置">
<item name="theme1" value="blueTheme.css|blueHq.css|hqRedGreen.css|blueTrade.css" description="主题1样式文件地址" />
<item name="theme4" value="redTheme.css|bightHq.css|hqGreenRed.css" description="主题4样式文件地址" />
<item name="theme3" value="blueTheme.css|blueHq.css|hqGreenRed.css" description="主题3样式文件地址" />
<item name="theme5" value="pinkTheme.css|pinkHq.css|hqRedGreen.css" description="主题5样式文件地址" />
</catalog>
//... ...
</system>

其中theme1对应的颜色值文件分别是blueTheme.cssblueHq.css
hqRedGreen.cssblueTrade.css

  • 【2】

接下来我打算找一个在blueTheme.css文件中有用到的颜色值并跟实际控件对比看看。比如‘资讯详情分享按钮’:

1
2
3
4
5
6
7
8
/* blueTheme.css */
/*资讯详情分享按钮*/
.informationShareButton {
/*文字颜色*/
color:white;
/*背景色 天蓝*/
background-color: #E15A53;
}

保持上面的配置,运行App,资讯详情页面的截图与对应的代码如下:
资讯详情页面

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#import "TKInfoShareButton.h"
@implementation TKInfoShareButton
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self addCssClass:@".informationShareButton"];
[self setUpInfoShareButton];
}
return self;
}
// to do ... ...

拿测色计取色结果对比下

验证正确!说明配置才.css文件中的颜色值,都是通过addCssClass:方法来改变对象的属性颜色的。查看该方法的类:

可知框架是扩展了UIView,对UIView的子类实例进行颜色设置的。

  • 3

最后,关键的一步是,我们怎么来切换主题,并且能让设置立即生效呢?

记得系统设置中的【行情显示设置】里面的红涨绿跌绿涨红跌中的代码是这样写的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/**
* @Author 刘鹏民, 15-04-21 17:04:32
* @brief
* @param tableView
* @param indexPath
*/
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if(cell == _defaultSelected ){
return;
}
[cell setAccessoryType:UITableViewCellAccessoryCheckmark];
[_defaultSelected setAccessoryType:UITableViewCellAccessoryNone];
_defaultSelected = cell;
NSString *theme = [TKThemeManager shareInstance].theme;
if (indexPath.row == 0) {
if ([theme isEqualToString:@"theme3"]) {
[TKThemeManager shareInstance].theme = @"theme1";
} else if([theme isEqualToString:@"theme4"]){
[TKThemeManager shareInstance].theme = @"theme2";
}
} else {
if ([theme isEqualToString:@"theme1"]) {
[TKThemeManager shareInstance].theme = @"theme3";
} else if([theme isEqualToString:@"theme2"]){
[TKThemeManager shareInstance].theme = @"theme4";
}
}
}

就是说,我们可以用[TKThemeManager shareInstance].theme = ...来设置文字的颜色,而且立即生效!That’s amazing!

同理我们也可以联想到对UIView类及其子类实例的背景颜色设置也同样是管用的。

摸清楚情况后,就开始着手对原生页面,按照设计师给色设计图和颜色值一点一点地来调试和修改了,接下来的就是体力活了,此处省略。下面是最终的效果动图:

####四、注意事项与总结
对这个主题颜色,我们有几点要注意和理解的:

1、目录/TKApp/resource/theme/下的各个主题文件夹里面的文件,与框架的Configuration_xxx.xml配置文件下配置的主题,可能不是一一对应的。起决定性的是,配置文件下各个主题配置的.css文件,这个我们要注意。当然,我们应该尽可能把同一个主题下的文件放在对应的主题文件夹目录下。

2、.css文件里面,每个cssClass都不知道哪里有用到,也没有注释说明下这个会在哪里用到,让人看起来很费解。我觉得可以把同一个业务模块的cssClass配置放在一起,并做一定的隔离;每个名称上面写些必要的注释。

3、.css文件中也是支持图片配置的,比如上面动图中点击的“太阳”和“月亮”图片。配置和使用示例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/*----------配置----------*/
//黑色主题 blackTheme.css
/*首页右侧导航栏的换肤按钮图片*/
.homerightNavbarSkinImage {
-mobile-image: url(home_rightNavbar_sun.png);
}
//蓝色主题 blueTheme.css
/*首页右侧导航栏的换肤按钮图片*/
.homerightNavbarSkinImage{
-mobile-image: url(home_rightNavbar_moon.png);
}
/*----------使用----------*/
//右换肤按钮
self.skinImageView = ({
UIImageView *imageView = [[UIImageView alloc]initWithFrame:CGRectMake(0, 0, 18, 18)];
[imageView addCssClass:@".homerightNavbarSkinImage"];
UITapGestureRecognizer *leftTagGesRecognizer = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(p_updateSkin)];
[imageView addGestureRecognizer:leftTagGesRecognizer];
imageView;
});

4、添加切换主题功能时,要注意与设置中的行情显示设置配合着来。我的解决方案是,在Configuration_xxx.xml中配置4套主题。

5、或许项目中的颜色配置都可以使用这种方式来设置,这样如果要开发这个功能时,可以很快上手。

—– That’s all,thank you.

文章目录