In ConstraintLayout
2.1, sono state aggiunte diverse funzionalità per
gestire dispositivi pieghevoli, tra cui SharedValues
,
ReactiveGuide
e supporto migliorato per le animazioni con MotionLayout
.
Valori condivisi
Abbiamo aggiunto un nuovo meccanismo per inserire i valori di runtime in ConstraintLayout
:
questo è destinato a essere utilizzato per i valori a livello di sistema, poiché tutte le istanze
ConstraintLayout
sono in grado di accedere al valore.
Nel contesto dei dispositivi pieghevoli, possiamo usare questo meccanismo per inserire posizione della piegatura in fase di esecuzione:
Kotlin
ConstraintLayout.getSharedValues().fireNewValue(R.id.fold, fold)
Java
ConstraintLayout.getSharedValues().fireNewValue(R.id.fold, fold);
In un helper personalizzato, puoi accedere ai valori condivisi aggiungendo un listener per modifiche:
Kotlin
val sharedValues: SharedValues = ConstraintLayout.getSharedValues() sharedValues.addListener(mAttributeId, this)
Java
SharedValues sharedValues = ConstraintLayout.getSharedValues(); sharedValues.addListener(mAttributeId, this);
Puoi esaminare l'esempio di Foldable Experiments
per vedere come afferriamo la posizione del fold usando
Jetpack WindowManager e inserisci
posizione in ConstraintLayout
.
Kotlin
inner class StateContainer : Consumer<WindowLayoutInfo> { override fun accept(newLayoutInfo: WindowLayoutInfo) { // Add views that represent display features for (displayFeature in newLayoutInfo.displayFeatures) { val foldFeature = displayFeature as? FoldingFeature if (foldFeature != null) { if (foldFeature.isSeparating && foldFeature.orientation == FoldingFeature.Orientation.HORIZONTAL ) { // The foldable device is in tabletop mode val fold = foldPosition(motionLayout, foldFeature) ConstraintLayout.getSharedValues().fireNewValue(R.id.fold, fold) } else { ConstraintLayout.getSharedValues().fireNewValue(R.id.fold, 0); } } } } }
Java
class StateContainer implements Consumer<WindowLayoutInfo> { @Override public void accept(WindowLayoutInfo newLayoutInfo) { // Add views that represent display features for (DisplayFeature displayFeature : newLayoutInfo.getDisplayFeatures()) { if (displayFeature instanceof FoldingFeature) { FoldingFeature foldFeature = (FoldingFeature)displayFeature; if (foldFeature.isSeparating() && foldFeature.getOrientation() == FoldingFeature.Orientation.HORIZONTAL ) { // The foldable device is in tabletop mode int fold = foldPosition(motionLayout, foldFeature); ConstraintLayout.getSharedValues().fireNewValue(R.id.fold, fold); } else { ConstraintLayout.getSharedValues().fireNewValue(R.id.fold, 0); } } } } }
fireNewValue()
prende un ID che rappresenta il valore come primo parametro e
il valore da inserire come secondo parametro.
ReactiveGuide
Un modo per sfruttare SharedValue
in un layout, senza dover
scrivere alcun codice, è utilizzare ReactiveGuide
come un assistente per le app. In questo modo, una linea guida orizzontale o verticale verrà posizionata in base alla
collegato SharedValue
.
<androidx.constraintlayout.widget.ReactiveGuide
android:id="@+id/fold"
app:reactiveGuide_valueId="@id/fold"
android:orientation="horizontal" />
Puoi quindi utilizzarlo come faresti con una normale linea guida.
MotionLayout
per pieghevoli
Nella versione 2.1 abbiamo aggiunto diverse funzionalità in MotionLayout
che aiutano il morphing
particolarmente utile per i pieghevoli, come
devono gestire l'animazione tra i diversi layout possibili.
Esistono due approcci disponibili per i pieghevoli:
- In fase di runtime, aggiorna il layout corrente (
ConstraintSet
) per mostrare o nascondere piega. - Usa un attributo
ConstraintSet
separato per ciascuno degli stati pieghevoli che vuoi assistenza (closed
,folded
ofully open
).
Animazione di un ConstraintSet
La funzione updateStateAnimate()
in MotionLayout
è stata aggiunta nella versione 2.1
release:
Kotlin
fun updateStateAnimate(stateId: Int, set: ConstraintSet, duration: Int)
Java
void updateStateAnimate(int stateId, ConstraintSet set, int duration);
Questa funzione animerà automaticamente le modifiche durante l'aggiornamento di una determinata
ConstraintSet
anziché eseguire un aggiornamento immediato (operazione che puoi eseguire
updateState(stateId, constraintset)
). In questo modo puoi aggiornare la UI
al volo, a seconda dei cambiamenti, ad esempio lo stato del pieghevole in cui ti trovi.
ReactiveGuide
in un MotionLayout
ReactiveGuide
supporta anche due attributi utili quando viene utilizzato all'interno di un
MotionLayout
:
app:reactiveGuide_animateChange="true|false"
app:reactiveGuide_applyToAllConstraintSets="true|false"
Il primo modificherà il valore ConstraintSet
corrente e animerà la modifica
automaticamente. La seconda applica il nuovo valore dell'attributo ReactiveGuide
posizione per tutti i ConstraintSet
in MotionLayout
. Un approccio tipico
i pieghevoli dovrebbero usare ReactiveGuide
che rappresenta la posizione di piegatura,
la configurazione degli elementi di layout in relazione a ReactiveGuide
.
Utilizzo di più ConstraintSet
per rappresentare lo stato pieghevole
Invece di aggiornare lo stato attuale di MotionLayout
, un altro modo di progettare
la UI per supportare i pieghevoli è la creazione di stati separati specifici (inclusi
closed
, folded
e fully open
).
In questo scenario, potresti comunque voler utilizzare ReactiveGuide
per rappresentare
ma avresti un controllo molto maggiore (rispetto alle
durante l'aggiornamento dell'attuale ConstraintSet
) su come ogni stato sarebbe
passare a un altro.
Con questo approccio, nel tuo listener DeviceState
, dovrai semplicemente indirizzare la
MotionLayout
per passare a stati specifici tramite
MotionLayout.transitionToState(stateId)
:
.