日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 综合教程 >内容正文

综合教程

iOS开发之主题皮肤

發布時間:2024/6/21 综合教程 30 生活家
生活随笔 收集整理的這篇文章主要介紹了 iOS开发之主题皮肤 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

iOS開發之主題皮膚

分類:【iOS】

最近在開發一款【公交應用】,里面有個模塊涉及到主題設置,這篇文章主要談一下個人的做法。

大概的步驟如下:

(1):整個應用依賴于一個主題管理器,主題管理器根據當前的主題配置,加載不同主題文件夾下的主題

(2):在應用的各個Controller中,涉及到需要更換主題圖片或顏色的地方,由原來的硬編碼方式改為從主題管理器獲取(此處可以看到,雖然.xib配置UI會比編碼渲染UI效率來得高,但在靈活性以及協同開發方面還是有些弱了)

(3):在主題設置Controller中,一旦切換主題,則需要像系統的通知中心發送消息(這一步的目的,主要是為了讓那些已經存在的并且UI已構建完成的對象修改他們的主題)

最終的效果圖見:

https://github.com/yanghua/iBus#version-102preview

首先來看看主題文件夾的目錄結構:

可以看到,通常情況下主題都是預先做好的,當然了,這里因為我沒有后端server,如果你的應用是擁有后端server的,那么可以做得更加強大,比如不將主題文件存儲在Bundle中,而是存儲在應用sandBox的Document中。這樣你在應用啟動的時候就可以check server 是否有新的主題包,如果有就download下來,釋放到Document,這樣會方便許多,而不需要在升級之后才能夠使用新主題。扯遠了,這里可以看到這些文件夾是藍顏色的,而非黃顏色,可見它不是xcode project的Group,它們都是真實存儲的文件夾(它們也是app的bundle的一部分,只是獲取的方式有些不同罷了,這樣做的目的就是為了方便組織各個主題的文件、目錄結構)。

看看獲取主題文件夾路徑的方式:

[cpp]view
plaincopyprint?

#defineBundle_Of_ThemeResource@"ThemeResource"

//thepathinthebundle
#defineBundle_Path_Of_ThemeResource
[[[NSBundlemainBundle]resourcePath]stringByAppendingPathComponent:Bundle_Of_ThemeResource]

ThemeManager:

[cpp]view
plaincopyprint?

@interfaceThemeManager:NSObject

@property(nonatomic,copy)NSString*themeName;
@property(nonatomic,copy)NSString*themePath;
@property(nonatomic,retain)UIColor*themeColor;

+(ThemeManager*)sharedInstance;

-(NSString*)changeTheme:(NSString*)themeName;

-(UIImage*)themedImageWithName:(NSString*)imgName;

@end

可以看到,ThemeManager對外開放了三個屬性以及兩個實例方法,并且ThemeManager被構建為是單例的(Single)
在實例初始化的時候,同時實例化主題的相關配置:

[cpp]view
plaincopyprint?

-(id)init{
if(self=[superinit]){
[selfinitCurrentTheme];
}

returnself;
}

initCurrentTheme定義:

[cpp]view
plaincopyprint?

-(void)initCurrentTheme{
self.themeName=[ConfigItemDaoget:@"主題設置"];
NSString*themeColorStr=[ConfigItemDaoget:self.themeName];
self.themeColor=[UIColorparseColorFromStr:themeColorStr];
self.themePath=[Bundle_Path_Of_ThemeResourcestringByAppendingPathComponent:self.themeName];

//initUI
UIImage*navBarBackgroundImg=[[selfthemedImageWithName:@"themeColor.png"]
resizableImageWithCapInsets:UIEdgeInsetsMake(0.0f,0.0f,1.0f,1.0f)
resizingMode:UIImageResizingModeTile];

[[UINavigationBarappearance]setBackgroundImage:navBarBackgroundImg
forBarMetrics:UIBarMetricsDefault];
}

這里從sqlite中獲取了主題類型、主題顏色,然后配置了主題屬性,同時初始化了一致的UINavigationBar。

在其他Controller中,獲取圖片的方式不再是:

[cpp]view
plaincopyprint?

UIImage*img=[UIImageimageNamed:@"img.png"];

取而代之的是:

[cpp]view
plaincopyprint?

UIImage*img=[[ThemeManagersharedInstance]themedImageWithName@"img.png"];

來確保img.png是來自當前主題文件夾下的img.png

實現如下:

[cpp]view
plaincopyprint?

-(UIImage*)themedImageWithName:(NSString*)imgName{
if(!imgName||[imgNameisEqualToString:@""]){
returnnil;
}

NSString*imgPath=[self.themePathstringByAppendingPathComponent:imgName];

return[UIImageimageWithContentsOfFile:imgPath];
}

到主題設置界面,選擇一個新主題,會調用changeTheme方法:

[cpp]view
plaincopyprint?

-(NSString*)changeTheme:(NSString*)themeName{
if(!themeName||[themeNameisEqualToString:@""]){
returnnil;
}

NSString*themePath=[Bundle_Path_Of_ThemeResourcestringByAppendingPathComponent:themeName];
if(dirExistsAtPath(themePath)){
self.themePath=themePath;

//updatetodb
[ConfigItemDaoset:[NSMutableDictionarydictionaryWithObjects:@[@"主題設置",themeName]
forKeys:@[@"itemKey",@"itemValue"]]];

//initagain
[selfinitCurrentTheme];
}

returnthemeName;
}

