57

我一定错过了 android:visibility 在动作布局中的变化。这是我的布局的简化版本。

<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>

我有一个motionScreen,它基于回收器视图设置一个Transition onswipe,以降低HeaderBackground 的高度并隐藏一些图像/文本视图(即折叠工具栏)。但是,如果有一些致命错误,我想在 RecyclerView 的顶部/前面显示 CustomViewGroup1,但是将 RecyclerView 的可见性切换为消失并且将 CustomViewGroup1 切换为可见不会使 CustomViewGroup1 显示。

我可以将 CustomViewGroup 组移出 MotionLayout 并添加一个框架布局作为活动的根并隐藏整个 MotionLayout。但这不太理想,因为我必须复制工具栏和图标。所以我想问题是关于可见性变化和潜在的 z 排序?

我在用着androidx.constraintlayout:constraintlayout:2.0.0-beta2

4

6 回答 6

95

原来这是我对 MotionLayout 如何工作的缺乏经验。默认情况下,MotionLayout 控制其中所有视图的可见性。但是您可以通过使用app:visibilityMode="ignore"属性<ConstraintSet>

在我的情况下<CustomViewGroup1>看起来像这样......

<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" />

这在折叠和展开的 ConstraintSets 中定义相同,因为我不希望它在滚动回收器视图时移动/动画。

感谢 John Hoford 在另一个频道中提供的建议。

于 2019-07-26T09:15:19.457 回答
37

我的方法是从运动布局中排除视图,忽略场景中的可见性,以便它可以是编程的并且还继承最终约束集中的约束。

文档提到了,但app:applyMotionScene="boolean"它没有告诉你在哪里。它必须在一个PropertySet

visibilityMode只在 a 内为我PropertySet工作

<?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>

小心应用程序命名空间从运动场景自动导入,这是错误的,您必须使用与布局中使用的相同的命名空间。

这样做的好处是:

  • 场景中没有宽度、高度或约束
  • 无需重复属性,因为是从开始约束集派生的
于 2020-02-19T14:54:59.457 回答
5

以编程方式

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);
于 2020-06-30T13:19:47.883 回答
2

visibilityMode属性设置为normal,对我来说工作正常2.0.0-beta3

 app:visibilityMode="normal"
 android:visibility="visible"
于 2020-07-27T20:06:24.640 回答
2

您可以通过以下方式以编程方式更改 Motion 布局的可见性子项:

fun View.changeVisibility(visibility: Int) {
        val motionLayout = parent as MotionLayout
        motionLayout.constraintSetIds.forEach {
            val constraintSet = motionLayout.getConstraintSet(it) ?: return@forEach
            constraintSet.setVisibility(this.id, visibility)
            constraintSet.applyTo(motionLayout)
        }
    }
于 2021-07-05T05:25:30.300 回答
1

根据您的用例,另一个选项是确保您要控制其可见性的视图不是 MotionLayout 的直接后代。将其放在容器视图中,您将能够正常设置可见性

于 2020-09-30T09:58:32.693 回答