30
votes

Android: modifications de la visibilité des enfants de MotionLayout

Je dois manquer quelque chose avec Android: la visibilité change dans une mise en page animée. Voici une version simplifiée de ma mise en page.

<MotionLayout>
 <ImageView android:id="@+id/HeaderBackground" />
Bunch of image views, Text views that are constrainted to the HeaderBackground. 
<RecyclerView android:visibility="visible">
<EditText android:visibility="visible">
<CustomViewGroup1 android:visibility="gone">
</MotionLayout>

J'ai un motionScreen qui définit un onswipe de transition basé sur la vue du recycleur pour réduire la hauteur de HeaderBackground et masquer certaines des images / vues de texte (c'est-à-dire une barre d'outils de réduction). Cependant, s'il y a une erreur fatale, je souhaite afficher CustomViewGroup1 en haut / en face de RecyclerView, mais basculer la visibilité de RecyclerView sur disparu et CustomViewGroup1 sur visible ne fait pas apparaître CustomViewGroup1.

Je pourrais déplacer le groupe CustomViewGroup hors du MotionLayout et ajouter un framelayout à la racine de l'activité et masquer tout le MotionLayout. Mais c'est loin d'être idéal car je devrais copier la barre d'outils et les icônes. Donc, je suppose que la question concerne les changements de visibilité et potentiellement l'ordre de z?

J'utilise androidx.constraintlayout:constraintlayout:2.0.0-beta2


4 commentaires

J'ai rencontré le même problème, travaillé avec alpha


@RameesThattarath pour clarifier que vous êtes revenu à l'alpha et que cela a résolu le problème? si oui, quelle version.


androidx.constraintlayout: constraintlayout: 2.0.0-beta1


hmm ... merci pour la réponse. Cependant, j'obtiens le même comportement entre 2.0.0-beta1 et 2.0.0-beta2 .


5 Réponses :


50
votes

Il s'avère que c'était mon inexpérience avec le fonctionnement de MotionLayout. Par défaut, MotionLayout contrôle la visibilité de toutes les vues qu'il contient. Mais vous pouvez désactiver les vues enfants en utilisant l'attribut app:visibilityMode="ignore" et en définissant la vue dans <ConstraintSet>

Dans mon cas, <CustomViewGroup1> ressemble à ceci ...

<Constraint
      android:id="@id/CustomViewGroup1"
      app:layout_constraintBottom_toBottomOf="parent"
      app:layout_constraintEnd_toEndOf="parent"
      app:layout_constraintStart_toStartOf="parent"
      app:layout_constraintTop_toBottomOf="@+id/HeaderBackground"
      app:layout_constraintVertical_weight="1"
      app:visibilityMode="ignore" />

Et cela est défini de la même manière dans les ConstraintSets réduits et étendus, car je ne veux pas qu'il se déplace / animation lorsque la vue du recycleur défile.

Merci à John Hoford pour les conseils dans une autre chaîne.


1 commentaires

Merci. Cela a été mon sauveur après des jours de recherche pour y remédier.



18
votes

Mon approche consiste à exclure la vue de la disposition de mouvement, à ignorer la visibilité de la scène afin qu'elle puisse être programmatique et également à hériter des contraintes du jeu de contraintes de fin.

La documentation mentionnait l' app:applyMotionScene="boolean" mais elle ne vous dit pas où. Il doit être dans un PropertySet

De plus, visibilityMode ne fonctionnait que pour moi dans un PropertySet également

<?xml version="1.0" encoding="utf-8"?>
<MotionScene xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:motion="http://schemas.android.com/apk/res-auto"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <Transition
        ...
    </Transition>

    <ConstraintSet android:id="@+id/start">

        <Constraint android:id="@id/viewId">
            <PropertySet
                app:applyMotionScene="false"
                app:visibilityMode="ignore" />
        </Constraint>

    </ConstraintSet>

    <ConstraintSet
        android:id="@+id/end"
        motion:deriveConstraintsFrom="@id/start">
        ...
    </ConstraintSet>

</MotionScene>

Attention avec l'importation automatique de l'espace de noms de l'application à partir de la scène de mouvement, celle-ci est erronée, vous devez utiliser celle qui est utilisée sur les mises en page.

L'avantage de ceci est:

  • Aucune largeur, hauteur ou contrainte dans la scène
  • Pas besoin de répéter les propriétés puisque dérivé du jeu de contraintes de début


0 commentaires

4
votes

De manière programmatique

View clickableArea = motionLayout.findViewById(R.id.video_overlay_thumbnail);    
motionLayout.getConstraintSet(R.id.start).getConstraint(clickableArea.getId()).propertySet.mVisibilityMode = 1; // 1 - ignore or 0 - normal
clickableArea.setVisibility(GONE);


0 commentaires

2
votes

Définissez la propriété visibilitéMode sur normal , ce qui fonctionne très bien pour moi avec 2.0.0-beta3 .

 app:visibilityMode="normal"
 android:visibility="visible"


1 commentaires

c'est normal par défaut



0
votes

L'autre option en fonction de votre cas d'utilisation est de vous assurer que la vue dont vous souhaitez contrôler la visibilité n'est pas un descendant direct de MotionLayout. Placez-le dans une vue de conteneur et vous pourrez définir la visibilité comme normale


0 commentaires