Projektowanie urządzeń składanych

W: ConstraintLayout wersji 2.1, dodaliśmy kilka funkcji, aby ułatwić zarządzaj urządzeniami składanymi, w tym SharedValues, ReactiveGuide i ulepszoną obsługę animacji w formatach MotionLayout.

Wspólne wartości

Dodaliśmy nowy mechanizm do wstrzykiwania wartości środowiska wykonawczego w komponencie ConstraintLayout: powinien być używany w przypadku wartości systemowych, ponieważ wszystkie wystąpienia ConstraintLayout mają dostęp do tej wartości.

W kontekście urządzeń składanych możemy użyć tego mechanizmu, aby wstrzykiwać pozycja części strony widocznej na ekranie podczas działania:

Kotlin

ConstraintLayout.getSharedValues().fireNewValue(R.id.fold, fold)

Java

ConstraintLayout.getSharedValues().fireNewValue(R.id.fold, fold);

Możesz uzyskać dostęp do wspólnych wartości w niestandardowym pomocniku, dodając detektor dla wszelkie zmiany:

Kotlin

val sharedValues: SharedValues = ConstraintLayout.getSharedValues()
sharedValues.addListener(mAttributeId, this)

Java

SharedValues sharedValues = ConstraintLayout.getSharedValues();
sharedValues.addListener(mAttributeId, this);

Spójrzmy na przykład FoldableExperiments. by sprawdzić, jak określamy położenie części strony widocznej na ekranie Biblioteka Jetpack WindowManager i wstrzykiwanie położenie w: 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() przyjmuje identyfikator reprezentujący wartość jako pierwszy parametr, a wartość do wstawienia jako drugi parametr.

ReactiveGuide

Jednym ze sposobów wykorzystania SharedValue w układzie bez konieczności do napisania dowolnego kodu, jest użycie funkcji ReactiveGuide jako pomoc. Spowoduje to umieszczenie wskazów w poziomie lub pionie zgodnie z połączono SharedValue.

    <androidx.constraintlayout.widget.ReactiveGuide
        android:id="@+id/fold"
        app:reactiveGuide_valueId="@id/fold"
        android:orientation="horizontal" />

Można go następnie używać w taki sam sposób jak w przypadku normalnych wytycznych.

MotionLayout dla urządzeń składanych

Dodaliśmy kilka funkcji w MotionLayout w wersji 2.1, które ułatwiają przekształcanie stanową. Jest to szczególnie przydatne w przypadku urządzeń składanych, obsługiwać animacje między różnymi możliwymi układami.

Na urządzeniach składanych dostępne są 2 sposoby:

  • W czasie działania zaktualizuj bieżący układ (ConstraintSet), aby wyświetlić lub ukryć strony.
  • W przypadku każdego stanu urządzenia składanego, który chcesz wybrać, użyj oddzielnego atrybutu ConstraintSet pomoc (closed, folded lub fully open).

Animowanie elementu ConstraintSet

Funkcja updateStateAnimate() w MotionLayout została dodana w wersji 2.1 wersja:

Kotlin

fun updateStateAnimate(stateId: Int, set: ConstraintSet, duration: Int)

Java

void updateStateAnimate(int stateId, ConstraintSet set, int duration);

Ta funkcja automatycznie animuje zmiany przy ConstraintSet zamiast natychmiastowej aktualizacji (możesz to zrobić updateState(stateId, constraintset)). Dzięki temu możesz zaktualizować UI w zależności od tego, jaki jest stan urządzenia składanego.

ReactiveGuide w: MotionLayout

Atrybut ReactiveGuide obsługuje też 2 przydatne atrybuty, gdy jest używany wewnątrz MotionLayout:

  • app:reactiveGuide_animateChange="true|false"

  • app:reactiveGuide_applyToAllConstraintSets="true|false"

Pierwsza z nich zmodyfikuje bieżący ConstraintSet i animuje zmianę automatycznie. Druga zastosuje nową wartość parametru ReactiveGuide na wszystkie ConstraintSet w MotionLayout. Typowe podejście w przypadku urządzeń składanych użyj ReactiveGuide reprezentującego pozycję i ustaw elementy układu względem ReactiveGuide.

Używanie wielu elementów ConstraintSet do reprezentowania stanu urządzenia złożonego

Zamiast aktualizować bieżący stan MotionLayout – inny sposób tworzenia architektury w interfejsie urządzeń składanych należy utworzyć określone stany (w tym closed, folded i fully open).

W takim przypadku nadal możesz używać zmiennej ReactiveGuide do reprezentowania elementu ale będziesz mieć znacznie większą kontrolę (w porównaniu do animacji przy aktualizacji bieżącego ConstraintSet), by dowiedzieć się, jak każdy stan przejść do innego.

Przy takim podejściu w detektorze DeviceState ustaw po prostu kierowanie MotionLayout, aby przejść do określonych stanów w MotionLayout.transitionToState(stateId). .