DevCorner

DevCorner: divertiamoci con animazioni, visibilità e font

Giuseppe Tripodi

Visto che si avvicina l’estate, stagione di colori sgargianti e belle spiagge, per questa settimana ci stacchiamo dalla programmazione spinta per concentrarci su qualche dettaglio che servirà sicuramente per abbellire il vostro software e prepararlo per la prova costume (?). In particolare, con una semplice app d’esempio vi spiegheremo come utilizzare le animazioni, come rendere visibile o meno qualcosa e come utilizzare dei font esterni.

Partiamo quindi creando una nuova Applicazione che per semplicità chiameremo ProvaAnimazioni: sarà composta da un’unica Activity, la classica MainActivity, immancabile in tutti i progetti di prova. Per prima cosa, quindi, definiamola graficamente, creando un bottone in alto (che vedremo apparire dal basso all’avvio) e una TextView, che faremo renderemo invisibile o meno con un click.

Con l’occasione, approfittiamo per parlarvi della proprietà Weight dei LinearLayout: quando utilizzate questo tipo di Layout (che mette tutti gli oggetti in fila uno dopo l’altro, in orizzontale o verticale), ogni singolo elemento può giovare della proprietà android:layout_weight. Ma cos’è questo peso? Come spiegato da Google nella sua guida, vedete il tutto come se stesse facendo un cocktail ma, invece che di bevande, lavorate con le View: nel nostro esempio daremo al bottone un peso di 1 e alla TextView un peso di 10: in questo modo, automaticamente, Android dividerà lo schermo in 11 parti ed assegnerà 1/11 al bottone e il resto al testo. Come è ovvio, in caso di semplici interfacce questo metodo è molto comodo per creare un layout adattabile a tutte le dimensioni.
Coloriamo il tutto con qualche colore random come rosso e verde (perché tanto siamo programmatori, non è previsto avere gusto estetico!) e il risultato del nostro XML sarà qualcosa di simile:



    

Il prossimo step è far salire allegramente il nostro tasto all’avvio dell’applicazione: per far muovere qualcosa ci sono diversi modi, ma vi segnaliamo quello che noi utilizziamo più spesso, avendolo trovato decisamente comodo: creiamo una nuova classe (attenzione, “solo” una classe, non un’intera Activity!) cliccando col tasto destro sul package chiamato com.example.provaanimazioni (o qualcosa di simile) e scegliamo New-> Class. All’interno andremo a sbatterci una serie di metodi che si occuperanno di far muovere a nostro piacimento gli oggetti: la cosa comoda è che, così facendo, nel caso di lunghi progetti non ci sarà bisogno di riscrivere ogni volta le operazioni ma basterà richiamare questa classe con uno dei suoi metodi (come spiegheremo in seguito): andate quindi a fiducia (per il momento), e incollate quanto segue all’interno di Animazione.java:

package com.example.provaanimazioni;


import android.view.animation.AccelerateInterpolator;
import android.view.animation.Animation;
import android.view.animation.TranslateAnimation;

public class Animazione {
	public Animation inFromRightAnimation(int ms) {
		Animation inFromRight = new TranslateAnimation(
				Animation.RELATIVE_TO_PARENT, +1.0f,
				Animation.RELATIVE_TO_PARENT, 0.0f,
				Animation.RELATIVE_TO_PARENT, 0.0f,
				Animation.RELATIVE_TO_PARENT, 0.0f);
		inFromRight.setDuration(ms);
		inFromRight.setInterpolator(new AccelerateInterpolator());
		return inFromRight;
	}

	public Animation outToLeftAnimation(int ms) {
		Animation outtoLeft = new TranslateAnimation(
				Animation.RELATIVE_TO_PARENT, 0.0f,
				Animation.RELATIVE_TO_PARENT, -1.0f,
				Animation.RELATIVE_TO_PARENT, 0.0f,
				Animation.RELATIVE_TO_PARENT, 0.0f);
		outtoLeft.setDuration(ms);
		outtoLeft.setInterpolator(new AccelerateInterpolator());
		return outtoLeft;
	}

	public Animation inFromLeftAnimation(int ms) {
		Animation inFromLeft = new TranslateAnimation(
				Animation.RELATIVE_TO_PARENT, -1.0f,
				Animation.RELATIVE_TO_PARENT, 0.0f,
				Animation.RELATIVE_TO_PARENT, 0.0f,
				Animation.RELATIVE_TO_PARENT, 0.0f);
		inFromLeft.setDuration(ms);
		inFromLeft.setInterpolator(new AccelerateInterpolator());
		return inFromLeft;
	}

