【问题标题】:Android, does layoutParams points on parent view and not the view itself?Android,layoutParams 是否指向父视图而不是视图本身?
【发布时间】:2021-06-03 12:18:20
【问题描述】:

我在尝试动态更新视图的layoutParams 时遇到问题。

要更新的视图是ConstraintLayout,我想动态更改它的app:layout_constraintDimensionRatio 属性。

片段 XML:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".LevelFragment">

        <androidx.constraintlayout.widget.ConstraintLayout
            android:id="@+id/board"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:layout_marginStart="32dp"
            android:layout_marginEnd="32dp"
            android:layout_marginTop="32dp"
            android:layout_marginBottom="32dp"
            android:background="@color/black"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintDimensionRatio="1:1"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent">

        </androidx.constraintlayout.widget.ConstraintLayout>

</FrameLayout>

但是当我尝试从 Kotlin 片段代码中更改它时

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    board = view.findViewById(R.id.board)
    // Set ratio
    val layoutParams = board!!.layoutParams as ConstraintLayout.LayoutParams
    layoutParams.dimensionRatio = "5:1"
    board!!.layoutParams = layoutParams
}

调试构建后失败并出现此错误:

android.widget.FrameLayout$LayoutParams 无法转换为 androidx.constraintlayout.widget.ConstraintLayout$LayoutParams

所以,我想知道为什么它抱怨 FrameLayout 到 ConstraintLayout 演员,因为 layoutParams 取自 board 视图,这是一个 ConstraintLayout...

paramsLayout 是指父视图而不是视图本身吗?

如果是这样,如何更新视图dimensionRatio 属性?

谢谢!

【问题讨论】:

  • 布局参数由视图父级提供,在这种情况下ConstraintLayoutFrameLayout 的子级,因此后者负责布局。
  • @Pawel 好的,我可以理解;但我发现的大多数示例(包括 Stackoverflow)都将 layoutParams 转换为视图类型,而不是父类型。如何更新当前视图属性? FrameLayout 没有“dimensionRatio”属性:/
  • 另外,更新 view.layoutParams 似乎更新了视图而不是父级?
  • 用另一个ConstraintLayout 替换FrameLayout 然后你就可以使用约束了。即使参数保存在视图中,它们也会在布局周期中由其父级解析。
  • 这是个脑筋急转弯。所以要更新特定的布局属性,它的父级必须是相同的类型?我无法更新特定的 ConstraintLayout 属性(应用于自身),因为它的父级是 FrameLayout..

标签: android android-view layoutparams


【解决方案1】:

LayoutParams 是父级ViewGroup 用于布局其子级的参数。每个孩子都有自己的LayoutParams,它具有基于其父母类型的特定类型。即FrameLayout 的孩子有FrameLayout.LayoutParams 作为他们的LayoutParamsLinearLayout 的孩子有LinearLayout.LayoutParams 作为他们的LayoutParams 等等。他们也不能互相转换,这意味着你不能把LinearLayout.LayoutParams转换成FrameLayout.LayoutParams,因为他们有不同的LayoutParams实现。但是所有LayoutParams 都已扩展ViewGroup.LayoutParams,因此将它们转换为ViewGroup.LayoutParams 是安全的。
在您的情况下,您将board.layoutParams 转换为ConstraintLayout.LayoutParams,但由于board 的父级是FrameLayout,那么其LayoutParams 的类型为FrameLayout.LayoutParams,并且无法转换为ConstraintLayout.LayoutParams
如果你想解决这个问题,你必须用 ConstraintLayout 替换 board 的父级 FrameLayout
如果您想了解LayoutParams 的工作原理,也可以阅读here

【讨论】:

  • 谢谢,如果我理解正确,布局只能保存其父级支持的参数?很失望 AndroidStudio 在 XML 端添加这些属性时没有警告我
  • 是的,这正是它的工作原理。我同意你关于失望的部分,因为我也因为将布局参数转换为错误的类型而发生了很多崩溃:D
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-03-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多