如何为 iPhone 应用程序创建多个主题/皮肤? [关闭]

2024-01-12

我已经准备好一个 iPhone 应用程序并获得应用程序商店的批准。现在我想为我的应用程序创建不同的主题。有人可以帮我提供有关如何为我的应用程序创建主题的信息/链接/步骤吗?

我想为男孩创建一个金属主题,为女孩创建一个粉红色主题。再次通过主题,我的意思是,整个应用程序(特性和功能)将保持不变,但根据用户是谁(男孩或女孩),他/她可以选择他们希望看到的主题。当主题改变时,只有图像/背景/音乐会根据应用的主题改变。

多谢!


这是相当困难的,因为应用程序没有相当于 css 样式表的东西。

首先,您需要确定要为应用程序的哪些部分设置外观,以及何时允许用户交换外观。

我假设您想要更改图像和字体颜色,并且如果用户必须重新启动应用程序来更改皮肤(这将使事情变得更简单),那也可以。

创建一个包含所有可换肤图像和颜色的 plist。 plist 将是一个字典,其中包含图像和颜色的合理的、主题中性的键名称(例如,没有名为“红色”的颜色,请将其称为“primaryHeadingColor”)。图像将是文件名,颜色可以是十六进制字符串,例如FF0000 为红色。

每个主题都会有一个 plist。

创建一个名为 ThemeManager 的新类,并通过添加以下方法使其成为单例:

+ (ThemeManager *)sharedManager
{
    static ThemeManager *sharedManager = nil;
    if (sharedManager == nil)
    {
        sharedManager = [[ThemeManager alloc] init];
    }
    return sharedManager;
}

ThemeManager 类将有一个名为“styles”的 NSDictionary 属性,在 init 方法中,您将把主题加载到样式字典中,如下所示:

- (id)init
{
    if ((self = [super init]))
    {
        NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
        NSString *themeName = [defaults objectForKey:@"theme"] ?: @"default";

        NSString *path = [[NSBundle mainBundle] pathForResource:themeName ofType:@"plist"];
        self.styles = [NSDictionary dictionaryWithContentsOfFile:path];
    }
    return self;
}

(注意:有些人不喜欢在 init 方法中做大量工作。我从来没有发现这是一个问题,但如果您愿意,可以创建一个单独的方法来加载主题字典并从应用程序的设置代码)。

请注意我如何从用户默认值中获取主题 plist 的名称。这意味着用户可以在您的首选项中选择一个主题并保存它,应用程序将在下次启动时加载该主题。如果没有选择主题,我会输入默认主题名称“default”,因此请确保您有一个default.plist主题文件(或将代码中的@“default”更改为您的默认主题plist实际调用的名称) )。

现在您已经加载了主题,您需要使用它;我假设您的应用程序有各种图像和文本标签。如果您在代码中加载和布局它们,那么这部分很容易。如果你用笔尖来做,那就有点棘手,但我稍后会解释如何处理。

现在通常您可以通过以下方式加载图像:

UIImage *image = [UIImage imageNamed:@"myImage.png"];

但如果您希望该图像可主题化,您现在需要通过以下方式加载它:

NSDictionary *styles = [ThemeManager sharedManager].styles;
NSString *imageName = [styles objectForKey:@"myImageKey"];
UIImage *image = [UIImage imageNamed:imageName];

这将在您的主题文件中查找与键“myImageKey”匹配的主题图像并加载它。根据您加载的主题文件,您将获得不同的样式。

您将经常使用这三行,因此您可能希望将它们包装在一个函数中。一个好主意是在 UIImage 上创建一个类别,声明一个名为以下内​​容的方法:

+ (UIImage *)themeImageNamed:(NSString *)key;

然后要使用它,您只需替换对 [UIImage imageNamed:@"foo.png"]; 的任何调用即可与 [UIImage themeImageNamed:@"foo"];其中 foo 现在是主题键而不是实际的图像名称。

好的,这就是图像主题化的过程。要设置标签颜色主题,假设您当前通过以下方式设置标签颜色:

 someLabel.color = [UIColor redColor];

您现在可以将其替换为:

NSDictionary *styles = [ThemeManager sharedManager].styles;
NSString *labelColor = [styles objectForKey:@"myLabelColor"];
someLabel.color = [UIColor colorWithHexString:labelColor];

