【问题标题】:Transitions: How to change parent view size after transition is finished?过渡:过渡完成后如何更改父视图大小?
【发布时间】:2019-07-08 00:20:35
【问题描述】:

在我的应用中,我有一个线性的视图布局。这些视图的大小可能会由于其自身布局的变化而发生变化。特别是,第一个视图 (sceneRoot) 由可隐藏部分 (view1) 和始终可见部分 (view2) 组成。我想分两步动画view1的出现和消失:

  • 如果view1 消失,1) view1 淡出然后 2) view2 向上移动 (1),
  • 如果view1 出现,1) view2 向下移动,然后 2) view1 淡入 (2)。

这是目前的结果:

问题是sceneRoot 会在view1 更改可见性时立即更改其边界。 view3 跳到它的新位置,使消失的过渡看起来被剪掉了。

理想情况下,我希望sceneRoot 的高度相应地设置动画。如果这无法实现,我希望在消失过渡完成后改变高度,而不是在它开始之前。

这是有问题的布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <LinearLayout
        android:id="@+id/scene_root"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <TextView
            android:id="@+id/view_1"
            android:layout_width="match_parent"
            android:layout_height="200dp"
            android:background="@android:color/holo_red_light"
            android:gravity="center"
            android:text="View 1 (Hideable)"
            android:textSize="24sp" />

        <TextView
            android:id="@+id/view_2"
            android:layout_width="match_parent"
            android:layout_height="100dp"
            android:background="@android:color/holo_orange_light"
            android:gravity="center"
            android:text="View 2"
            android:textSize="24sp" />

    </LinearLayout>

    <TextView
        android:id="@+id/view_3"
        android:layout_width="match_parent"
        android:layout_height="200dp"
        android:background="@android:color/holo_green_dark"
        android:gravity="center"
        android:text="View 3"
        android:textSize="24sp" />

</LinearLayout>

在这个简化的示例中,单个 LinearLayout 就足够了。然而,在现实生活中,布局扁平化并不是那么容易实现的。

以下是我如何更改 view1 的可见性:

private fun toggleView1Visibility() {
    TransitionManager.endTransitions(sceneRoot)

    val isView1Appearing = view1.visibility != View.VISIBLE

    TransitionManager.beginDelayedTransition(
        sceneRoot,
        createTransition(isView1Appearing)
    )

    view1.visibility = if (isView1Appearing) View.VISIBLE else View.GONE
}

private fun createTransition(
    isView1Appearing: Boolean
): Transition {
    val view1Fade = Fade().apply {
        addTarget(view1)
        duration = 750
    }

    val view2ChangeBounds = ChangeBounds().apply {
        addTarget(view2)
        duration = 750
    }

    return TransitionSet().apply {
        ordering = TransitionSet.ORDERING_SEQUENTIAL

        if (isView1Appearing) {
            addTransition(view2ChangeBounds)
            addTransition(view1Fade)
        } else {
            addTransition(view1Fade)
            addTransition(view2ChangeBounds)
        }
    }
}

在不使用布局展平的情况下,我必须通过哪些选项来修复消失过渡?

谢谢。

【问题讨论】:

  • 您是否在父级 LL 中尝试过 android:animateLayoutChanges="true"
  • 很遗憾,它不起作用。可能是因为父母 LL 对其孩子的变化一无所知。它只会对整个 sceneRoot 的可见性变化做出反应。

标签: android android-animation android-transitions


【解决方案1】:

显然,过渡目标不是场景根的直接子级。

ChangeBounds() 添加更多目标就成功了:

private fun createTransition(
        isView1Appearing: Boolean
): Transition {
    val view1Fade = Fade().apply {
        addTarget(view1)
        duration = 750
    }

    val changeBounds = ChangeBounds().apply {
        addTarget(sceneRoot)

        addTarget(view2)
        addTarget(view3)

        duration = 750
    }

    return TransitionSet().apply {
        ordering = TransitionSet.ORDERING_SEQUENTIAL

        if (isView1Appearing) {
            addTransition(changeBounds)
            addTransition(view1Fade)
        } else {
            addTransition(view1Fade)
            addTransition(changeBounds)
        }
    }
}

希望它对某人有用。

【讨论】:

    【解决方案2】:

    如果你找到了答案,那就太好了。在这里我也添加了一个答案,虽然它是用 Java 编写的,因为我对 kotlin 不太了解。

     private void toggleView1Visibility() {
    
            final int originalDimension = sceneRoot.getHeight();
            final int newDimension =sceneRoot.getHeight();
    
    
            Boolean isView1Appearing = view1.getVisibility() != View.VISIBLE;
    
            TransitionManager.beginDelayedTransition(sceneRoot, new TransitionSet()
                    .addTransition(new ChangeBounds()));
            if (isView1Appearing){
                ViewGroup.LayoutParams params = sceneRoot.getLayoutParams();
                params.height = newDimension;
                sceneRoot.setLayoutParams(params);
                view1.setVisibility(View.VISIBLE );
            }
    
            else {
                TransitionManager.beginDelayedTransition(sceneRoot, new TransitionSet()
                        .addTransition(new ChangeBounds()));
    
                ViewGroup.LayoutParams params = sceneRoot.getLayoutParams();
                params.height = originalDimension;
                sceneRoot.setLayoutParams(params);
                view1.setVisibility(View.GONE);
            }
        }
    

    记住这里的sceneroot是布局的父LL。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-11-29
      • 1970-01-01
      • 1970-01-01
      • 2021-09-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多