這是一個簡單的ThemeManager,通常有可能會有更多的配置,比如: themedFontWithName:(NSString *)fontName 等,當然方式都是一樣的。
上面這些都只是定義,看看它是怎么運轉的,怎么跟Controller組合的。

BaseController中:
注:BaseController是所有其他Controller的super class,任何時候,你去寫一個應用程序也好,一個app也罷,你一開始總是應該規劃好類型的繼承關系,這是非常重要的,就個人經驗而言,我總是會在創建一個應用程序之后,就立即構建一個super class,這會為你省去很多麻煩事。又廢話了,進入正題。
在BaseController中,我們開放一個public method:

[cpp]view
plaincopyprint?

-(void)configUIAppearance{
NSLog(@"baseconfigui");
}

該類默認沒有實現,主要用于供sub class去 override。
比如其中一個子controller的實現如下:

[cpp]view
plaincopyprint?

-(void)configUIAppearance{
self.appNameLbl.strokeColor=[[ThemeManagersharedInstance]themeColor];
[self.commentBtnsetBackgroundImage:[[ThemeManagersharedInstance]themedImageWithName:@"aboutBtnBG.png"]
forState:UIControlStateNormal];

[self.shareBtnsetBackgroundImage:[[ThemeManagersharedInstance]themedImageWithName:@"aboutBtnBG.png"]
forState:UIControlStateNormal];

[self.developerBtnsetBackgroundImage:[[ThemeManagersharedInstance]themedImageWithName:@"aboutBtnBG.png"]forState:UIControlStateNormal];

[superconfigUIAppearance];
}

可以看到,所有需要使用主題的UI控件的相關設置,都抽取出來放到了configUIAppearance中。
該方法,在所有子controller中都不會顯式調用,因為在BaseController的viewDidLoad方法中以及調用了。這樣,如果子類override了它,就會調用子類的,如果沒有override,則調用BaseController的默認實現。

可以看到,上面的方法中配置了一些UI的外觀,在一個view show出來的時候會被調用,還有一個調用點當然是主題改變的時候!
主題改變的時候,所有應用的controller無非是兩種狀態:
(1)未被實例化
(2)已經被實例化,而且view已經構建完成并且可見
對于第一種狀態,我們不需要太多的擔心,因為根據選擇新主題的時候,會調用ThemeManager的changeTheme方法,該方法會update數據庫的主題配置,同時init并config新的主題,所以未被實例化的controller在后面被實例化的時候,肯定會應用新的主題。
但對于已經可見的主題就不是第一種情況那樣了,除非你重新show他們,否則是不會主動應用新的主題的,但將其他controller都distory之后再重新構建,根本不可能。所以,這里應用了ios的Notification,并再次展示了需要一個BaseController的好處,因為我們不需要為已存在的每一個controller注冊消息通知并實現處理收到通知的方法,我們在BaseController中做,就等于在所有繼承它的sub controller中做了,不是嗎?
那么我們首先要在BaseController中像Notification center注冊我們關注的Notification_For_ThemeChanged Notification:(在BaseController的ViewDidLoad中調用該注冊方法)

[cpp]view
plaincopyprint?

-(void)registerThemeChangedNotification{
[Default_Notification_CenteraddObserver:self
selector:@selector(handleThemeChangedNotification:)
name:Notification_For_ThemeChanged
object:nil];
}

同時給出消息處理的邏輯:

[cpp]view
plaincopyprint?

-(void)handleThemeChangedNotification:(NSNotification*)notification{
UIImage*navBarBackgroundImg=[[[ThemeManagersharedInstance]themedImageWithName:@"themeColor.png"]
resizableImageWithCapInsets:UIEdgeInsetsMake(0.0f,0.0f,1.0f,1.0f)

resizingMode:UIImageResizingModeTile];

[self.navigationController.navigationBarsetBackgroundImage:navBarBackgroundImg
forBarMetrics:UIBarMetricsDefault];
<prename="code"class="cpp">[selfconfigUIAppearance];</pre>}

可以看到這里又調用了configUIAppearance,由于繼承關系,這里的self指針指向的并非BaseController實例(而是sub controller的實例),所以調用的也是sub controller的方法。所以,雖然可能還停留在“主題設置的界面”,但其他已存活的controller已經接受到了切換主題的Notification,并悄悄完成了切換。

最后再看看切換主題的大致邏輯:

[cpp]view
plaincopyprint?

-(void)themeButton_touchUpIndise:(id)sender{
//unselect
UIButton*lastSelectedBtn=(UIButton*)[self.viewviewWithTag:(Tag_Start_Index+self.currentSelectedIndex)];
lastSelectedBtn.selected=NO;

//select
UIButton*selectedBtn=(UIButton*)sender;
self.currentSelectedIndex=selectedBtn.tag-Tag_Start_Index;
selectedBtn.selected=YES;

[[ThemeManagersharedInstance]changeTheme:((NSDictionary*)self.themeArr[self.currentSelectedIndex]).allKeys[0]];

//postthemechangednotification
[Default_Notification_CenterpostNotificationName:Notification_For_ThemeChanged
object:nil];
}

大致的流程就是這樣~

如果你覺得代碼片段過于零散,沒有關系,所有的實現代碼都放到了github上。
并且整個應用都是開源的!

總結

以上是生活随笔為你收集整理的iOS开发之主题皮肤的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。