现在您可能已经注意到 UIColor 没有方法“colorWithHexString:” - 您必须使用类别添加该方法。您可以通过 Google 搜索“带有十六进制字符串的 UIColor”解决方案来查找执行此操作的代码,或者我已经编写了一个方便的类别来执行此操作,并在此处执行更多操作:https://github.com/nicklockwood/ColorUtils https://github.com/nicklockwood/ColorUtils

如果您一直在关注,您还会想,与其一遍又一遍地编写这三行,为什么不向 UIColor 添加一个方法,称为:

+ (UIColor *)themeColorNamed:(NSString *)key;

就像我们对 UIImage 所做的那样?好想法!

就是这样了。现在,您可以在应用程序中为任何图像或标签设置主题。您可以使用相同的技巧来设置字体名称或任意数量的其他潜在主题视觉属性。

只有一件小事我们忘记了......

如果您将大部分视图构建为笔尖(我认为您没有理由不这么做),那么这些技术将不起作用,因为您的图像名称和字体颜色被隐藏在难以穿透的笔尖数据中,并且不会被使用。在你的源代码中设置。

有几种方法可以解决这个问题:

1) 您可以复制笔尖的主题副本,然后将笔尖名称放入主题 plist 中并从主题管理器加载它们。这还不错,只需实现视图控制器的 nibName 方法,如下所示:

- (NSString *)nibName
{
    NSDictionary *styles = [ThemeManager sharedManager].styles;
    return [styles objectForKey:NSStringFromClass([self class])];
}

请注意我使用视图控制器的类名作为键的巧妙技巧 - 这将为您节省一些打字时间,因为您只需使用该方法创建一个基本 ThemeViewController 并让所有可主题视图控制器继承它。

不过,这种方法确实意味着维护每个笔尖的多个副本,如果您以后需要更改任何屏幕,这将是一场维护噩梦。

2)您可以为笔尖中的所有 imageView 和标签制作 IBOutlet,然后在 viewDidLoad 方法中的代码中设置它们的图像和颜色。这可能是最麻烦的方法,但至少您不需要维护重复的笔尖(顺便说一句,这本质上与本地化笔尖是相同的问题,并且解决方案选项几乎相同)。

3)您可以创建一个名为 ThemeLabel 的 UILabel 自定义子类,在实例化标签时使用上面的代码自动设置字体颜色,然后通过将标签的类设置为 ThemeLabel 在 nib 文件中使用这些 ThemeLabels 而不是常规 UILabels界面生成器。不幸的是,如果您有多种字体或字体颜色,则需要为每种不同的样式创建不同的 UILabel 子类。

或者您可以狡猾地使用诸如视图标记或accessibilityLabel属性之类的东西作为样式字典键,以便您可以拥有单个ThemeLabel类并在Interface Builder中设置辅助功能标签来选择样式。

同样的技巧也适用于 ImageViews - 创建一个名为 ThemeImageView 的 UIImageView 子类,在 awakeFromNib 方法中,根据 tag 或accessibilityLabel 属性将图像替换为主题图像。

我个人最喜欢选项 3,因为它节省了编码时间。选项 3 的另一个优点是,如果您希望能够在运行时交换主题,您可以实现一种机制,让您的主题管理器重新加载主题字典,然后向所有 ThemeLabels 和 ThemeImageView 广播 NSNotification,告诉它们重新绘制自己。这可能只需要额外大约 15 行代码。

不管怎样,你已经有了一个完整的 iOS 应用主题解决方案。不客气!

UPDATE:

从 iOS 5 开始,现在可以在 Interface Builder 中通过 keyPath 设置自定义属性,这意味着不再需要为每个主题属性创建视图子类,或滥用标签或accessibilityLabel来选择样式。只需给你的 UILabel 或 UIImageView 子类一个字符串属性来指示它应该从 plist 使用哪个主题键,然后在 IB 中设置该值。

更新2:

从 iOS 6 开始,iOS 中内置了一个有限的皮肤系统,允许您使用名为UI外观代理一次为给定控件类的所有实例设置外观(有一个关于 UIAppearance API 的很好的教程here http://www.raywenderlich.com/21703/user-interface-customization-in-ios-6)。值得检查这是否足以满足您的蒙皮需求,但如果不能,我上面概述的解决方案仍然可以很好地工作,并且可以替代使用,或与 UIAppearance 结合使用。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何为 iPhone 应用程序创建多个主题/皮肤? [关闭] 的相关文章

随机推荐