美文网首页
Android LayoutParams的深拷贝

Android LayoutParams的深拷贝

作者: 超级呆 | 来源:发表于2020-07-16 11:26 被阅读0次
      // 通用的复制属性方法
      private fun cloneParams(params: ViewGroup.LayoutParams): ViewGroup.LayoutParams {
            val paramsClass = params.javaClass
            val newInstance =
                Class.forName(paramsClass.name).getConstructor(ViewGroup.LayoutParams::class.java).newInstance(
                    params
                ) as ViewGroup.LayoutParams
            for (paramsField in paramsClass.declaredFields) {
                if (TextUtils.equals(paramsField.name, "widget")) { // 该属性导致约束布局的后续修改,影响被复制的View属性
                       continue
                }
                paramsField.isAccessible = true
                paramsField.set(newInstance, paramsField.get(params))
                println("当前字段 ${paramsField.name}:${paramsField.get(params)}")
            }
            return newInstance
        }
    

    遇到的问题整理

    • 对称布局提供了API直接在存在的LayoutParams对象上创建新实例,但是修改以后,原来的View也会被改变,和对Java的理解不一样

    androidx.constraintlayout.widget.ConstraintLayout.LayoutParams#LayoutParams(androidx.constraintlayout.widget.ConstraintLayout.LayoutParams)

    使用该API,理论上应该会深拷贝一个新的实例,修改该实例的值,不应该影响原来的View的属性,代码层面是没有修改,但是实际效果是修改了的。

    目前还不清楚原因 …

    原因排查:
    androidx.constraintlayout.widget.ConstraintLayout.LayoutParams#widget ->
    androidx.constraintlayout.solver.widgets.ConstraintWidget

    猜测可能是复制了widget属性

    虽然没有找到确定的证据,但从android.support.constraint.ConstraintLayout#setChildrenConstraints中可窥一二,猜测是该属性决定了子View,在父布局ConstraintLayout的一个重排机制,用于外部设置ConstraintSet去设置该属性。

    image.png

    真相大白,从ConstraintLayout的布局方法中来看的话,可知道宽高以及绘制的位置取决与 ConstraintWidget , 所以如果通过反射获取对应的引用,会导致修改到原View的属性~

    相关文章

      网友评论

          本文标题:Android LayoutParams的深拷贝

          本文链接:https://www.haomeiwen.com/subject/hzcphktx.html