gpt4 book ai didi

objective-c - 如何为 iphone 应用程序创建多个主题/皮肤?

转载 作者:行者123 更新时间:2023-12-01 22:08:51 27 4
gpt4 key购买 nike

很难说出这里问的是什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或言辞激烈,无法以目前的形式合理回答。如需帮助澄清此问题以便可以重新打开,visit the help center .




9年前关闭。




我有一个 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 )。

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

现在通常你会说:
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

如果您一直在关注,您还会想到与其一遍又一遍地编写这三行,为什么不向 UIColor 添加一个名为的方法:
+ (UIColor *)themeColorNamed:(NSString *)key;

就像我们对 UIImage 所做的那样?好点子!

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

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

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

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

1)您可以制作 Nib 的重复主题副本,然后将 Nib 名称放入主题 plist 并从主题管理器加载它们。这还不错,只需像这样实现 View Controller 的 nibName 方法:
- (NSString *)nibName
{
NSDictionary *styles = [ThemeManager sharedManager].styles;
return [styles objectForKey:NSStringFromClass([self class])];
}

请注意我使用 View Controller 的类名作为键的巧妙技巧 - 这将为您节省一些输入,因为您可以使用该方法创建一个基本的 ThemeViewController 并让所有可主题化的 View Controller 从它继承。

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

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

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

或者,您可以狡猾地使用诸如 view 标签或 accessibilityLabel 属性之类的东西作为样式字典键,这样您就可以拥有一个 ThemeLabel 类并在 Interface Builder 中设置可访问性标签以选择样式。

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

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

无论如何,您有一个完整的 iOS 应用程序主题解决方案。别客气!

更新:

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

更新 2:

从 iOS 6 开始,iOS 中现在有一个有限的皮肤系统,它允许您使用称为 UIAppearance 代理的属性一次为给定控件类的所有实例设置皮肤(有一个关于 UIAppearance API 的很好的教程 here) .值得检查这是否足以满足您的蒙皮需求,但如果不是,我上面概述的解决方案仍然有效,并且可以替代使用,或与 UIAppearance 结合使用。

关于objective-c - 如何为 iphone 应用程序创建多个主题/皮肤?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8919334/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com