2011-10-29 31 views
7

我想让我的iPhone应用程序能够在皮肤(或设计主题,或外观和感觉,如木制,金属,土色,男士,女士等等)之间切换。如何在iOS应用中切换外观(或设计主题)?

我将准备一些包含按钮和背景,声音和文本颜色图像的皮肤集合,并让用户决定应用程序设置使用哪组皮肤。

实现此目的的最佳实践是什么?

的条件是:

  • 我想使用Interface Builder
  • 我需要支持的iOS 3.1.3,后来
  • 我想使皮肤的套从因特网上免费下载(我无法在应用中捆绑所有皮肤,因为一套皮肤需要大量图像,如果我这样做,应用程序文件大小可能会变得很大......我也不想硬编码有关特定皮肤的任何信息)
  • 如果自定义外观不包含一个或某些元素(如图像o r声音文件),我希望它使用默认皮肤集中的缺失元素。
  • 我不想为每个皮肤创建Nib文件。一个屏幕的Nib文件应该是主包中唯一的一个,以便于维护。

我想在我的应用程序中制作所有UIViewControllers的超类,并覆盖它加载Nib文件的部分,而不是从主包加载,从保存的皮肤中加载资源文档目录...但我不知道该怎么做...... Nib加载方法的默认行为总是从主包中加载资源,并且有关资源文件名的信息在阅读...后会丢失: (

在此先感谢您的帮助。

+1

这里有一个非常详细的解释如何皮肤的iOS应用程序在这里:http://stackoverflow.com/questions/8919334/how-to-create-multiple-themes-skins-for-iphone-apps?rq= 1它还解释了如何为笔尖蒙皮,尤其是来自iOS 5. –

+1

你可以看看下面的图书馆https://github.com/charithnidarsha/MultiThemeManager –

回答

4

我不知道有关最佳做法。但是,如果你的应用程序是不够大,那么一个结构良好的plist是你的朋友。

最初,您可以选择:金属主题。以下内容应该适用:

您可能有一个Singleton ThemeManager,或者只是将一个NSDictionary粘贴到您的一个Singleton(如果适用)。

的ThemeManager背后的关键是资产和主题之间的映射..

一些示例代码(直接写SOF ..不要介意语法错误):

#define kThemeMap(__x__) [[ThemeManager sharedManager] assetForCurrentTheme:__x__] 

... 

-(void)doUselessStuff { 
    UIImage* backgroundImage = [UIImage imageNamed:kThemeMap(@"FirstViewBG")]; 

    ... 

} 

//in the ThemeManager: 
//returns the appropriate name of the asset based on current theme 
-(NSString*)assetForCurrentTheme:(NSString*)asset { 
    //_currentTheme is an NSDictionary initialized from a plist. Plist can be downloaded, too. 
    NSString* newAsset = [_currentTheme objectForKey:asset]; 
    if(newAsset == nil) { 
     newAsset = [_defaultTheme objectForKey:asset]; 
    } 
    return asset; 
} 

//Let us assume the user selects Metal Theme somewhere .. Still coding ThemeManager: 
-(void)selectedNewTheme:(NSString*)newTheme { 
    //First, get the full path of the resource .. Either The main bundle, or documents directory or elsewhere.. 
    NSString* fullPath = ...; 
    self.currentTheme = [NSDictionary dictionaryWithContentsOfFile:fullPath]; 
} 

的的plist文件只是一个字符串字典字符串的映射......是这样的:

//Default.plist 
@"FirstViewBG" : @"FirstViewBG_Default.png" 
@"SecondViewBG" : @"SecondViewBG_Default.png" 
@"WinSound"  : @"WinSound_Default.aiff" 

//Metal.plist 
@"FirstViewBG" : @"FirstViewBG_Metal.png" 
@"SecondViewBG" : @"SecondViewBG_Metal.png" 
@"WinSound"  : @"WinSound_Metal.aiff" 

或者,你可以只保存后缀,如果是够用了哟但是,它将需要字符串操作,通过切分扩展名 - >添加后缀 - >添加扩展名。

或者可能使它成为前缀?

+0

非常感谢你的回答和非常具有描述性的代码!这可能是一个可能的解决方案。 :) – Taka

+0

唯一的原因我犹豫采取这种方法是这样的,我必须在Nib文件和Plist中保存有关资源文件名的冗余信息。虽然...我仍然希望有一种方法可以在加载Nib期间读取资源文件名,并将特定于主题的后缀或前缀添加到进程中的文件名中...任何理念?如果这不容易或不可能,我会采取这种方法。谢谢。 ;) – Taka

+0

啊..我真的不能想办法做到这一点。您必须将它们作为IBOutlets链接并在viewDidLoad中进行自定义;) – Mazyod

0

您可以使用方法为imageNamed:的UIImage类别,使用自定义imageNamed:而不是默认值。 在自定义方法中,按主题选择图像。

+0

感谢您的回复。那么,它会工作,但我认为使用Objective-C类别来覆盖方法并不是一个好习惯。 (正如在http://stackoverflow.com/questions/5272451/overriding-methods-using-categories-in-objective-c中讨论的)在这种情况下,我们可以继承UIImage以覆盖imageNamed :,但这种方式我们不能使用Interface生成器有效。 – Taka