Skip to content

Commit 2defb52

Browse files
committed
add AWLThemeManager
1 parent f747c49 commit 2defb52

File tree

19 files changed

+1226
-0
lines changed

19 files changed

+1226
-0
lines changed

AWLThemeManager/AWLThemeManager.h

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
//
2+
// AWLThemeManager.h
3+
// ThemeManagerDemo
4+
//
5+
// Created by Neeeo on 14-10-16.
6+
// Copyright (c) 2014年 AppWill. All rights reserved.
7+
//
8+
9+
#import <Foundation/Foundation.h>
10+
#import <UIKit/UIKit.h>
11+
12+
@interface AWLThemeManager : NSObject
13+
14+
@property (nonatomic, strong) NSString *currentTheme;
15+
16+
// return themeName
17+
- (NSString*)addTheme:(NSString*)themePath;
18+
- (NSArray*)allThemes;
19+
20+
//Get color from defaults.plist
21+
- (UIColor*)colorForKey:(NSString*)key;
22+
- (UIColor*)colorForKey:(NSString*)key forTheme:(NSString*)themeName;
23+
24+
//Get font from defaults.plist
25+
- (UIFont*)fontForKey:(NSString*)key;
26+
- (UIFont *)fontForKey:(NSString *)key forTheme:(NSString*)themeName;
27+
28+
//Get img from theme bundle
29+
- (UIImage*)imageNamed:(NSString*)imgName;
30+
- (UIImage *)imageNamed:(NSString *)imgName forTheme:(NSString*)themeName;
31+
32+
//key in defaults.plist of the current theme
33+
- (id)objectForKey:(NSString*)key;
34+
- (id)objectForKey:(NSString *)key forTheme:(NSString*)themeName;
35+
36+
//file path in the current theme bundle
37+
- (NSString*)filePathForFileName:(NSString*)fileName;
38+
- (NSString*)filePathForFileName:(NSString *)fileName forTheme:(NSString*)themeName;
39+
40+
@end

AWLThemeManager/AWLThemeManager.m

Lines changed: 235 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,235 @@
1+
//
2+
// AWLThemeManager.m
3+
// ThemeManagerDemo
4+
//
5+
// Created by Neeeo on 14-10-16.
6+
// Copyright (c) 2014年 AppWill. All rights reserved.
7+
//
8+
9+
#import "AWLThemeManager.h"
10+
11+
@interface AWLThemeManager ()
12+
13+
@property (nonatomic, strong) NSMutableDictionary *themeList;
14+
@property (nonatomic, strong) NSMutableDictionary *themeRelationship;
15+
@property (nonatomic, strong) NSMutableDictionary *themeDefaultsList;
16+
17+
@end
18+
19+
@implementation AWLThemeManager
20+
21+
- (instancetype)init
22+
{
23+
self = [super init];
24+
if (self) {
25+
_themeList = [NSMutableDictionary dictionary];
26+
_themeRelationship = [NSMutableDictionary dictionary];
27+
_themeDefaultsList = [NSMutableDictionary dictionary];
28+
}
29+
30+
return self;
31+
}
32+
33+
- (NSString*)addTheme:(NSString *)themePath
34+
{
35+
if ([self isValidString:themePath] == NO) {
36+
return nil;
37+
}
38+
39+
if ([[NSFileManager defaultManager] fileExistsAtPath:themePath] == NO) {
40+
return nil;
41+
}
42+
43+
NSDictionary *defaults = [self defaultsForTheme:themePath];
44+
if (defaults) {
45+
NSString *themeName = defaults[@"AWL_THEME_NAME"];
46+
if ([self isValidString:themeName]) {
47+
[self.themeDefaultsList setObject:defaults forKey:themeName];
48+
[self.themeList setObject:themePath forKey:themeName];
49+
50+
NSString *baseTheme = defaults[@"AWL_BASE_THEME"];
51+
if ([self isValidString:baseTheme]) {
52+
[self.themeRelationship setObject:baseTheme forKey:themeName];
53+
}
54+
55+
return themeName;
56+
}
57+
}
58+
59+
return nil;
60+
}
61+
62+
- (NSDictionary*)defaultsForTheme:(NSString*)themePath
63+
{
64+
NSString *path = [themePath stringByAppendingPathComponent:@"defaults.plist"];
65+
if ([[NSFileManager defaultManager] fileExistsAtPath:path]) {
66+
return [NSDictionary dictionaryWithContentsOfFile:path];
67+
}
68+
69+
return nil;
70+
}
71+
72+
- (NSArray *)allThemes
73+
{
74+
return [self.themeList allKeys];
75+
}
76+
77+
- (UIColor *)colorForKey:(NSString *)key
78+
{
79+
return [self colorForKey:key forTheme:self.currentTheme];
80+
}
81+
82+
- (UIColor *)colorForKey:(NSString *)key forTheme:(NSString *)themeName
83+
{
84+
if ([self isValidString:themeName] == NO || [self isValidString:key] == NO) {
85+
return nil;
86+
}
87+
88+
NSString *colorValue = [self objectForKey:key forTheme:themeName];
89+
UIColor *color = [self colorFromString:colorValue];
90+
if (color == nil && [self isValidString:colorValue]) {
91+
color = [self colorForKey:colorValue forTheme:themeName];
92+
}
93+
94+
return color;
95+
}
96+
97+
- (UIColor*)colorFromString:(NSString*)colorValue
98+
{
99+
if ([self isValidString:colorValue]) {
100+
NSArray* array = [colorValue componentsSeparatedByString:@","];
101+
if (array && [array count] == 4) {
102+
return [UIColor colorWithRed:[array[0] floatValue]/255
103+
green:[array[1] floatValue]/255
104+
blue:[array[2] floatValue]/255
105+
alpha:[array[3] floatValue]];
106+
}
107+
}
108+
109+
return nil;
110+
}
111+
112+
- (UIImage *)imageNamed:(NSString *)imgName
113+
{
114+
return [self imageNamed:imgName forTheme:self.currentTheme];;
115+
}
116+
117+
- (UIImage *)imageNamed:(NSString *)imgName forTheme:(NSString*)themeName
118+
{
119+
if ([self isValidString:themeName] == NO || [self isValidString:imgName] == NO) {
120+
return nil;
121+
}
122+
123+
NSString *path = self.themeList[themeName];
124+
NSString *filePath = [path stringByAppendingPathComponent:imgName];
125+
UIImage *img = [UIImage imageNamed:filePath];
126+
if (img == nil) {
127+
NSString *baseTheme = self.themeRelationship[themeName];
128+
img = [self imageNamed:imgName forTheme:baseTheme];
129+
}
130+
131+
return img;
132+
}
133+
134+
- (UIFont *)fontForKey:(NSString *)key
135+
{
136+
return [self fontForKey:key forTheme:self.currentTheme];
137+
}
138+
139+
- (UIFont *)fontForKey:(NSString *)key forTheme:(NSString*)themeName
140+
{
141+
if ([self isValidString:themeName] == NO || [self isValidString:key] == NO) {
142+
return nil;
143+
}
144+
145+
NSString *fontValue = [self objectForKey:key forTheme:themeName];
146+
UIFont *font = [self fontFromString:fontValue];
147+
if (font == nil && [self isValidString:fontValue]) {
148+
font = [self fontForKey:fontValue forTheme:themeName];
149+
}
150+
151+
return font;
152+
}
153+
154+
- (UIFont*)fontFromString:(NSString*)fontValue
155+
{
156+
UIFont *font = nil;
157+
if ([self isValidString:fontValue]) {
158+
NSArray *array = [fontValue componentsSeparatedByString:@","];
159+
if (array && array.count == 2) {
160+
NSString *fontName = array[0];
161+
CGFloat fontSize = [array[1] floatValue];
162+
if ([self isValidString:fontName]) {
163+
if ([fontName isEqualToString:@"bold"]) {
164+
font = [UIFont boldSystemFontOfSize:fontSize];
165+
}
166+
else if ([fontName isEqualToString:@"italic"]) {
167+
font = [UIFont italicSystemFontOfSize:fontSize];
168+
}
169+
else {
170+
font = [UIFont fontWithName:fontName size:fontSize];
171+
}
172+
}
173+
else {
174+
font = [UIFont systemFontOfSize:fontSize];
175+
}
176+
}
177+
}
178+
179+
return font;
180+
}
181+
182+
- (id)objectForKey:(NSString *)key
183+
{
184+
return [self objectForKey:key forTheme:self.currentTheme];
185+
}
186+
187+
- (id)objectForKey:(NSString *)key forTheme:(NSString*)themeName
188+
{
189+
if ([self isValidString:themeName] == NO || [self isValidString:key] == NO) {
190+
return nil;
191+
}
192+
193+
NSDictionary *defaults = self.themeDefaultsList[themeName];
194+
id obj = defaults[key];
195+
if (obj == nil) {
196+
NSString *baseTheme = self.themeRelationship[themeName];
197+
obj = [self objectForKey:key forTheme:baseTheme];
198+
}
199+
200+
return obj;
201+
}
202+
203+
- (NSString *)filePathForFileName:(NSString *)fileName
204+
{
205+
return [self filePathForFileName:fileName forTheme:self.currentTheme];
206+
}
207+
208+
- (NSString*)filePathForFileName:(NSString *)fileName forTheme:(NSString*)themeName
209+
{
210+
if ([self isValidString:themeName] == NO || [self isValidString:fileName] == NO) {
211+
return nil;
212+
}
213+
214+
215+
NSFileManager *fileManger = [NSFileManager defaultManager];
216+
NSString *themePath = self.themeList[themeName];
217+
NSString *filePath = [themePath stringByAppendingPathComponent:fileName];
218+
if ([fileManger fileExistsAtPath:filePath] == NO) {
219+
NSString *baseTheme = self.themeRelationship[themeName];
220+
filePath = [self filePathForFileName:fileName forTheme:baseTheme];
221+
}
222+
223+
return filePath;
224+
}
225+
226+
- (BOOL)isValidString:(NSString *)str
227+
{
228+
if (str && [str isKindOfClass:[NSString class]] && [str length] > 0) {
229+
return YES;
230+
}
231+
232+
return NO;
233+
}
234+
235+
@end

