首先:是的,我阅读了关于这个主题的所有其他主题 . 不仅是来自这个网站的人......(你看,我有点沮丧)
他们中的大多数都提出了在XML文件中使用 android:id
而不仅仅是 id
的建议 . 我做到了 .
我从其他人那里了解到, View.findViewById
与 Activity.findViewById
不同 . 我也是这样处理的 .
在我的 location_layout.xml
中,我使用:
<FrameLayout .... >
<some.package.MyCustomView ... />
<LinearLayout ... >
<TextView ...
android:id="@+id/txtLat" />
...
</LinearLayout>
</FrameLayout>
在我的活动中,我做了:
...
setContentView( R.layout.location_layout );
在我的自定义视图类中:
...
TextView tv = (TextView) findViewById( R.id.txtLat );
返回 null
. Doing this, my Activity works fine. 所以也许是因为 Activity.findViewById
和 View.findViewById
的差异 . 所以我在本地存储了传递给海关视图构造函数的上下文并尝试:
...
TextView tv = (TextView) ((Activity) context).findViewById( R.id.txtLat );
其中也返回 null
.
然后,我更改了我的自定义视图以扩展 ViewGroup
而不是 View
并更改 location_layout.xml
以让 TextView
成为我的自定义视图的直接子项,以便 View.findViewById
应该按预期工作 . 惊喜:它没有解决任何问题 .
那么我做错了什么?
我会感激任何评论 .
27 回答
可能是因为你太早称它 . 等到
onFinishInflate()
. Here is a sample project演示自定义View
访问其内容 .可能在调用
setContentView
之前调用findViewById
?如果是这种情况,请尝试调用findViewById
AFTER 调用setContentView
确保您的布局没有多个版本用于不同的屏幕密度 . 我在向现有布局添加新ID但忘记更新hdpi版本时遇到此问题 . 如果您忘记更新布局文件的所有版本,它将适用于某些屏幕密度,但不适用于其他屏幕密度 .
就我而言,我的项目中有2个活动,
main.xml
和main2.xml
. 从一开始,main2
就是main
的副本,一切运作良好,直到我将TextView
添加到main2
,所以R.id.textview1
可用于其他应用程序 . 然后我尝试通过标准调用来获取它:它总是空的 . 事实证明,在
onCreate
构造函数中,我实例化的不是main2
,而是另一个 . 我有:代替
我到达这里后,在网站上注意到了这一点 .
除了其他地方提到的经典原因:
确保在
findViewById()
之前调用setContentView()
确保您想要的
id
位于您提供给setContentView()
的视图或布局中确保
id
不会在不同的布局中意外重复我在标准布局中找到了一个自定义视图,这违反了文档:
理论上,您可以创建自定义视图并将其添加到布局(see here) . 但是,我发现在这种情况下,有时
id
属性适用于布局中除自定义视图之外的所有视图 . 我使用的解决方案是:使用
FrameLayout
替换每个自定义视图,其具有与自定义视图相同的布局属性 . 给它一个合适的id
,比如frame_for_custom_view
.在
onCreate
:它将自定义视图放在框架中 .
如果在自定义视图中调用错误的超级构造函数,则FindViewById可以为null . ID标记是attrs的一部分,因此如果忽略attrs,则删除ID .
这是错误的
这是对的
使用ExpandableListView的人的答案,并根据它的 Headers 运行这个问题 .
我尝试在我的子视图和组视图中使用TextViews作为ExpandableListView实现的一部分时出现此错误 .
您可以在getChildView()和getGroupView()方法的实现中使用类似下面的内容 .
我发现了这个here .
我是Android / Eclipse的新手,我错误地将UI内容添加到
activity_main.xml
而不是fragment_main.xml
. 花了我几个小时来搞清楚......FWIW,我没有看到任何人以我想要的方式解决这个问题 . 在编译时没有抱怨,但我在运行时获得了一个空视图,并以正确的顺序调用事物 . 也就是说,在setContentView()之后的findViewById() . 问题是我的视图是在content_main.xml中定义的,但在我的activity_main.xml中,我缺少这一个语句:
当我将它添加到activity_main.xml时,不再有NullPointer .
在我的特定情况下,我试图向ListView添加页脚 . 该跟随onCreate()的调用返回null .
更改此项以扩大页脚视图而不是通过ID查找它解决了此问题 .
我的情况不像上面那样,没有解决方案有效 . 我认为我的观点对布局层次结构太深了 . 我将它向上移动了一级,它不再是null .
就我而言,我使用的是ExpandableListView,我设置了
android:transcriptMode="normal"
. 这导致可扩展组中的少数子项消失,并且当我使用滚动列表时,我曾经得到NULL异常 .对我来说,我有两个xml布局用于相同的活动 - 一个在纵向模式,一个在横向 . 当然,我已经更改了横向xml中对象的id,但忘记了在纵向版本中进行相同的更改 . 确保你改变一个你对另一个xml做同样的事情,否则你不会得到错误,直到你运行/调试它并且它找不到你没有改变的id . 哦,愚蠢的错误,你为什么要这样惩罚我?
从布局资源设置活动内容 . 即 . ,
setContentView(R.layout.basicXml)
;我有同样的问题 . 我使用的是第三方库,它允许您覆盖GridView的适配器并为每个GridView单元指定自己的布局 .
我终于意识到发生了什么 . Eclipse仍然在GridView中为每个单元格使用库的布局xml文件,即使它没有给出任何指示 . 在我的自定义适配器中,它表明它正在使用我自己项目中的xml资源,即使在运行时,它也没有 .
所以我所做的是确保我的自定义xml布局和ID与仍然位于库中的那些不同,清理项目然后它开始阅读我项目中正确的自定义布局 .
简而言之,如果要覆盖第三方库的适配器并为适配器指定自己的布局xml,请务必小心 . 如果项目中的布局与库中的布局具有相同的文件名,则可能会遇到一个非常难以找到的错误!
除了以上解决方案,您还要确保
布局中的
tools:context=".TakeMultipleImages"
在mainfest.xml文件中是相同的值:android:name=".TakeMultipleImages"
用于相同的活动元素 . 使用复制和粘贴创建新活动时会发生这种情况我有同样的问题,但我认为它值得与你们分享 . 如果必须在自定义布局中查找ViewById,例如:
你无法在构造函数中获取视图 . 您应该在视图充气后调用findViewById . 他们是一种可以覆盖的方法
onFinishInflate
只是想在这里抛出我的具体案例 . 可能会帮助某人下线 .
我在我的Android UI XML中使用该指令,如下所示:
家长观点:
子视图(retry_button):
.findViewById(R.id.retry)将始终返回null . 但是,如果我将ID从子视图移动到include标记,它就开始工作了 .
固定父母:
固定儿童:
在我的情况下,我已经夸大了布局,但子视图返回null . 本来我有这个:
但是,当我将其更改为以下内容时,它可以工作:
关键是要专门引用已经膨胀的布局以获得子视图 . 也就是说,添加
footerView
:我已经尝试了上面所有的一切都没有工作..所以我不得不让我的 ImageView static
public static ImageView texture;
然后texture = (ImageView) findViewById(R.id.texture_back);
,我不是一个很好的方法,但这真的适用于我的情况:)根据我的经验,在OnDestroyView之后调用代码时(当片段位于后台堆栈时),似乎也会发生这种情况 . 如果要更新BroadCastReceiver输入的UI,您应该检查是否是这种情况 .
充满了布局! (包含id)
在我的情况下,findViewById()返回null,因为编写元素的布局没有膨胀...
例如 . fragment_layout.xml
findViewById(R.id.listview)返回null,因为我没有做过inflater.inflate(R.layout.fragment_layout,...,...);在它之前 .
希望这个答案可以帮助你们所有人 .
我的解决方法是清理项目 .
如果你在Fragment中,findViewById也可以返回null . 如下所述:findViewById in Fragment
您应该调用getView()以返回片段内的顶级视图 . 然后你可以找到布局项目(按钮,textviews等)
在我的例子中,findViewById返回null时我将调用从父对象移动到父对象实例化的适配器对象 . 在尝试了这里列出的技巧但没有成功之后,我将findViewById移回了父对象,并在实例化适配器对象期间将结果作为参数传递 . 例如,我在父对象中执行了此操作:
然后我在创建适配器对象期间将hdSpinner作为参数传递:
它崩溃了,因为我的活动ID中的一个字段与另一个活动中的id匹配 . 我通过给出一个唯一的ID来修复它 .
在我的loginActivity.xml中,密码字段id是“password” . 在我的注册活动中,我只是通过给出id r_password来修复它,然后它返回的不是null对象: