为iOS应用设计样式的推荐方法是什么?例如,如果有多个标签或文本视图,如何在一个地方更新字体样式/颜色更新所有其他位置的样式/颜色?
我知道子分类可能是一种方式......还有其他方法吗?
答案 0 :(得分:9)
您可以将标准头文件导入所有控制器,并为样式设置几个常量...示例:
<强> Styles.h 强>
#define kFontSize 14
#define kFontFamily @"Helevetica"
<强>控制器强>
#import "Styles.h" // at the top
myLabel.font = [UIFont fontWithName:kFontFamily size:kFontSize];
我个人认为Interface Builder是最好的样式方式,但这会直接回答你的问题。
答案 1 :(得分:9)
更新:我建议首先了解UIAppearance
API,看看它们是否符合您的需求。 UIAppearance
是一种在多个级别(例如全局或上下文)提供特定控件属性的自定义默认样式的便捷方式。
我的原始答案,早于UIAppearance
的可用性:
因为我们正在使用基于对象的语言......
对于实现,它取决于您希望它的行为/执行方式。当实现变得非常重要时,我会经常创建一个协议。您可以使用类方法或实例方法,并根据您的用途显着优化这些类型,因为您创建的中间颜色,字体,图像等较少。
基本界面可采用以下形式:
@protocol MONLabelThemeProtocol
- (UIFont *)labelFont;
- (UIColor *)labelTextColor;
- (UITextAlignment)labelTextAlignment;
// ...
@end
@protocol MONTableViewCellThemeProtocol
- (UIFont *)tableViewCellFont;
- (UIColor *)tableViewCellTextColor;
- (UIImage *)tableViewCellImage;
- (NSInteger)tableViewCellIndentationLevel;
- (CGFloat)tableViewCellIndentationWidth;
// ...
@end
然后可以像这样声明一个简单的合并主题:
@interface MONAmalgamateThemeBase : NSObject
< MONLabelThemeProtocol, MONTableViewCellThemeProtocol >
{
@protected
/* labels */
UIFont * labelFont;
UIColor * labelTextColor;
UITextAlignment labelTextAlignment;
// ...
/* table view cells */
UIFont * tableViewCellFont;
UIColor * tableViewCellTextColor;
UIImage * tableViewCellImage;
NSInteger tableViewCellIndentationLevel;
CGWidth tableViewCellIndentationWidth;
// ...
}
@end
在这个例子中,amalgamate定义了getter和dealloc,并期望子类初始化实例变量。如果初始化时间很长(例如使用许多图像),你也可以支持延迟初始化。
然后专业化可以采取以下形式:
@interface MONDarkTheme : MONAmalgamateThemeBase
@end
@implementation MONDarkTheme
- (id)init
{
self = [super init];
if (nil != self) {
labelFont = [[UIFont boldSystemFontOfSize:15] retain];
labelTextColor = [[UIColor redColor] retain];
// and so on...
}
return self;
}
// ...
@end
/* declare another theme and set it up appropriately */
@interface MONLightTheme : MONAmalgamateThemeBase
@end
然后只需在整个应用程序中重用主题实例(例如MONDarkTheme)来设置视图的样式。如果你有很多主题或者它们不是很容易构建,那么你可能想要为主题创建一个集合(主题管理器)。如果你的需求很简单,amalgamate也可以带一个参数,比如带主题的init。如果需要动态更改支持,您甚至可以配置对象以注册主题更改。
最后,您可以创建一个简单的主题应用程序,让生活更轻松 - 就像这样:
@interface UILabel (MONThemeAdditions)
- (void)mon_applyMONLabelTheme:(id<MONLabelTheme>)theme;
@end
@implementation UILabel (MONThemeAdditions)
- (void)mon_applyMONLabelTheme:(id<MONLabelTheme>)theme
{
assert(theme);
if (nil == theme) return;
self.font = [theme labelFont];
self.textColor = [theme labelTextColor];
self.textAlignment = [theme labelTextAlignment];
}
@end
答案 2 :(得分:6)
坦率地说,最好的方法是使用Interface Builder。虽然在代码中的某个地方更改单个常量并让整个应用程序更改样式似乎很不错,但它从来都不会那样。以下是我的推理:
1)开发人员不像接口构建器那样编写接口代码。 界面构建器是一个经过年精炼,测试和处理的工具。它提供字体,文本对齐,阴影等。它可以向后兼容,因为它可以追溯到你想要的地方。它为任何数量的开发人员和设计人员提供了一种非常简单的方法,可以直接进入并处理非常简单的事情。
2)总有一些边缘情况你需要考虑。当然,一个简单的常量会做你想要的最多的时间,但是你最终还是要破解一些东西在这里潜行一些东西。您开始编写的“简单”界面代码将会增长,增长和增长。其他开发人员必须维护该代码。您将不得不维护该代码。你将不得不提交和修复错误,调整它,除了等等。它将不可避免地成为一堆乱七八糟的东西。
3)您编写的代码越多,您编写的错误就越多。界面构建器用于构建大多数iOS应用程序的“外观”。用它。不要太聪明。
注意: 我知道Interface builder不能为所有应用做任何事情。有些情况下编码接口是唯一的解决方案。这个答案只是我在大部分应用中使用的一般“最佳实践”。
答案 3 :(得分:3)
与Alex的想法类似,您可以创建一个名为ThemeManager的静态类:
typedef enum
{
defaultStyle,
redStyle,
} ThemeStyles;
@interface Level : NSObject
{
ThemeStyles currentTheme;
}
所有可以为主题的类都将导入ThemeManager。然后,您可以创建如下方法:
+ (UIColor*) fontColor;
当他们想要字体颜色时,会调用哪些其他类。然后,如果您想更改主题,可以将fontColor
实现为:
+ (UIColor*) fontColor
{
switch (currentTheme)
{
case defaultStyle:
return [UIColor blackColor];
case redStyle:
return [UIColor redColor];
}
}
当您想要更改主题时,您可以让ThemeManager实现如下方法:
+ (void) changeTheme:(ThemeStyles)newTheme
{
currentTheme = newTheme;
}
答案 4 :(得分:3)
您可以使用UIAppearance的第三方抽象:
使用Storyboard有很多好处,但很多样式选项都不可用,其中最不自然的是自定义字体。如果您想要一个深度自定义的UI,您将需要一些样式代码来实现它。
答案 5 :(得分:1)
我使用plists。正如我本地化字符串一样,我使用相同的过程来更改主题。我编写了一个加载当前主题plist和后备plist的单例。然后我用键和宏函数替换资源的名称,从单例中提取真实的资源名称。
缺点:您必须为每个元素设置资源,而不仅仅是在NIB中设置它 优点:一旦你完成,下一个主题的大部分涉及photoshop和textmate,而不是IB或代码。
答案 6 :(得分:0)
您可能需要查看此库。它支持多个主题/皮肤。目前支持图像和颜色。将来会添加字体支持。