在我的Android应用中,我需要实现一个场景转换,其中涉及其中一个元素的高程(z-index)的更改。正如您在左侧开始场景中的下图所示,蓝色弧线显示在狗的图像下方。在右侧显示的最终转换中,狗的图像显示在蓝色弧下方。我的愿望是首先启动图像的changeBounds转换,然后稍后稍稍执行arcBounds转换。在转换的大约一半时,图像的底部应位于弧的上方。在这个中间点,我想要改变图像的高程/ z指数,以便狗图像显示在蓝色弧下面。
我目前已将我的应用主题配置为使用以下transitionSet进行此场景更改。
<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>
我正在尝试使用下面显示的自定义“ElevationTransition”进行高程更改:
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;
}
}
主要活动只使用以下布局显示空白地图:
<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>
点击地图会将上面的FrameLayout替换为显示使用以下布局的底部“卡片”的片段:
<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>
单击片段,使用下面的xml以较大的狗图像开始第二个活动:
`
<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>`
目前,我看到的是,在过渡开始时海拔立即发生变化,导致狗图像被圆弧遮挡。
答案 0 :(得分:2)
我检查了github。这是一个错误。
我可以使用Transtions和TransitionManager.go()分别运行场景之间的转换。但是,当您在片段和活动之间运行转换时,始终会立即更改淡入淡出动画。在Support 26.0.0 beta-1
中修复了几个淡入淡出错误但是,问问自己,你所有的小提琴你曾经看到它做了一个真正的淡入淡出过渡? - 没有。比如忽略所有的动作和其他什么,你能让它完全褪色吗?因为我的所有建议都需要,而且我无法按照你运行的方式运行它。但是,显然所有元素的移动都有效,所以它是一个该死的bug。
你也可以完全伪造它。如果你已经淡出,你可以调用它并让它工作。如果将Activity2中的onCreate()更改为:
,则会获得正确的动画@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
setContentView(R.layout.activity2);
findViewById(R.id.arc1).setVisibility(View.VISIBLE);
findViewById(R.id.arc2).setAlpha(0);
findViewById(R.id.arc2).animate().alpha(1).setDuration(2000).start();
}
我只将arc1的可见性设置为正确的,因为你错了。这是一个始终可见的那个。
我认为然后在相同的时间段内添加一个动画,与另一个相同,以进行相位调整。有用。这是一个愚蠢的错误。根本没有充分理由,你不能在活动之间消失。
我自己发现了阿尔法。第一个可能是发生了什么。或者它可能是完全不同的一类错误。但是,我可以向你保证。我检查并做好了一切。它仍然失败了。显然,解决方法是使用他们工作的场景转换。也许根本不使用新的活动。
您可以明显地提出一些解决方法。只需使用它应该具有的布局启动活动,然后设置场景以转换到正确的布局。在第一个活动中自己添加另一个到布局的过渡。或者诸如此类的。但是,它不起作用。你做了从片段到活动的过渡,然后东西会移动,但是淡入淡出总会引发一种情绪并拒绝。它立即具有其他视图的可见性,并且没有alpha工作,也没有办法轻易纠正。
我的原始代码有一些工作是使用场景:
boolean to = true;
public void onClick(View view) {
Scene scene;
ViewGroup mSceneRoot = (ViewGroup) findViewById(R.id.container);
if (to) {
Transition mFadeTransition =
TransitionInflater.from(this).
inflateTransition(R.transition.transitionset);
scene = Scene.getSceneForLayout(mSceneRoot, R.layout.fragment_replacement, this);
TransitionManager.go(scene, mFadeTransition);
}
else {
Transition mFadeTransition =
TransitionInflater.from(this).
inflateTransition(R.transition.backwardstransitionset);
scene = Scene.getSceneForLayout(mSceneRoot, R.layout.fragment_rep, this);
TransitionManager.go(scene, mFadeTransition);
}
to = !to;
}
当我认为无法实现我对如何进行转换的非常明确的想法时,留下一些旧答案。这个错误是他没有那个有效的褪色,而这一直是问题所在。
您无法仅使用Z顺序制作动画。你改变了顺序,他们在彼此之上绘制而不是相反。做你想要做的事情就是有效地同时两个订单,并以透明度动画他们的过渡。
你画,弧,狗,另一个弧。然后,Z顺序的变化实际上是顶部绘制的圆弧的透明度。如果它完全不透明,那么弧就在狗的顶部。如果它完全透明,那么狗就在弧上。但是,如果最顶部的弧是部分透明的,它看起来像狗正在通过弧线融化,或者弧线正在融化狗,这取决于我们如何调整透明度。你可以在其他地方采用相同的技巧。把东西放在两个地方。如果它是不透明的,它会被覆盖,但如果它是透明的,它只显示最下面的弧,如果是部分透明的话,弧与物体之间的混合。在动画结束时,只需按正确顺序排列。
因此,在动画期间,您始终将2个弧移动到相同的位置。您应该将它们视为相同的弧形。并在顶部改变弧的不透明度,并做任何你对那条狗做的事情。
视频:
创建布局。将您希望在另一个对象的两个副本之间更改高度的位三明治。在其中一个布局中,将可见性设置为invisible
。因此,所有项目都以相同的顺序在两个布局中。但是,在一个中,所讨论的元素的第二个副本是不可见的。确保两个副本在两个副本中处于相同位置。更改一个副本的边界时,请确保也更改另一个副本的边界。将它们作为一个整体移动。转换视图时,将项目淡出,同时移动它或诸如此类的东西。由于第二个副本不会看起来像淡出,它看起来像是一个融化。