Le nostre competenze a vostra disposizione sul blog
Amiamo il nostro lavoro e vogliamo condividerlo con voi! Tenetevi aggiornati su tutte le news e le tecnologie con le quali lavoriamo e di cui potreste avere bisogno! Seguite il nostro blog.
×

Error message

The spam filter installed on this site is currently unavailable. Per site policy, we are unable to accept new submissions until that problem is resolved. Please try resubmitting the form in a couple of minutes.
alex.reggiani's picture

Nello sviluppo di applicazioni mobili, emerge in alcuni contesti la necessità di creare diverse applicazioni che condividono le stesse funzionalità e che differiscono solamente per le risorse utilizzate; con risorse mi riferisco ad asset grafici, testi, e in generale lo stile dell'applicazione. Sfortunatamente, iOS non ci viene incontro quando vogliamo creare diversi temi per le nostre applicazioni in quanto il linguaggio non supporta alcun meccanismo equivalente ai CSS e per questo motivo dobbiamo pensare a diverse alternative per aggirare questo problema e riuscire nell'intento.
Ci sono diversi approcci che possiamo utilizzare e che dipendono dalle nostre particolari esigenze e da come è strutturata la nostra applicazione.

Come prima cosa dobbiamo pensare a quali proprietà dell'applicazione vogliamo rendere temabili.

Supponiamo che vogliamo cambiare immagini e colori, e che l'utente per cambiare tema debba riavviare l'applicazione, il che rende le cose più semplici.

Creiamo un file plist contenente tutte le risorse grafiche che vogliamo utilizzare per il tema. Il plist sarà un dictionary che avrà ad esempio i riferimenti ad immagini, font e colori utilizzati. Per le immagini possiamo utilizzare come chiave un nome identificativo che descrive cosa sta a rappresentare l'immagine (es: "defaultBackgroundImage") e come valore il nome del file. Per i colori cerchiamo di utilizzare come chiave nomi il più generale possibile (ad esempio non usiamo parole chiave come "blueColor" o "yellowColor" ma "primaryColor" e "secondaryColor") e come valore ad esempio la stringa che rappresenta la terna di componenti RGB 0,255,0. oppure RGBA 0,255,0,1 (la componente alpha come valore compreso tra 0 ed 1)

Dovremo creare un plist per ogni tema dell'applicazione.

Creiamo una nuova classe chiamata ThemeManager di tipo singleton aggiungendo il seguente metodo:

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

Definiamo nella classe ThemeManager una proprietà di tipo NSDictionary chiamata "theme", e nel metodo init andremo a caricare il tema salvato nel plist

- (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.theme = [NSDictionary dictionaryWithContentsOfFile:path];
	}
    return self;

}

In questo modo, il tema viene letto dalle preferenze dell'utente; nel caso in cui l'utente non abbia selezionato alcun tema, viene letto quello di default, per cui dobbiamo assicurarci di aver creato un file default.plist nel nostro progetto che avrà il tema base dell'applicazione.
Ora che abbiamo caricato il tema andremo ad usarlo e qui si profilano due diversi scenari:
temare l'applicazione via codice
temare l'applicazione mediante xib

In questo primo post tratterò il primo caso, mentre rimando al prossimo le varie soluzioni adottabili nel caso in cui si voglia temare l'app usando gli i file xib.
Partiamo dal caricamento di un'immagine; normalmente per caricare un'immagine si usa questa istruzione
UIImage *image = [UIImage imageNamed:@"defaultBackgroundImage.png"];
ma se vogliamo renderla temabile, allora dobbiamo utilizzare l'oggetto ThemeManager appena creato, e lo facciamo in questo modo

NSDictionary *theme = [ThemeManager sharedInstance].theme;
NSString *imageName = [theme objectForKey:@"defaultBackgroundImageKey"];
UIImage *image = [UIImage imageNamed:imageName];

In questo modo, andremo a cercare nel tema caricato, qual'è il nome effettivo dell'immagine impostata per quel tema che corrisponde alla chiave @"defaultBackgroundImageKey" ed a seconda del tema caricato otterremo un'immagine differente.
Se abbiamo molte immagini nell'applicazione, allora ci ritroveremo spesso a dover utilizzare il blocco di codice sopra riportato, per cui è conveniente creare una category sulla classe UIImage, in modo che quest'ultima possa rispondere ad esempio al metodo

