android:MotionLayout子级的可见性更改

时间:2019-07-23 15:58:10

标签: android android-motionlayout

我必须在动作布局中缺少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,它根据回收者视图设置“过渡”滑动,以减小HeaderBackground的高度并隐藏某些图像/文本视图(即,折叠工具栏)。 但是,如果发生致命错误,我想在RecyclerView的顶部/前面显示CustomViewGroup1,但是将RecyclerView的可见性切换为“消失”,而将CustomViewGroup1切换为可见,则不会显示CustomViewGroup1。

我可以将CustomViewGroup组从MotionLayout中移出,并添加一个framelayout作为活动的根,并隐藏整个MotionLayout。但这并不理想,因为我必须复制工具栏和图标。所以我想这个问题是关于能见度的变化和可能的z顺序的?

我正在使用androidx.constraintlayout:constraintlayout:2.0.0-beta2

6 个答案:

答案 0 :(得分:18)

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

documentation提到了app:applyMotionScene="boolean",但没有告诉您在哪里。它必须在PropertySet

visibilityMode也只在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>

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

这样做的好处是:

  • 场景中没有宽度,高度或约束
  • 无需重复这些属性,因为它们是从开始约束集中得出的

答案 1 :(得分:4)

以编程方式

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

答案 2 :(得分:2)

visibilityMode 属性设置为 普通 ,对于 2.0.0-beta3

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

答案 3 :(得分:0)

事实证明,这是我对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在另一个频道中提供的建议。

答案 4 :(得分:0)

取决于您的用例的另一种选择是确保要控制其可见性的视图不是MotionLayout的直接后代。将其放置在容器视图中,就可以将可见性设置为普通

答案 5 :(得分:0)

您可以通过这种方式自动更改 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)
        }
    }