DevCorner: modifichiamo i Toast e utilizziamo gli Spinner

Giuseppe Tripodi
Giuseppe Tripodi Tech Master
DevCorner: modifichiamo i Toast e utilizziamo gli Spinner

Abbiamo parlato più volte dei Toast, dei semplici messaggi popup che appaiono per un breve periodo di tempo, solitamente per informare l'utente che qualche operazione è stata completata. Oggi vediamo come personalizzarli (in particolare impostando durata e posizione sullo schermo) e, per farlo, diamo un'occhiata approfondita agli Spinner. Pronti per partire?

Per prima cosa, come ogni martedì, stabiliamo cosa vogliamo ottenere nell'interfaccia della nostra applicazione: oggi la nostra view sarà più complicata del solito, con un numero relativamente elevato di elementi per un semplice tutorial. Il risultato che vogliamo ottenere è il seguente:

ToastGravity - Vuoto

In alto abbiamo due spinner, per indicare la posizione del nostro toast (a scelta tra Sinistra, Destra, Sopra, Sotto, Centro): ovviamente per ottenere un toast in alto a destra è necessario selezionare Top/Right, mentre per avere il messaggio nell'esatto centro è sufficiente selezionare entrambe le volte Center e così via.
Lo spinner più in basso ci permette di scegliere la durata del messaggio e ha due soli valori, Long e Short.

Abbiamo, infine, tre EditText: nelle due ai lati è possibile impostare gli offset rispettivamente dell'asse Y e X, ossia la distanza verticale e orizzontale dal punto stabilito con i due spinner iniziali. Nell'EditText in basso, invece, possiamo digitare il messaggio che vogliamo appaia alla pressione del tasto Make Toast. Tutto chiaro?

Per ottenere un'interfaccia simile, potete rifarvi al seguente XML:

<relativelayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingbottom="@dimen/activity_vertical_margin" android:paddingleft="@dimen/activity_horizontal_margin" android:paddingright="@dimen/activity_horizontal_margin" android:paddingtop="@dimen/activity_vertical_margin" tools:context=".MainActivity">

<button android:id="@+id/makeToast" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignparentbottom="true" android:layout_centerhorizontal="true" android:layout_marginbottom="32dp" android:text="Make Toast"></button>

<spinner android:id="@+id/durationSpinner" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerhorizontal="true" android:layout_centervertical="true"></spinner>

<edittext android:id="@+id/xOffsetEditText" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignbottom="@+id/yOffsetEditText" android:layout_torightof="@+id/makeToast" android:inputtype="number" android:hint="Offset X" android:ems="10"></edittext>

<edittext android:id="@+id/yOffsetEditText" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/durationSpinner" android:layout_margintop="18dp" android:layout_toleftof="@+id/makeToast" android:inputtype="number" android:ems="10" android:hint="Offset Y">

<requestfocus></requestfocus>
</edittext>

<edittext android:id="@+id/toastText" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_above="@+id/makeToast" android:layout_centerhorizontal="true" android:layout_marginbottom="12dp" android:ems="10" android:hint="Testo del toast"></edittext>

<textview android:id="@+id/textPosizione" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignparenttop="true" android:layout_centerhorizontal="true" android:text="Scegli la posizione relativa e la durata del Toast"></textview>

<spinner android:id="@+id/spinnerPosition1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignleft="@+id/spinnerPosition2" android:layout_below="@+id/textPosizione" android:layout_margintop="27dp"></spinner>

<spinner android:id="@+id/spinnerPosition2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignleft="@+id/durationSpinner" android:layout_below="@+id/spinnerPosition1"></spinner>

</relativelayout>

Per definire i valori che devono apparire negli spinner, in questo tutorial ci rifacciamo a degli Array di stringhe dichiarati nelle risorse: per questo motivo, all'interno del file Strings.xml dovreste aggiungere qualcosa del genere:

  
        Left
        Right
        Top
        Bottom
        Center
    
    
        Long
        Short
    

Arrivati a questo punto siamo pronti per dedicarci alla nostra MainActivity.java: implementiamo due interfacce, OnClickListener e OnItemClickListener per stabilire cosa fare, rispettivamente, quando viene cliccato il bottone in basso o quando viene selezionato un elemento dallo spinner.

L'inizio della nostra classe, dove dichiariamo anche tutte le View presenti all'interno dell'interfaccia e gli interi che ci servono per stabilire la posizione del Toast, somiglierà quindi a qualcosa del genere:

