C'est assez difficile car les applications n'ont pas l'équivalent d'une feuille de style css.
D'abord, vous devez savoir quelles sont les parties de l'application que vous voulez de la peau, et quand vous le voulez pour permettre à l'utilisateur de changer de peaux.
Je vais supposer que vous souhaitez modifier des images et les couleurs de police, et que c'est correct si l'utilisateur dispose de relancer l'application pour changer la peau (qui va rendre les choses plus simples pour l'instant).
Créer un fichier plist contenant tous vos skinnable images et de couleurs. Le plist sera un dictionnaire avec sensible, thème neutre noms de clés pour les images et les couleurs (par exemple, ne pas avoir une couleur appelée "rouge", de l'appeler "primaryHeadingColor"). Les Images seront des noms de fichiers, et les couleurs peuvent être hex chaînes de caractères, par exemple FF0000 pour le rouge.
Vous aurez un plist pour chaque thème.
Créer une nouvelle classe appelée ThemeManager et d'en faire un singleton en ajoutant la méthode suivante:
+ (ThemeManager *)sharedManager
{
static ThemeManager *sharedManager = nil;
if (sharedManager == nil)
{
sharedManager = [[ThemeManager alloc] init];
}
return sharedManager;
}
Le ThemeManager classe aura un NSDictionary propriété appelée "styles", et dans la méthode init vous allez charger le thème dans vos styles dictionnaire comme ceci:
- (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;
}
(Note: certaines personnes n'aiment pas faire beaucoup de travail à l'intérieur d'une méthode init. Je n'ai jamais trouvé que c'est un problème, mais si vous préférez, de créer une méthode pour charger les thèmes et le dictionnaire de l'appeler à partir de votre application de code de configuration).
Remarquez comment je suis arriver le nom du thème plist de l'utilisateur par défaut. Cela signifie que l'utilisateur peut sélectionner un thème, de vos préférences et de l'enregistrer et l'appli se charge de ce thème pour la prochaine fois qu'il est lancé. J'ai mis dans un thème par défaut nom de "défaut" si aucun thème n'est sélectionné, assurez-vous que vous avez un défaut.plist fichier de thème (ou de modifier le @"par défaut" dans le code pour quel que soit votre thème par défaut plist est en fait appelé).
Maintenant que vous avez chargé votre thème, vous devez l'utiliser; je suis en supposant que votre application a diverses images et des étiquettes de texte. Si vous êtes en train de charger et de la pose de ceux dans le code de cette partie est facile. Si vous le faites en plumes, alors c'est un peu plus compliqué, mais je vais vous expliquer comment gérer cela plus tard.
Maintenant, normalement vous devez charger une image en disant:
UIImage *image = [UIImage imageNamed:@"myImage.png"];
Mais si vous voulez cette image pour être compatible, vous aurez maintenant besoin de charger en disant:
NSDictionary *styles = [ThemeManager sharedManager].styles;
NSString *imageName = [styles objectForKey:@"myImageKey"];
UIImage *image = [UIImage imageNamed:imageName];
Qui va regarder dans votre fichier de thème pour le thème de l'image correspondant à la clé "myImageKey" et les charger. Selon le thème de fichier que vous avez chargé, vous aurez un style différent.
Vous serez à l'aide de ces trois lignes beaucoup de sorte que vous pouvez les envelopper dans une fonction. Une bonne idée serait de créer une catégorie sur UIImage qui déclare une méthode appelée quelque chose comme:
+ (UIImage *)themeImageNamed:(NSString *)key;
Ensuite pour l'utiliser, vous pouvez simplement remplacer tous les appels à [UIImage imageNamed:@"foo.png"]; avec [UIImage themeImageNamed:@"foo"]; où foo est maintenant le thème clé de la place du vrai nom de l'image.
Ok, donc c'est tout pour annoter vos images. Pour le thème de votre étiquette de couleurs, supposons que vous êtes en train de mettre sur votre étiquette de couleurs en disant:
someLabel.color = [UIColor redColor];
Vous remplacez maintenant que, avec:
NSDictionary *styles = [ThemeManager sharedManager].styles;
NSString *labelColor = [styles objectForKey:@"myLabelColor"];
someLabel.color = [UIColor colorWithHexString:labelColor];
Maintenant, vous avez peut-être remarqué que UIColor ne dispose pas d'une méthode "colorWithHexString:" - vous aurez à ajouter que l'utilisation d'une catégorie. Vous pouvez Google pour "UIColor avec chaîne hexadécimale de" solutions à trouver le code pour le faire, j'ai écrit une pratique de la catégorie qui ne qui et de un peu plus ici: https://github.com/nicklockwood/ColorUtils
Si vous avez été attentif, vous aurez aussi la pensée qui, au lieu de l'écriture de ces trois lignes de plus et plus, pourquoi ne pas ajouter une méthode à UIColor appelé:
+ (UIColor *)themeColorNamed:(NSString *)key;
Comme nous l'avons fait avec UIImage? Excellente idée!
Donc, c'est ça. Maintenant, vous pouvez le thème de l'image ou de l'étiquette dans votre application. Vous pouvez utiliser la même astuce pour définir le nom de la police, ou n'importe quel nombre d'autres potentiellement compatible propriétés visuelles.
Il y a juste une petite chose que nous avons oublié...
Si vous avez construit la plupart de vos points de vue comme des plumes (et je ne vois aucune raison pourquoi vous ne vous seriez pas) ensuite, ces techniques ne sont pas aller travailler parce que votre image noms des polices et des couleurs sont enterrés à l'intérieur impénétrable plume de données et ne sont pas mis dans votre code source.
Il ya quelques approches pour résoudre ce problème:
1) Vous pourriez faire de doublon sur le thème des copies de vos plumes et ensuite, mettre la plume des noms dans votre thème plist et de les charger à partir de votre gestionnaire de thème. Ce n'est pas trop mauvais, juste de mettre en œuvre la nibName méthode de votre point de vue contrôleurs comme ceci:
- (NSString *)nibName
{
NSDictionary *styles = [ThemeManager sharedManager].styles;
return [styles objectForKey:NSStringFromClass([self class])];
}
Avis mon astuce d'utiliser le nom de la classe de la vue contrôleur comme la clé qui vous permettra d'économiser un peu de temps parce que vous pouvez juste faire une base ThemeViewController avec cette méthode et d'avoir tous vos themable vue contrôleurs hériter d'elle.
Cette approche signifie que la gestion de plusieurs copies de chaque plume qui est un entretien cauchemar si vous devez modifier un des écrans plus tard.
2) Vous pourriez faire IBOutlets pour tous les imageViews et des étiquettes à vos plumes, puis l'ensemble de leurs images et de couleurs en code dans votre méthode viewDidLoad. C'est probablement le plus lourd, mais au moins vous n'avez pas de double pointes pour maintenir (ce qui est essentiellement le même problème que la localisation de plumes btw, et à peu près les mêmes options de solution).
3) Vous pouvez créer une sous-classe personnalisée de UILabel appelé ThemeLabel qui établit automatiquement la couleur de la police à l'aide du code ci-dessus lorsque l'étiquette est instancié, puis utilisez les ThemeLabels dans votre plume fichiers au lieu d'un UILabels par la définition de la classe de l'étiquette ThemeLabel dans Interface Builder. Malheureusement, si vous avez plus d'une police ou la couleur de la police, vous aurez besoin de créer un UILabel sous-classe pour chaque style différent.
Ou vous pourriez être sournois et utiliser quelque chose comme le point de vue de la balise ou accessibilityLabel bien que le style dictionnaire clé de sorte que vous pouvez avoir un seul ThemeLabel de classe et de définir le label d'accessibilité dans Interface Builder pour sélectionner le style.
La même chose pourrait fonctionner pour les ImageViews - créer une UIImageView sous-classe appelée ThemeImageView que, dans le awakeFromNib méthode remplace l'image avec un thème de l'image en fonction de la balise ou accessibilityLabel de la propriété.
Personnellement, j'aime bien l'option 3 meilleur car il permet d'économiser sur le codage. Un autre avantage de l'option 3 est que si vous voulez être en mesure de swap thèmes au moment de l'exécution, vous pouvez mettre en œuvre un mécanisme où le thème de votre gestionnaire de recharge le thème de dictionnaire, puis diffuse une NSNotification à tous les ThemeLabels et ThemeImageViews de leur dire de redessiner. Ce serait sans doute juste prendre un supplément de 15 lignes de code.
De toute façon, là, vous avez une application iOS de la thématisation de la solution. Vous êtes les bienvenus!
Mise à JOUR:
Comme de iOS5, il est maintenant possible de définir des attributs personnalisés par le chemin d'accès clé dans Interface Builder, ce qui signifie qu'il n'est plus nécessaire de créer une vue sous-classe pour chaque themable des biens, ou de l'abus de la marque ou de l'accessibilityLabel pour sélectionner les styles. Il suffit de donner votre UILabel ou UIImageView sous-classe d'une chaîne de propriété pour indiquer quel thème clé, il doit utiliser à partir de la plist, et puis définissez la valeur de l'IB.