Gestire Finestre multiple e ridimensionabili in Android
Come gestire la modalità Multi-Window introdotta per la prima volta in Android Nougat. Come disattivarla nelle vecchie API e come richiamare nuove Activity direttamente in Java. Le principali novità della nuova versione Android N (Nougat/Torrone) rilasciata da Google in Agosto 2016.
Le novità di Android N (Nougat) - API 24
Finestre multiple e ridimensionabili
Una delle caratteristiche più interessanti dal punto di vista della programmazione, introdotto nella versione Android N, è l'introduzione di API che permettono di mostrare sullo schermo, nello stesso istante, più Activity all'utente. Dai tutorial visti nel corso base, sappiamo infatti che per lanciare una nuova Activity, si frutta il meccanismo degli Intent, ma non abbiamo mai potuto impostare la dimensione dell'Activity, che andava ad occupare sempre tutto lo spazio a disposizione nello schermo.
Perché sono state introdotte le finestre multiple? Sicuramente ti sarà capitato di essere in vacanza e dover rispondere ad un cliente per email, prelevando delle informazioni dal tuo gestionale interno. Prima di Android N, l'unico modo per riuscire in questa "impresa", era di aprire l'applicazione email, leggere la richiesta, parcheggiare l'app, aprire l'app del gestionale, copiare le informazioni, parcheggiare l'app, riaprire l'app email, e copiarvi le informazioni. Insomma una vera e propria perdita di tempo e completamente inefficiente.
Fortunatamente, questo modo di lavorare, apparterrà al passato, perché ora tutte le nuove applicazioni, con target Android N e successivi, avranno la possibilità di essere ridimensionate sullo schermo, esattamente come avviene per le finestre nel classico computer desktop. Una funzionalità apprezzabile maggiormente su tablet, ma che su smartphone con schermi oltre i 5 pollici, può comunque giovare avere. Un decisivo aumento di produttività, rispetto al passato.
Questo è molto utile anche nei dispositivi TV, in cui ti sarà possibile ad esempio visualizzare un video su una finestra, mentre stai usando un'altra applicazione.
Per poter attivare la modalità multi finestra, sarà sufficiente premere a lungo il pulsante a forma di quadrato "Anteprima app recenti", per scegliere l'app da trascinare e posizionare nella seconda metà dello schermo, oltre quella già eventualmente aperta. A livello predefinito l'applicazione suddividerà lo spazio a disposizione al 50%, ma in ogni istante potrai cambiare la dimensione delle finestre (modalità freeform), agendo sul cursore centrale che le suddivide sullo schermo.
Per ritornare alla modalità singola finestra/singola Activity, sarà sufficiente ripremere a lungo il tasto "Anteprima" oppure trascinare verso il basso o verso l'alto, l'app che si desidera eliminare.
Abilitare/Disabilitare il comportamento multischermo
A partire da Android N, tutte le nuove applicazioni che creerai partendo da Android Studio, saranno ridimensionabili a livello predefinito. Non sempre potresti avere la necessità di mostrare la tua applicazione in queste finestre, quindi è necessario che tu conosca anche la modalità per bypassare questo comportamento.
Per ritornare al comportamento classico, antecedente ad Android N, dovrai aggiungere manualmente una proprietà android:resizableActivity
nel nodo <application> del file androidmanifest.xml, in modo che l'applicazione venga sempre lanciata a tutto schermo e non si possa farla apparire nella finestra multipla.
Il valore predefinito di questa proprietà, per le applicazioni con API dalla 24 in su, è a true, quindi dovrai impostarlo manualmente a false, inserendo appunto la proprietà indicata nel file.
<application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:resizeableActivity="true" android:supportsRtl="true" android:theme="@style/AppTheme">
Tutte le Activity lanciate all'interno dello stesso stack, ereditano il comportamento dell'Activity lanciata dal primo Intent, quindi sarà sufficiente inserire tale modifica sull'Activity principale, per farla "ereditare" a tutte le altre.
Per tutte le applicazioni invece antecedenti le API 24, al fine di bloccare il ridimensionamento dell'app, visto che l'attributo android:resizeableActivity
non è disponibile, sarà sufficiente impostare un orientamento fisso con l'attributo android:screenOrientation,
sempre all'interno del file androidmanifest.xml
<application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name=".MainActivity" android:screenOrientation="portrait"> <intent-filter> <action android:name="android.intent.action.MAIN"/>n <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application>
Lanciare un'Activity in un'altra finestra
Se l'applicazione è nella modalità a schermo suddiviso, un' ulteriore activity può essere fatta partire adiacente o sotto a quella da cui si lancia la nuova, anche usando il codice Java e richiamando il metodo addFlag, passando Intent.FLAG_ACTIVITY_LAUNCH_TO_ADJACENT
. Questo in realtà è solo un suggerimento al sistema, nel senso che potrebbe venire ignorato, se ad esempio, l'activity è lanciata nello stesso task.
Note: Come ricorderai, l'apertura di una nuova Activity da un'app, è come la distribuzione di una carta da un mazzo, ossia viene sempre visualizzata "sovrapponendosi" all'Activity precedentemente visualizzata. Si dice appunto che è lanciata nello stesso stack. Aprendo una nuova app, si crea invece un nuovo "Task", al quale, a livello predefinito, quindi in assenza di attributi specifici per le activity nel file androidmanifest (android:lanchMode
o android:taskAffinity
), appartengono tutte le activity di quella applicazione e così via per ogni app.
Questo il motivo per cui viene anche aggiunto Intent.FLAG_ACTIVITY_NEW_TASK
, all'Intent che chiamerà la nuova Activity. In questo modo avrà un proprio stack di Activity, diverso da quello dell'activity chiamante.
Intent intent = new Intent(this, ActivityAdiacente.class); intent.addFlag(Intent.FLAG_ACTIVITY_LAUNCH_TO_ADJACENT|Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(Intent);
Il layout di un'Activity in modalità multi finestra
In Android N, per tutte le activity che entrano nella modalità multifinestra, è possibile impostare una serie di attributi nel tag <layout>, che influiscono sul loro comportamento di visualizzazione, come la dimensione minima della finestra o la dimensione predefinita.
Questi attributi sono:
- android:defaultWidth - Stabilisce la larghezza predefinita dell'activity, quando lanciata in modalità ridimensionamento libero (freeform).
- android:defaultHeight - Imposta l'altezza dell'activity quando lanciata in modalità "freeform".
- android:gravity - Posizione originale dell'activity lanciata sempre in modalità "freeform"
- android:minimalHeight, android:minimalWidth - altezza e larghezza minima dell'activity sia nella modalità multifinestra che freeform.
Questi parametri spesso si vanno ad impostare su dispositivi tablet o TV, in cui sappiamo di avere un certo spazio a disposizione. Nell'esempio qui sotto, andiamo a impostare un'altezza minima di 400dp e una larghezza minima di 350dp, sotto le quali la finestra non può essere ridimensionata.
<activity android:name=".MiaActivity"> <layout android:defaultHeight="600dp" android:defaultWidth="500dp" android:gravity="top|end" android:minHeight="400dp" android:minWidth="350dp" /> </activity>
Il ciclo di vita di un'Activity nella modalità multifinestra
Non ci sono modifiche al ciclo di vita di un'Activity quando questa è nella modalità multi-finestra. L'activity che ha avuto le ultime interazioni con l'utente, è considerata come l'activity in "foreground". Tutte le altre activity, saranno nello stato di pausa, anche quella che condivide lo schermo con l'Activity in foreground. Android darà priorità a quella Activity in pausa che non sono state messe in background.
Esiste tuttavia uno scenario particolare in cui bisogna prestare attenzione quando si è nella modalità multi-finestra. Quando un'activity è nello stato di pausa, ma visibile nello schermo condiviso, e all'interno abbiamo un video, il video non deve andare in pausa, ma deve continuare la riproduzione.
Per questo motivo è necessario spostare il codice che mette in pausa il video, dal metodo onPause() al metodo onStop(). Allo stesso modo, per riprendere l'esecuzione del video, il play dovrà essere spostato dal metodo onResume() al metodo onStart().
Nuovi metodi nella classe Activity e Fragment
Oltre agli attributi nel file androidmanifest e al layout, sono stati introdotti nuovi metodi per meglio gestire la conoscenza dello stato in cui si trova l'Activity, al fine di conoscere ad esempio se l'activity è uscita dalla modalità multi finestra, oppure se l'Activity si trova ancora nella modalità multi finestra etc.
Qui sotto sono indicati i nuovi metodi:
- inMultiWindow() - Restituisce vero se l'activity è nella modalità multi-finestra
- inPictureInPicture() - Vero se l'activity è nella modalità picture-in-picture.
- onMultiWindowChanged() - Chiamato dal sistema quando l'activity cambia dalla modalità a tutto schermo, alla modalità multi-finestra e viceversa.
- onPictureInPictureChanged() - Chiamato dal sistema quando l'activity cambia a e dalla modalità picture-in-picture.
2024-12-12 Tipo/Autore: Davide Copelli {ing} Pubblicato da: CorsoAndroid.it