public class MainActivity extends Activity implements OnClickListener,
		OnItemSelectedListener {
	Button makeToastBtn;
	Spinner pos1;
	Spinner pos2;
	Spinner dur;
	EditText toastText;
	EditText xOffsetText;
	EditText yOffsetText;
	int gravity1;
	int gravity2;
	int xOffset;
	int yOffset;
	int duration;

Arrivati a questo punto, nell'OnCreate dobbiamo istanziare tutti gli oggetti dichiarati, richiamandoli come consueto dal loro ID. Utilizziamo, inoltre, due ArrayAdapter per assegnate le posizioni (Left, Right, etc...) ai primi due spinner e le due durate al terzo: otteniamo tutti i valori dagli Array precedentemente definiti nella risorsa stringhe. Infine, assegniamo agli Spinner l'OnItemSelectedListener e al tasto l'OnClickListener.

@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		makeToastBtn = (Button) findViewById(R.id.makeToast);
		makeToastBtn.setOnClickListener(this);
		toastText = (EditText) findViewById(R.id.toastText);
		pos1 = (Spinner) findViewById(R.id.spinnerPosition1);
		pos2 = (Spinner) findViewById(R.id.spinnerPosition2);
		dur = (Spinner) findViewById(R.id.durationSpinner);
		xOffsetText = (EditText) findViewById(R.id.xOffsetEditText);
		yOffsetText = (EditText) findViewById(R.id.yOffsetEditText);
		ArrayAdapter positionAdapter = ArrayAdapter
				.createFromResource(this, R.array.positions,
						android.R.layout.simple_spinner_item);
		ArrayAdapter durationAdapter = ArrayAdapter
				.createFromResource(this, R.array.duration,
						android.R.layout.simple_spinner_item);
		positionAdapter
				.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
		durationAdapter
				.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
		pos1.setAdapter(positionAdapter);
		pos2.setAdapter(positionAdapter);
		dur.setAdapter(durationAdapter);
		pos1.setOnItemSelectedListener(this);
		pos2.setOnItemSelectedListener(this);
		dur.setOnItemSelectedListener(this);

	}

Non rimane adesso che stabilire come ottenere la posizione del nostro Toast e, per far questo, scriveremo buona parte del codice all'interno nel metodo onItemSelected implementato con OnItemSelectedListener: qui per prima cosa facciamo un controllo, ossia stabiliamo se lo spinner (chiamato parent) che ha richiamato l'azione è quello della durata o uno dei due per l'offset.

Nel primo caso, assegniamo alla nostra variabile duration Toast.LENGTH_LONG nel caso l'utente abbia selezionato la prima opzione e Toast.LENGTH_SHORT in caso contrario.

Adesso dobbiamo gestire la posizione sullo schermo: per farlo, nel nostro else scriviamo uno switch che operi sulla position cliccata dall'utente e assegni ad una variabile d'appoggio generalmente chiamata gravity la direzione, a seconda di quanto cliccato dall'utente. Effettuiamo quindi un controllo per stabilire se lo spinner utilizzato è il primo o il secondo e assegniamo la variabile gravity a uno degli interi gravity1 o gravity2.

@Override
	public void onItemSelected(AdapterView<?> parent, View view, int position,
			long id) {

		if(parent.getId()==dur.getId())
		{
			switch (position) {
			case 0:
				duration=Toast.LENGTH_LONG;
				break;

			case 1:
				duration=Toast.LENGTH_SHORT;
				break;
			default:
				break;
			}
		}

		else

		{
			int gravity=0;
			switch (position) {
			case 0:
				gravity = Gravity.LEFT;
				break;
			case 1:
				gravity = Gravity.RIGHT;
				break;
			case 2:
				gravity = Gravity.TOP;
				break;
			case 3:
				gravity = Gravity.BOTTOM;
				break;
			case 4:
				gravity = Gravity.CENTER;
				break;
			default:
				break;
			}
			if(parent.getId()==pos1.getId())
			{
				gravity1 = gravity;
			}
			else if(parent.getId()==pos2.getId())
			{
				gravity2 = gravity;
			}
		}

		}

Ottenuti questi valori e sommandoli agli offset, possiamo finalmente sapere dove andrà a posizionarsi il nostro Toast: dopo aver quindi verificato che a richiamare l'OnClick è il nostro bottone in basso, chiamiamo il metodo makeToast dove per prima cosa preleviamo i valori delle tre EditText: per quanto riguarda le due relative agli offset, proviamo a farci restituire un intero con il metodo parseString, restituendo 0 nel caso in cui non si tratti di un numero.

Otteniamo, infine, la stringa da mostrare come messaggio prelevandola dall'EditText in basso: passiamo quindi il Context, il testo e la durata per creare il Toast e i valori di gravity e offset per stabilire la posizione con setGravity. Infine, mostriamo il nostro agognato Toast.

@Override
	public void onClick(View v) {
		if (v.getId() == makeToastBtn.getId()) {
			makeToast();

		}

	}

	public void makeToast() {
		String text = toastText.getText().toString();
		xOffset = parseString(xOffsetText.getText().toString());
		yOffset = parseString(yOffsetText.getText().toString());
		Context context = getApplicationContext();
		Toast toast = Toast.makeText(context, text, duration);
		toast.setGravity(gravity1|gravity2, xOffset, yOffset);
		toast.show();

	}

	public Integer parseString(String text) {
		  try {
		    return new Integer(text);
		  } catch (NumberFormatException e) {
		    return 0;
		  }
		}

Anche per questa settimana il nostro tutorial è finito: vi lasciamo con qualche screenshot che chiarifica l'utilizzo di questa semplice app e vi ricordiamo che per ricevere assistenza su questa o qualsiasi altra guida, nonché per trovare i codici sorgenti completi potete visitare l'apposita sezione del nostro forum.

Buon sviluppo a tutti!