我尝试以编程方式创建新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_width
和layout_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
?
答案 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());
请注意,此处的第三个参数attachToRoot
为false
。如果将其设置为true
,则膨胀的视图会自动附加到其父容器,这简化了典型情况。
但是,当attachToRoot == true
inflate()
的返回值不是Button
实例而是hiddenPicture
时,即受影响的层次结构的提供的根View
。
在这种情况下,永远不要直接访问Button
对象。由于您在充气按钮上进行手动设置(附加监听器,设置ID),因此手动连接更简单。