+ (UIImage *)themeImageNamed:(NSString *)imageKey

ed a questo punto, qualora si voglia temare un'immagine, basterà utilizzare l'istruzione:

UIImage *image = [UIImage themeImageNamed:@"defaultBackgroundImageKey"];

Per quanto riguarda i colori, il discorso è analogo.
Normalmente assegnamo un colore ad una label in questo modo

myLabel.textColor = [UIColor blueColor];

ma se vogliamo renderlo temabile allora dovremo utilizzare il nostro ThemeManager in questo modo

NSDictionary *theme = [ThemeManager sharedInstance].theme;
NSString *labelColor = [theme objectForKey:@"myLabelColor"];
myLabel.textColor = [UIColor colorWithRGBAString:labelColor];

Lo stesso discorso fatto per le immagini vale per i colori, ovvero è piu comodo inglobare questo blocco di codice in una category in modo da ridurre l'assegnazione come segue:

+ (UIColor *)themeColorNamed:(NSString *)colorKey

ed a questo punto, per rendere temabile il colore di una label è sufficiente utilizzare la category appena creata in questo modo

myLabel.textColor = [UIColor themeColorNamed:@"primaryColor"];

Nota:
La classe UIColor di default non ha un metodo chiamato colorWithRGBAString: ma possiamo inglobare anch'esso in una category e di seguito una possibile implementazione:

+ (UIColor *)colorWithRGBAString:(NSString *)RGBAString {
	UIColor *color = nil;
    
	NSArray *rgbaComponents = [RGBAString componentsSeparatedByString:@","];
	float RED = 0.0f;
	float GREEN = 0.0f;
	float BLUE = 0.0f;
	float ALPHA = 0.0f;
	if ([rgbaComponents count] == 3) {
    	RED = [(NSString*)[rgbaComponents objectAtIndex:0] floatValue]/255;
    	GREEN = [(NSString*)[rgbaComponents objectAtIndex:1] floatValue]/255;
    	BLUE = [(NSString*)[rgbaComponents objectAtIndex:2] floatValue]/255;
        
    	color = [UIColor colorWithRed:RED green:GREEN blue:BLUE alpha:1.0f];
	}else if ([rgbaComponents count] == 4) {
    	RED = [(NSString*)[rgbaComponents objectAtIndex:0] floatValue]/255;
    	GREEN = [(NSString*)[rgbaComponents objectAtIndex:1] floatValue]/255;
    	BLUE = [(NSString*)[rgbaComponents objectAtIndex:2] floatValue]/255;
    	ALPHA = [(NSString*)[rgbaComponents objectAtIndex:3] floatValue]/255;
        
    	color = [UIColor colorWithRed:RED green:GREEN blue:BLUE alpha:ALPHA];
	}
    
	return color;
}

Infine prendiamo in esame i font.
Normalmente, l'assegnazione di un font prevede due parametri, il nome e la dimensione:

myLabel.font = [UIFont fontWithName:@"Helvetica" size:18.0];

Per renderlo temabile utilizzando lo ThemeManager, dovremmo quindi leggere non uno ma due parametri e lo facciamo in questo modo:

NSDictionary *theme = [ThemeManagersharedInstance].theme;
NSString *fontName = [theme objectForKey:@"primaryFontName"];
NSNumber *fontSize = [theme objectForKey:@"primaryFontSize"];
myLabel.font = [UIFont fontWithName:fontName
                               size:[fontSize doubleValue]];

Come per le immagini ed i colori, utilizzando una category semplifichiamo questa procedura come segue:

+ (UIFont *)themeFontNamed:(NSString *)fontName ofSize:(NSNumber *)fontSize

e quindi l'assegnazione del font alla nostra label risulterà essere:

myLabel.font = [UIFont themeFontNamed:fontName ofSize:fontSize];

Nel prossimo post vi farò vedere invece quali sono le possibili strade da seguire per temare la vostra applicazione utilizzando direttamente i file xib.

iOS

Aggiungi un commento

Filtered HTML

  • Web page addresses and e-mail addresses turn into links automatically.
  • Allowed HTML tags: <a> <em> <strong> <cite> <blockquote> <code> <ul> <ol> <li> <dl> <dt> <dd>
  • Lines and paragraphs break automatically.

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.