	public Animation outToRightAnimation(int ms) {
		Animation outtoRight = new TranslateAnimation(
				Animation.RELATIVE_TO_PARENT, 0.0f,
				Animation.RELATIVE_TO_PARENT, +1.0f,
				Animation.RELATIVE_TO_PARENT, 0.0f,
				Animation.RELATIVE_TO_PARENT, 0.0f);
		outtoRight.setDuration(ms);
		outtoRight.setInterpolator(new AccelerateInterpolator());
		return outtoRight;
	}

	public Animation inFromTopAnimation(int ms) {
		Animation inFromTop = new TranslateAnimation(
				Animation.RELATIVE_TO_PARENT, 0.0f,
				Animation.RELATIVE_TO_PARENT, 0.0f,
				Animation.RELATIVE_TO_PARENT, -1.0f,
				Animation.RELATIVE_TO_PARENT, 0.0f);
		inFromTop.setDuration(ms);
		inFromTop.setInterpolator(new AccelerateInterpolator());
		return inFromTop;
	}

	public Animation inFromBottomAnimation(int ms) {
		Animation inFromBottom = new TranslateAnimation(
				Animation.RELATIVE_TO_PARENT, 0.0f,
				Animation.RELATIVE_TO_PARENT, 0.0f,
				Animation.RELATIVE_TO_PARENT, +1.0f,
				Animation.RELATIVE_TO_PARENT, 0.0f);
		inFromBottom.setDuration(ms);
		inFromBottom.setInterpolator(new AccelerateInterpolator());
		return inFromBottom;
	}

	public Animation outToTopAnimation(int ms) {
		Animation outtoRight = new TranslateAnimation(
				Animation.RELATIVE_TO_PARENT, 0.0f,
				Animation.RELATIVE_TO_PARENT, 0.0f,
				Animation.RELATIVE_TO_PARENT, +1.0f,
				Animation.RELATIVE_TO_PARENT, 0.0f);
		outtoRight.setDuration(ms);
		outtoRight.setInterpolator(new AccelerateInterpolator());
		return outtoRight;
	}

	public Animation outToBottomAnimation(int ms) {
		Animation outtoRight = new TranslateAnimation(
				Animation.RELATIVE_TO_PARENT, 0.0f,
				Animation.RELATIVE_TO_PARENT, 0.0f,
				Animation.RELATIVE_TO_PARENT, -1.0f,
				Animation.RELATIVE_TO_PARENT, 0.0f);
		outtoRight.setDuration(ms);
		outtoRight.setInterpolator(new AccelerateInterpolator());
		return outtoRight;
	}
}

Tutto fatto? Non ci resta che andare a lavorare sul MainActivity per mostrare qualche chicca grafica (di dubbio gusto): per prima cosa, quindi, definiamo i nostri Button e TextView come siamo soliti fare, richiamandoli dall’id. Successivamente, nell’OnCreate andiamo istanziare un nuovo oggetto della classe Animazione, che abbiamo precedentemente definito. Per farlo, semplicemente digitiamo quanto segue.

miaAnimazione = new Animazione();

Da questo momento in poi, ogni volta che vorremo far muovere qualcosa, sarà sufficiente richiamare uno dei metodi presenti nell’altra classe: per esempio, proviamo a far entrare il testo dal basso, creando un OnCreate simile:

Button tastoSposta;
	TextView testo;
	Animazione miaAnimazione;
	@Override
	protected void onCreate(Bundle savedInstanceState) {

		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		testo = (TextView) findViewById(R.id.testo);
		tastoSposta = (Button) findViewById(R.id.tasto_sposta);
		
		miaAnimazione = new Animazione();
		tastoSposta.setAnimation(miaAnimazione.inFromBottomAnimation(3000));
				

	}

