Dans mon application Android, je dois implémenter une transition de scène impliquant un changement d'élévation (z-index) de l'un des éléments. Comme vous pouvez le voir sur l'image ci-dessous dans la scène de départ à gauche, l'arc bleu est affiché sous l'image du chien. Dans la transition finale affichée sur la droite, l'image du chien est affichée sous l'arc bleu. Mon désir est d'avoir une transition changeBounds de l'image commence d'abord, puis légèrement plus tard, une transition changeBounds de l'arc. Vers la moitié de la transition, le bas de l'image doit être positionné au-dessus de l'arc. A ce point, j'aimerais que l'altitude/z-index de l'image change afin que l'image du chien soit affichée sous l'arc bleu. J'ai actuellement le thème de mon application configuré pour utiliser le transitionSet suivant pour ce changement de scène.Comment puis-je animer un changement d'élévation dans le cadre d'une animation/transition de changement de scène?
<transitionSet xmlns:android="http://schemas.android.com/apk/res/android"
android:transitionOrdering="together"
android:duration="2000">
<changeBounds
android:startDelay="0"
android:duration="1000"
android:resizeClip="false"
>
<targets>
<target android:targetId="@id/charlie"/>
</targets>
</changeBounds>
<transition class="com.motb.transitiontest.ElevationTransition">
android:startDelay="0"
android:duration="1000"
<targets>
<target android:targetId="@id/charlie"/>
<target android:targetId="@id/arc1"/>
</targets>
</transition>
<changeBounds
android:startDelay="300"
android:duration="1000"
>
<targets>
<target android:targetId="@id/arc1"/>
<target android:targetId="@id/helloText" />
</targets>
</changeBounds>
</transitionSet>
Je tente d'avoir le changement d'altitude en utilisant cette coutume « ElevationTransition » ci-dessous:
public class ElevationTransition extends Transition {
public static final String TAG = "ElevationTransition" ;
public ElevationTransition(Context context, AttributeSet attributes) {
super(context, attributes);
}
private static final String PROPNAME_TRANS_Z = "com.motb:transition:transz";
@Override
public void captureStartValues(TransitionValues transitionValues) {
float translationZ = transitionValues.view.getTranslationZ() ;
transitionValues.values.put(PROPNAME_TRANS_Z + "_start" , translationZ);
}
@Override
public void captureEndValues(TransitionValues transitionValues) {
float translationZ = transitionValues.view.getTranslationZ() ;
transitionValues.values.put(PROPNAME_TRANS_Z + "_end", translationZ);
}
@Override
public Animator createAnimator(ViewGroup sceneRoot, TransitionValues startValues,
TransitionValues endValues) {
if (startValues == null || endValues == null) {
return null;
}
final View view = endValues.view;
float startElevation = (Float) startValues.values.get(PROPNAME_TRANS_Z + "_start");
float endElevation = (Float) endValues.values.get(PROPNAME_TRANS_Z + "_end");
if (startElevation != endElevation) {
view.setTranslationZ(startElevation);
return ObjectAnimator.ofFloat(view, View.TRANSLATION_Z,
startElevation, endElevation);
}
return null;
}
}
L'activité principale affiche simplement la carte vierge en utilisant la mise en page suivante:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.motb.transitiontest.MainActivity"
android:id="@+id/main"
android:onClick="onClick"
android:background="@drawable/treasuremap"
>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="250dp"
android:id="@+id/fragmentContainer"
android:layout_alignParentBottom="true"
/>
</RelativeLayout>
Un clic sur la carte remplace le FrameLayout ci-dessus par un fragment dis jouer le fond « carte » qui utilise la mise en page suivante:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="250dp"
tools:context="com.motb.transitiontest.MainActivity"
android:id="@+id/main"
android:background="@android:color/transparent"
>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="160dp"
android:background="@drawable/arc_bg"
android:backgroundTint="#ff0000ff"
android:layout_alignParentBottom="true"
android:transitionName="rv1"
android:id="@+id/arc1"
android:translationZ="20dp"
>
<TextView
android:id="@+id/helloText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World Transition Test"
android:layout_marginStart="165dp"
android:layout_marginTop="27dp"
android:textSize="40dp"
android:gravity="left"
android:transitionName="tv1"
android:textColor="#ffffffff"
/>
</RelativeLayout>
<ImageView
android:layout_width="300px"
android:layout_height="300px"
android:layout_alignParentTop="true"
android:layout_marginTop="80dp"
android:layout_marginStart="20dp"
android:transitionName="iv1"
android:src="@drawable/charlie"
android:id="@+id/charlie"
android:translationZ="30dp"
android:stateListAnimator="@null"
/>
</RelativeLayout>
Un clic sur le fragment, commence la deuxième activité avec l'image du chien en utilisant le code XML ci-dessous:
`
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.motb.transitiontest.Activity2"
android:theme="@android:style/Theme.Translucent.NoTitleBar"
>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.motb.transitiontest.Activity2"
android:layout_marginTop="200dp"
android:background="@drawable/arc_bg"
android:layout_alignParentBottom="true"
android:transitionName="rv1"
android:id="@+id/arc1"
android:backgroundTint="#ff0000ff"
android:translationZ="40dp"
>
<TextView
android:id="@+id/helloText"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginTop="30dp"
android:layout_marginLeft="50dp"
android:layout_marginRight="50dp"
android:text="Hello World Transition Test"
android:textSize="40dp"
android:textAlignment="center"
android:transitionName="tv1"
android:textColor="#ffffffff"
/>
</RelativeLayout>
<ImageView
android:id="@+id/charlie"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:src="@drawable/charlie"
android:transitionName="iv1"
android:scaleType="centerCrop"
android:translationZ="0dp"
android:stateListAnimator="@null"
/>
</RelativeLayout>`
Actuellement, ce que je vois, c'est que l'élévation change instantanément au début de la transition, ce qui fait que l'image du chien est obscurcie par l'arc.
Une solution plus élégante et efficace sera d'écrire votre classe personnalisée pour dessiner l'image avec l'index z progressif et vous pouvez utiliser valueAnimator pour donner la douceur à votre animation – sumit
@sumit S'il vous plaît fournir plus de détails sur pourquoi vous pensez un valueAnimator est meilleur qu'un ObjectAnimator dans ce cas. Qu'est-ce qui le rend plus élégant et efficace? – John
Pouvez-vous également publier la hiérarchie de vue? – azizbekian