为什么LayoutInflater忽略我指定的layout_width和layout_height布局参数?


168

我在使LayoutInflater正常工作时遇到了很大的麻烦,其他人也是如此:如何在运行时使用layoutinflator添加视图?

为什么LayoutInflater会忽略我指定的布局参数?例如,为什么不尊重我的资源XML 中的layout_widthlayout_height值?


是的-这很疼还是我选错地方了?只是以为我会分享我的结果。必须承认教程并未明确提及的FAQ页面..
andig

3
请参阅常见问题解答中第一个问题的最后一段。将其发布为问题,然后将教程发布为答案。当然,您可以编辑此问题,并在答案中粘贴教程。如果您解决此问题,我会投票表决。
bigstones 2011年

Answers:


381

我已经研究了这个问题,参考了LayoutInflater文档并建立了一个小样本演示项目。以下教程显示了如何使用来动态填充布局LayoutInflater

在开始之前,请先查看LayoutInflater.inflate()参数如下:

  • resource:要加载的XML布局资源的ID(例如R.layout.main_page
  • root:可选视图,它是生成的层次结构(如果attachToRoottrue)的父级,或者只是一个LayoutParams为返回的层次结构的根(如果attachToRootfalse)提供一组值的对象。
  • attachToRoot:是否应将扩展的层次结构附加到root参数?如果为false,则root仅用于为LayoutParamsXML中的根视图创建的正确子类。

  • 返回:展开的层次结构的根视图。如果提供了root且attachToRoottrue,则为root。否则,它是膨胀的XML文件的根。

现在获取示例布局和代码。

主要布局(main.xml):

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
</LinearLayout>

添加到此容器中的是一个单独的TextView,如果从XML(red.xml)成功应用了布局参数,则将显示为红色小方块:

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="25dp"
    android:layout_height="25dp"
    android:background="#ff0000"
    android:text="red" />

现在LayoutInflater可用于多种调用参数

public class InflaterTest extends Activity {

    private View view;

    @Override
    public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);

      setContentView(R.layout.main);
      ViewGroup parent = (ViewGroup) findViewById(R.id.container);

      // result: layout_height=wrap_content layout_width=match_parent
      view = LayoutInflater.from(this).inflate(R.layout.red, null);
      parent.addView(view);

      // result: layout_height=100 layout_width=100
      view = LayoutInflater.from(this).inflate(R.layout.red, null);
      parent.addView(view, 100, 100);

      // result: layout_height=25dp layout_width=25dp
      // view=textView due to attachRoot=false
      view = LayoutInflater.from(this).inflate(R.layout.red, parent, false);
      parent.addView(view);

      // result: layout_height=25dp layout_width=25dp 
      // parent.addView not necessary as this is already done by attachRoot=true
      // view=root due to parent supplied as hierarchy root and attachRoot=true
      view = LayoutInflater.from(this).inflate(R.layout.red, parent, true);
    }
}

参数变化的实际结果记录在代码中。

提要:LayoutInflater不指定root的调用会导致忽略XML中的布局参数而导致膨胀的调用。以root不等于调用inflate nullattachRoot=true会加载布局参数,但会再次返回根对象,这会阻止对加载的对象进行进一步的布局更改(除非您可以使用来找到它findViewById())。因此,您最可能想使用的调用约定是:

loadedView = LayoutInflater.from(context)
                .inflate(R.layout.layout_to_load, parent, false);

为了帮助解决布局问题,强烈建议使用“ 布局检查器”


20
极好的答案。在Android平台上工作了3年,并且还在不断增加,从中可以学到一些东西。
Reuben Scratton 2012年

嗨,有什么方法可以用Java代码做同样的事情,而不用R.layout夸大其词。因为我没有布局。我已经使用Java代码创建了该视图,并且希望将同一视图添加300次。
2012年

1
@andig:Activity是的子类,Context并且答案的示例在的范围内Activity,因此为了简化起见,我getBaseContext()thisas 代替了它,就这个答案而言,它是等效的。
Marcin Orlowski

5
容器的layout_width和layout_height设置为“ match_parent”;然后评论说“ //结果:layout_height = wrap_content layout_width = match_parent”。我想念什么吗?
MarianPaździoch2015年

1
感谢您进行研究并分享结果!另外,我第二次回答玛丽安的问题。
LarsH 2015年

5

andig是正确的,因为LayoutInflater忽略您的layout_params的常见原因是未指定根。许多人认为您可以将null传递给root。对于某些情况(例如对话框),这是可以接受的,在这种情况下,创建时您无权访问root。但是,要遵循的一个好规则是,如果您具有root用户,则将其分配给LayoutInflater。

我写了一篇关于此的深入博客文章,您可以在这里查看:

https://www.bignerdranch.com/blog/understanding-androids-layoutinflater-inflate/


1
This is acceptable for a few scenarios such as a dialog那就是我所需要的
rookieDeveloper

0

想要添加到上面的主要答案中,
我尝试遵循它,但是我的recyclerView开始将每个项目拉伸到屏幕上
,在膨胀以达到目标后,我不得不添加下一行

itemLayoutView.setLayoutParams(new RecyclerView.LayoutParams(RecyclerView.LayoutParams.MATCH_PARENT, RecyclerView.LayoutParams.WRAP_CONTENT));

我已经通过xml添加了这些参数,但是它无法正常工作,
并且在这行中一切正常

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.