Il numero tra parentesi dopo inFromBottomAnimation rappresenta il tempo che l’oggetto deve impiegare per arrivare a destinazione, espresso in millisecondi (3000 sarà quindi equivalente a 3 secondi).  
A questo punto, visto che vogliamo abbellire un po’ il tutto, vediamo come utilizzare nella nostra app un font esterno. Scaricate un font qualsiasi in formato ttf (ne trovate parecchi gratuiti su siti come dafont): noi, giusto per ribadire la nostra  scarsa propensione all’estetica, abbiamo preso il primo che ci è apparso digitando magic come chiave di ricerca, tale Magician. Dopo averlo estratto dallo zip, copiamo il file ttf all’interno della cartella assets del progetto: sarà sufficiente un semplice drag and drop. Per assegnarlo ai singoli elementi, però, dobbiamo prima creare un oggetto di tipo Typefont: digitiamo quindi quanto segue all’interno dell’OnCreate per “tirarci fuori” il nostro font:

Typeface font = Typeface.createFromAsset(getAssets(), "Magician.ttf");

Ovviamente dovete sostituire “Magician.ttf” se il file che avete scaricato si chiama in maniera diversa; una volta creato l’elemento font, non ci rimane che assegnarlo al bottone e alla TextView:

tastoSposta.setTypeface(font);
testo.setTypeface(font);

Come ultimo trucchetto, spieghiamo adesso come giocare con la visibilità degli oggetti: questo potrebbe risultarvi molto utile nel caso andiate a sviluppare un semplice giochino o vogliate fare qualche transizione. Il metodo per rendere visibili o meno le View è setVisibility(), al quale possiamo passare come proprietà View.INVISIBLE, View.VISIBLE o View.GONE. È facile intuire a cosa servono i primi due: per quanto riguarda, invece, la differenza tra Invisible e Gone, con la prima l’oggetto è invisibile ma è sempre “presente” (nel senso che occupa effettivamente dello spazio all’interno dal layout, sebbene sia trasparente), mentre con la seconda la View scompare completamente e ci si può anche “sovrapporre” altro. Detto questo, facciamo in modo che la nostra TextView sia invisibile all’avvio dell’app: digitiamo quindi:

testo.setVisibility(View.INVISIBLE);

Adesso non ci rimane che fare in modo che, ad un click del bottone, il testo compaia o scompaia alternativamente. Implementiamo quindi l’OnClickListener come spiegato in un precedente episodio e nel metodo OnClick andiamo a scrivere quanto segue:


	@Override
	public void onClick(View v) {
		if (v == tastoSposta) {
			if(testo.getVisibility()==View.INVISIBLE){
			testo.setVisibility(View.VISIBLE);
			}
			else
				testo.setVisibility(View.INVISIBLE);

		}
		// TODO Auto-generated method stub

	}

Come è facile intuire, abbiamo fatto in modo che ad ogni click del tasto, se la visibilità dell’oggetto (ottenuta con il metodo getVisibility()) è uguale a View.INVISIBLE, questo diventi visibile tramite View.VISIBILE, viceversa verrà settata a View.INVISIBLE.

L’intera classe MainActivity, quindi, risulterà più o meno così:


package com.example.provaanimazioni;

import android.os.Bundle;
import android.app.Activity;
import android.graphics.Typeface;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

public class MainActivity extends Activity implements OnClickListener {

	Button tastoSposta;
	TextView testo;
	Animazione miaAnimazione;
	 
	@Override
	protected void onCreate(Bundle savedInstanceState) {

		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		testo = (TextView) findViewById(R.id.testo);
		Typeface font = Typeface.createFromAsset(getAssets(),
				"Magician.ttf");
		testo.setVisibility(View.INVISIBLE);
		tastoSposta = (Button) findViewById(R.id.tasto_sposta);
		tastoSposta.setTypeface(font);
		miaAnimazione = new Animazione();
		tastoSposta.setAnimation(miaAnimazione.inFromBottomAnimation(3000));
		tastoSposta.setOnClickListener(this);
		testo.setTypeface(font);
		
		

	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}

	@Override
	public void onClick(View v) {
		if (v == tastoSposta) {
			if(testo.getVisibility()==View.INVISIBLE){
			testo.setVisibility(View.VISIBLE);
			}
			else
				testo.setVisibility(View.INVISIBLE);

		}
		// TODO Auto-generated method stub

	}

}

Anche per questa settimana è tutto: adesso che sapete come gestire animazioni e visibilità potete iniziare a cimentarvi con qualche primo esperimento per rendere più gradevole la vostra app, senza dimenticare i font (sperando che abbiate più gusto di noi nello sceglierli!): come sempre, qualora doveste incappare in qualche problema, non esitate a postare nel nostro forum dove cercheremo di assistervi al meglio.
Alla prossima e buon sviluppo!