【问题标题】:Why do we need to Inflate a layout and attachToRoot in Android?为什么我们需要在 Android 中 Inflate 布局和 attachToRoot?
【发布时间】:2018-04-21 10:16:00
【问题描述】:

我得到了这个代码:

override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        return inflater!!.inflate(R.layout.fragment_wednesday, container, false)
    }

我不明白为什么我们需要膨胀布局并写入 attachToRoot 值。 顺便说一句,为什么我们需要一个 viewGroup?

【问题讨论】:

标签: java android xml kotlin


【解决方案1】:

布局定义只是一些 XML 数据,但要真正显示布局,必须将其转换为对象树。充气机就是这样做的。

需要一个容器 (ViewGroup) 来控制(在较大的视图对象树中)应放置膨胀子树的位置。

【讨论】:

    【解决方案2】:

    考虑这段代码

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup fragment_container, Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.example_fragment, fragment_container, false);
    }
    

    第二个参数fragment_container是一个id为fragment_container的容器(framelayout),activity用来在其布局中添加片段视图。

    不,如果我们阅读 LayoutInflater 类的 inflate 方法的源代码,我们会得到这个(我在这里删除了不必要的废话,以便您更好地理解代码)

    // The view that would be returned from this method.
    View result = root;
    
    // Temp is the root view that was found in the xml.                     
    final View temp = createViewFromTag(root, name, attrs, false);
    

    首先,它从提供的根目录创建一个临时视图。

    如果 attachToRoot 为 false,它会这样做:

    // Decide whether to return the root that was passed in or the
    // top view found in xml.
       if (root == null || !attachToRoot) {
             result = temp;
         }
    

    如果attachToRoot为false,它只是返回片段的xml的根,即容器参数只是用于获取片段的根视图的layoutParams(因为它没有根,所以它需要来自某个地方的参数) .

    如果 attachToRoot 为真,它会这样做:

     // We are supposed to attach all the views we found (int temp)
     // to root. Do that now.
      if (root != null && attachToRoot) {
               root.addView(temp, params);
        }
    

    它将上面创建的临时视图添加到根视图(即容器)。

    “第三个”参数attachToRoot是真还是假的主要区别是这个。

    true : 立即将子视图添加到父视图

    false:不现在将子视图添加到父视图。稍后添加。 `

    那是什么时候?

    稍后是当您使用例如 parent.addView(childView)

    一个常见的误解是,如果 attachToRoot 参数为 false,那么子视图将不会添加到父视图。 错误 在这两种情况下,子视图都将添加到 parentView。这只是时间的问题。

    inflater.inflate(child,parent,false);
    parent.addView(child); 
    

    等价于

    inflater.inflate(child,parent,true);
    

    注意!!笔记 !!注意!!

    当您不负责将子视图添加到父视图时,您永远不应将 attachToRoot 传递为 true。

    例如添加片段时

      public View onCreateView(LayoutInflater inflater,ViewGroup parent,Bundle bundle)
      {
            super.onCreateView(inflater,parent,bundle);
            View v = inflater.inflate(R.layout.image_fragment,parent,false);
           return v;
      }
    

    现在,如果您将第三个参数作为 true 传递,您将得到 IllegalStateException,因为下面的代码。

    getSupportFragmentManager()
      .beginTransaction()
      .add(parent, childFragment)
      .commit();
    

    由于您已经错误地在 onCreateView() 中添加了子片段。调用 add 将告诉您子视图已添加到 parent,因此 IllegalStateException。此异常来自以下代码,在检查 LayoutInflater 类中的 inflate 方法时可以找到该代码

    if (child.getParent() != null) {
            throw new IllegalStateException("The specified child already has a parent. " +
                    "You must call removeView() on the child's parent first.");
        }
    

    这里你不负责添加childView,FragmentManager负责。所以在这种情况下总是传递 false

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-06-09
      • 2014-04-02
      • 2020-09-05
      • 2012-12-03
      • 2016-06-25
      • 2017-03-12
      • 1970-01-01
      相关资源
      最近更新 更多