README.md

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
# AWLThemeManager
2+
3+
AWLThemeManager which uses bundle as the module is a lightweight theme manager for iOS.
4+
5+
## Features
6+
7+
### What can be customized
8+
9+
1. Image;
10+
2. Font;
11+
3. Color;
12+
4. Property-list supported objects
13+
5. Any file in bundle.
14+
15+
### Theme Inheritance
16+
17+
In actual work, there may be a little difference among themes. In a traditional way, you need to keep the same content in every theme. This is a bad way if you want to change the value, you need find all the places and change it.
18+
From now on, you can feel release if you want to do that because of the inheritance of AWLThemeManager. You just need to modify the root theme then all the themes that inheritant from the root theme will be changed to the new value.
19+
20+
## How to use
21+
22+
### Import to your poject
23+
24+
* Use cocoapods
25+
26+
pod 'AWLThemeManager'
27+
28+
* Traditional way
29+
Just add the header and source file to your project
30+
* AWLThemeManager.h
31+
* AWLThemeManager.m
32+
33+
### Write your own bundle file
34+
35+
The structure of bundle file is below:
36+
37+
![Bundle](http://ww1.sinaimg.cn/large/73941b03jw1eq2u5jqhm2j204w01k3yg.jpg)
38+
39+
defaults.plist is necessary. Add other files to the root directory of bundle.
40+
41+
### defaults.plist
42+
defaults.plist is used to set the property of themes, include color, font etc.
43+
44+
![defaults.plist](http://ww4.sinaimg.cn/large/73941b03jw1eq2u3kp0vpj20d0037t8x.jpg)
45+
46+
#### bease info
47+
Default key used in defualts.plist:
48+
49+
* AWL_THEME_NAME
50+
51+
This key is necessary. it is the name of the theme, used to identify the theme, must be only.
52+
53+
* AWL_BASE_THEME
54+
55+
Alternative. If you want to use theme as your base theme, you should add this key. Set the name of base theme to this key.
56+
57+
#### Define Color
58+
The format of color is :
59+
60+
![defaults.plist](http://ww1.sinaimg.cn/large/73941b03jw1eq2u3jquu6j20bc00mjr9.jpg)
61+
62+
It will return the color use follow method:
63+
64+
[UIColor colorWithRed:[array[0] floatValue]/255
65+
green:[array[1] floatValue]/255
66+
blue:[array[2] floatValue]/255
67+
alpha:[array[3] floatValue]];
68+
69+
Make sure you set the right value to the color.
70+
71+
**Support reference** If you want to the same value to different color key, you can set the key of one color to another color, then AWLThemeManager will find the actual value of the color.
72+
73+
#### Define Font
74+
The format of font is :
75+
76+
![defaults.plist](http://ww2.sinaimg.cn/large/73941b03jw1eq2u3l0thcj20c500rwed.jpg)
77+
78+
The first one is name of font, second is size of the font.
79+
It will return the font use follow method:
80+
81+
[UIFont fontWithName:fontName size:fontSize]
82+
83+
If you want to use system font, you should ignore the first value, like this:
84+
85+
,14 //systemFontOfSize
86+
bold,14 //boldSystemFontOfSize
87+
italic,14 //italicSystemFontOfSize
88+
89+
**Support reference** Same with the color
90+
91+
You can add whatever you want to the defaults.plist. Just use `objectForKey:` to get the value.
92+
93+
### How to use in your project
94+
95+
Add the absolute path of bundle to AWLThemeManager object, then set the current theme that you want.
96+
For example:
97+
98+
NSString *bundlePath1 = [[NSBundle mainBundle] pathForResource:@"BaseSample" ofType:@"bundle"];
99+
NSString *bundlePath2 = [[NSBundle mainBundle] pathForResource:@"Sample" ofType:@"bundle"];
100+
AWLThemeManager *mgr = [[AWLThemeManager alloc] init];
101+
[mgr addTheme:bundlePath1];
102+
mgr.currentTheme = [mgr addTheme:bundlePath2];
103+
104+
Then you can access the resource use the same AWLThemeManager object as follow.
105+
106+
UIImage *img = [mgr imageNamed:@"icon"];
107+
titleLabel.textColor = [mgr colorForKey:@"Content_Text_Color"];
108+
titleLabel.font = [mgr fontForKey:@"Content_Font"];
109+
110+
111+
112+
113+
114+
115+

0 commit comments

Comments
 (0)