android - 以编程方式更改约束时,Android MotionLayout 状态未更新
问题描述
我有一个非常简单的 MotionLayout,我正在尝试以编程方式更改其中一个约束的可见性,并让视图反映该更改。但是,直到我从当前状态转换然后回到它之前,更改才会反映出来。如何让视图立即根据新的约束进行自我更新?我试过了updateState()
,rebuildScene()
但invalidate()
他们似乎都没有做任何事情。
这是视图:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.motion.widget.MotionLayout
android:id="@+id/motion_layout"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" xmlns:app="http://schemas.android.com/apk/res-auto"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:showIn="@layout/activity_main"
app:layoutDescription="@xml/motion_scene"
tools:context=".MainActivity">
<TextView
android:id="@+id/left_to_right_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Left to right"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<TextView
android:id="@+id/top_to_bottom_text"
android:text="Top to bottom"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
</androidx.constraintlayout.motion.widget.MotionLayout>
这是动态场景:
<?xml version="1.0" encoding="utf-8"?>
<MotionScene xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<Transition
app:constraintSetStart="@id/base"
app:constraintSetEnd="@id/bottom">
<OnClick
app:targetId="@id/top_to_bottom_text">
</OnClick>
</Transition>
<Transition
app:constraintSetStart="@id/base"
app:constraintSetEnd="@id/right">
<OnSwipe
app:dragDirection="dragRight"
app:touchAnchorId="@id/left_to_right_text"
app:touchAnchorSide="right">
</OnSwipe>
</Transition>
<ConstraintSet android:id="@+id/base">
<Constraint
android:id="@id/left_to_right_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<Constraint
android:id="@id/top_to_bottom_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
</ConstraintSet>
<ConstraintSet android:id="@+id/bottom">
<Constraint
android:id="@id/left_to_right_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<Constraint
android:id="@id/top_to_bottom_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
/>
</ConstraintSet>
<ConstraintSet android:id="@+id/right">
<Constraint
android:id="@id/left_to_right_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<Constraint
android:id="@id/top_to_bottom_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
</ConstraintSet>
</MotionScene>
这是我尝试在 2 秒后更新文本视图之一的可见性的代码:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setSupportActionBar(toolbar)
Completable.timer(2, TimeUnit.SECONDS)
.observeOn(AndroidSchedulers.mainThread())
.subscribe {
motion_layout.getConstraintSet(R.id.base)?.let {
it.setVisibility(R.id.left_to_right_text, View.INVISIBLE)
}
motion_layout.updateState()
// These don't work either
// motion_layout.rebuildScene()
// motion_layout.invalidate()
}
}
你可以在下面的 gif 中看到,我等了 2 秒,没有任何反应。直到我转换到一个新状态,然后回到原来的状态,可见性才会更新。
解决方案
我找到了解决办法!
Phan Van Linh 提供的解决方案对我不起作用(我使用的是 2.0.0-beta1 约束版本)
只需在您刚刚更改可见性(或其他视图属性)的视图上调用 .requestLayout() 所以在您的示例中:
motion_layout.getConstraintSet(R.id.base)?.let {
it.setVisibility(R.id.left_to_right_text, View.INVISIBLE)
yourView.requestLayout() // <-- this line
}
由于 requestLayout 方法的文档,它将通过当前布局传递中的所有视图层次结构。
推荐阅读
- python - 如何爬取 IEEE
- elixir - 为什么在 Elixir 中不允许使用 `<< String.reverse("Halo") >>`?
- javascript - React-Native 动画存在渲染问题
- javascript - 多个 AddEventListener 表单提交
- spring-boot - 在百里香弹簧靴中,动态旋转木马滑块不起作用
- oracle - Oracle 更新语句与 Join
- git - 尝试克隆 TensorFlow 存储库时 git clone 不起作用
- amazon-web-services - AWS CloudFormation:新创建的 EC2 密钥对出现“密钥对 ___ 不存在”错误
- python - Where to initialize SQLAlchemy instance with Flask-restplus
- c# - 使用 win32 api 获取 Treeview(SysTreeView32) 项目文本