添加充气按钮时的NPE

时间:2015-11-01 12:32:20

标签: android android-layout

我尝试以编程方式创建新Button,并将其创建到现有ViewGroup(我从自定义更改为经典LinearLayout以确保错误不在自定义ViewGroup中)。

代码很简单,它在不同的用例中工作:

private void appendTile() {
    View view = getLayoutInflater().inflate(R.layout.template_tile, null);
    view.setId(View.generateViewId());
    view.setOnClickListener(tileListener);
    hiddenPicture.addView(view, view.getLayoutParams());
}

template_tile.xml:

<Button xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text=""
style="@style/FormulaValue" />

但它失败了,因为view.getLayoutParams()null(尽管XML中有layout_widthlayout_height

Caused by: java.lang.NullPointerException: Attempt to read from field 'int android.view.ViewGroup$LayoutParams.width' on a null object reference
   at android.view.ViewGroup$LayoutParams.<init>(ViewGroup.java:6453)
   at android.view.ViewGroup$MarginLayoutParams.<init>(ViewGroup.java:6735)
   at android.widget.LinearLayout$LayoutParams.<init>(LinearLayout.java:1901)
   at android.widget.LinearLayout.generateLayoutParams(LinearLayout.java:1799)
   at android.widget.LinearLayout.generateLayoutParams(LinearLayout.java:62)
   at android.view.ViewGroup.addViewInner(ViewGroup.java:3945)
   at android.view.ViewGroup.addView(ViewGroup.java:3786)
   at android.view.ViewGroup.addView(ViewGroup.java:3758)
   at lelisoft.com.lelimath.activities.PuzzleActivity.appendTile(PuzzleActivity.java:39)
   at lelisoft.com.lelimath.activities.PuzzleActivity.onCreate(PuzzleActivity.java:31)

我去了ViewGroups构造函数,它从null params读取宽度。我的活动有什么不同之处?为什么没有设置XML的layout_width

2 个答案:

答案 0 :(得分:2)

布局参数来自父对象。由于您使用null父级进行了充气,​​因此您的视图还没有布局参数。

替换

addView(view, view.getLayoutParams())

addView(view)

不自己提供布局参数,让框架为你生成一个。

答案 1 :(得分:2)

LayoutParams特定于容器(即ViewGroup)。由于您在没有root参数的情况下进行充气,layout parameters are ignored,因为根本没有&#34;正确的&#34;在不知道容器类型的情况下创建LayoutParams的合适实例的方法。

要使用XML中的布局参数,您需要在充气时提供根ViewGroup

View view = getLayoutInflater().inflate(
    R.layout.template_tile,
    hiddenPicture,
    false // don't attachToRoot
);
view.setId(View.generateViewId());
view.setOnClickListener(tileListener);
hiddenPicture.addView(view, view.getLayoutParams());

请注意,此处的第三个参数attachToRootfalse。如果将其设置为true,则膨胀的视图会自动附加到其父容器,这简化了典型情况。

但是,当attachToRoot == true inflate()的返回值不是Button实例而是hiddenPicture时,即受影响的层次结构的提供的根View

在这种情况下,永远不要直接访问Button对象。由于您在充气按钮上进行手动设置(附加监听器,设置ID),因此手动连接更简单。