首先:是的,我阅读了有关此主题的所有其他主题。而且不仅是来自这个网站的人......(你看,我有点沮丧)
他们中的大多数都提出了在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
。 这样做,我的活动工作正常。所以可能是因为Activity.findViewById
和View.findViewById
的差异。所以我在本地存储了传递给海关视图构造函数的上下文并尝试:
...
TextView tv = (TextView) ((Activity) context).findViewById( R.id.txtLat );
也返回null
。
然后,我更改了自定义视图以扩展ViewGroup
而不是View
并更改了location_layout.xml
以让TextView
成为我的自定义视图的直接子项,以便View.findViewById
应该按照假设工作。惊喜:它没有解决任何问题。
那么我做错了什么?
我会感激任何评论。
答案 0 :(得分:248)
返回null
可能是因为你太早说了。等到onFinishInflate()
。 Here is a sample project演示了访问其内容的自定义View
。
答案 1 :(得分:138)
您可能在致电findViewById
之前致电setContentView
?
如果是这种情况,请尝试拨打findViewById
AFTER 致电setContentView
答案 2 :(得分:95)
确保您的布局没有多个版本,以适应不同的屏幕密度。我在向现有布局添加新ID但忘记更新hdpi版本时遇到此问题。如果您忘记更新布局文件的所有版本,它将适用于某些屏幕密度,但不适用于其他版本。
答案 3 :(得分:15)
就我而言,我的项目中有2个活动,main.xml
和main2.xml
。从一开始,main2
就是main
的副本,一切运作良好,直到我向TextView
添加了新的main2
,因此R.id.textview1
可用于应用程序的其余部分。然后我尝试通过标准调用来获取它:
TextView tv = (TextView) findViewById( R.id.textview1 );
它始终为空。事实证明,在onCreate
构造函数中,我实例化的不是main2
,而是另一个。{1}}。我有:
setContentView(R.layout.main);
而不是
setContentView(R.layout.main2);
我到达这里后,在网站上注意到了这一点。
答案 4 :(得分:13)
如果在自定义视图中调用错误的超级构造函数,则FindViewById可以为null。 ID标记是attrs的一部分,因此如果忽略attrs,则删除ID。
这是错误的
public CameraSurfaceView(Context context, AttributeSet attrs) {
super(context);
}
这是正确的
public CameraSurfaceView(Context context, AttributeSet attrs) {
super(context,attrs);
}
答案 5 :(得分:13)
除了其他地方提到的经典原因外:
setContentView()
findViewById()
id
位于您setContentView()
id
不会在不同的布局中意外重复我在标准布局中找到了一个自定义视图,这违反了文档:
理论上,您可以创建自定义视图并将其添加到布局(see here)。但是,我发现在这种情况下,有时id
属性适用于布局中除自定义视图之外的所有视图。我使用的解决方案是:
FrameLayout
。给它一个合适的id
,比如frame_for_custom_view
。在onCreate
:
setContentView(R.layout.my_layout);
FrameView fv = findViewById(R.id.frame_for_custom_layout);
MyCustomView cv = new MyCustomView(context);
fv.addView(cv);
将自定义视图放在框架中。
答案 6 :(得分:8)
@Override
protected void onStart() {
// use findViewById() here instead of in onCreate()
}
答案 7 :(得分:6)
使用ExpandableListView的人的答案,并根据它的标题运行这个问题。
我尝试在我的子视图和组视图中使用TextViews作为ExpandableListView实现的一部分时出现此错误。
您可以在getChildView()和getGroupView()方法的实现中使用以下内容。
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) myContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.child_layout, null);
}
我发现了here。
答案 8 :(得分:5)
我对Android / Eclipse很陌生,错误地我将UI内容添加到activity_main.xml
而不是fragment_main.xml
。花了我几个小时来搞清楚......
答案 9 :(得分:4)
FWIW,我没有看到任何人以我想要的方式解决这个问题。在编译时没有抱怨,但我在运行时获得了一个空视图,并以正确的顺序调用事物。那是, findViewById() 后的 的setContentView()。 问题是我的视图是在content_main.xml中定义的,但在我的activity_main.xml中,我缺少这一句话:
<include layout="@layout/content_main" />
当我将它添加到activity_main.xml时,不再有NullPointer。
答案 10 :(得分:3)
在我的特定情况下,我试图将一个页脚添加到ListView。 onCreate()中的以下调用返回null。
TextView footerView = (TextView) placesListView.findViewById(R.id.footer);
更改此项以扩充页脚视图而不是通过ID查找它解决了此问题。
View footerView = ((LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.footer_view, null, false);
答案 11 :(得分:3)
我的情况不像上面那样,没有解决方案有效。我认为我的观点对布局层次结构太深了。我将它向上移动了一级,它不再是空的。
答案 12 :(得分:2)
我有同样的问题。我使用的是第三方库,它允许您覆盖GridView的适配器并为每个GridView单元指定自己的布局。
我终于意识到发生了什么。 Eclipse仍然在GridView中为每个单元格使用库的布局xml文件,即使它没有给出任何指示。在我的自定义适配器中,它表明它正在使用我自己项目中的xml资源,即使在运行时,它也不是。
所以我所做的是确保我的自定义xml布局和ID与仍然位于库中的那些不同,清理项目然后它开始阅读我项目中正确的自定义布局。
简而言之,如果您要覆盖第三方库的适配器并为适配器指定自己的布局xml,请务必小心。如果项目中的布局与库中的文件名相同,则可能会遇到一个非常难以找到的错误!
答案 13 :(得分:2)
从布局资源设置活动内容。
即,setContentView(R.layout.basicXml)
;。
答案 14 :(得分:2)
除了上述解决方案,您还要确保
tools:context=".TakeMultipleImages"
在布局中,mainfest.xml文件中的值相同:
android:name=".TakeMultipleImages"
表示相同的活动元素。
使用复制和粘贴创建新活动时会发生这种情况
答案 15 :(得分:2)
就我而言,我使用的是ExpandableListView,并设置了android:transcriptMode="normal"
。这导致可扩展组中的少数子项消失,并且当我使用滚动列表时,我曾经得到NULL异常。
答案 16 :(得分:2)
我有同样的问题,但我认为值得与你们分享。 如果必须在自定义布局中查找ViewById,例如:
public class MiniPlayerControllBar extends LinearLayout {
//code
}
你无法在构造函数中获取视图。
您应该在视图充气后调用findViewById。
他们是一种可以覆盖onFinishInflate
答案 17 :(得分:2)
对我来说,我有两个xml布局用于同一个活动 - 一个在纵向模式,一个在横向。当然,我已经更改了横向xml中对象的id,但忘记了在纵向版本中进行相同的更改。确保你改变一个你对另一个xml做同样的事情,否则你不会得到错误,直到你运行/调试它并且它找不到你没有改变的id。哦,愚蠢的错误,你为什么要这样惩罚我?
答案 18 :(得分:2)
只是想在这里抛出我的具体案例。可能会帮助某人下线。
我在我的Android UI XML中使用了这样的指令:
家长观点:
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:tag="home_phone"
android:background="@color/colorPrimary">
...
<include
layout="@layout/retry_button"
android:visibility="gone" />
子视图(retry_button):
<com.foo.RetryButton
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/retry"
android:layout_gravity="center"
android:orientation="vertical"
android:layout_width="100dp"
android:layout_height="140dp">
.findViewById(R.id.retry)将始终返回null。但是,如果我将ID从子视图移动到include标记,它就会开始工作。
固定父母:
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:tag="home_phone"
android:background="@color/colorPrimary">
...
<include
layout="@layout/retry_button"
android:id="@+id/retry"
android:visibility="gone" />
修正儿童:
<com.foo.RetryButton
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_gravity="center"
android:orientation="vertical"
android:layout_width="100dp"
android:layout_height="140dp">
答案 19 :(得分:1)
在我的情况下,我已经夸大了布局,但子视图返回null。最初我有这个:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_history);
footerView = ((LayoutInflater) getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.listview_footer, null, false);
pbSpinner = (ProgressBar) findViewById(R.id.pbListviewFooter);
tvText = (TextView) findViewById(R.id.tvListviewFooter);
...
}
然而,当我将其改为以下时,它起作用了:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_history);
footerView = ((LayoutInflater) getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.listview_footer, null, false);
pbSpinner = (ProgressBar) footerView.findViewById(R.id.pbListviewFooter);
tvText = (TextView) footerView.findViewById(R.id.tvListviewFooter);
...
}
关键是要专门引用已经膨胀的布局以获取子视图。也就是说,添加footerView
:
答案 20 :(得分:1)
我已经尝试了上述所有内容都没有工作..所以我必须让我的 ImageView静态 public static ImageView texture;
然后texture = (ImageView) findViewById(R.id.texture_back);
,我不认为这是虽然这是一个很好的方法,但这确实适用于我的情况:)
答案 21 :(得分:0)
我的解决方法是清理项目。
答案 22 :(得分:0)
如果你在片段中,findViewById也可以返回null。如下所述:findViewById in Fragment
您应该调用getView()以返回片段内的顶级视图。然后你可以找到布局项目(按钮,文本视图等)
答案 23 :(得分:0)
充满布局! (包含id)
在我的情况下,findViewById()返回null,因为编写元素的布局没有膨胀......
EG。 fragment_layout.xml
Random
findViewById(R.id.listview)返回null,因为我没有这样做 inflater.inflate(R.layout.fragment_layout,...,...); 在它之前。
希望这个答案可以帮助所有人。
答案 24 :(得分:0)
根据我的经验,在OnDestroyView之后调用代码时(当片段位于后台堆栈时),似乎也会发生这种情况。如果要更新BroadCastReceiver输入的UI,您应该检查是否是这样的。
答案 25 :(得分:0)
在我的情况下,当我将调用从父对象移动到由父对象实例化的适配器对象时,findViewById返回null。在尝试了此处未列出的技巧之后,我将findViewById移回了父对象,并在实例化适配器对象期间将结果作为参数传递。 例如,我是在父对象中完成的:
Spinner hdSpinner = (Spinner)view.findViewById(R.id.accountsSpinner);
然后我在创建适配器对象的过程中将hdSpinner作为参数传递:
mTransactionAdapter = new TransactionAdapter(getActivity(),
R.layout.transactions_list_item, null, from, to, 0, hdSpinner);
答案 26 :(得分:0)
它崩溃了,因为我的活动ID中的一个字段与另一个活动中的ID匹配。我通过提供唯一的ID对其进行了修复。
在我的loginActivity.xml密码字段中,ID为“ password”。在我的注册活动中,我只是通过提供id r_password对其进行了修复,然后它返回的不是null对象:
password = (EditText)findViewById(R.id.r_password);
答案 27 :(得分:0)
当我尝试为ListView
创建自定义视图时,我遇到了类似的问题。
我只是通过以下方法解决了它:
public View getView(int i, View view, ViewGroup viewGroup) {
// Gets the inflater
LayoutInflater inflater = LayoutInflater.from(this.contexto);
// Inflates the layout
ConstraintLayout cl2 = (ConstraintLayout)
inflater.inflate(R.layout.custom_list_view, viewGroup, false);
//Insted of calling just findViewById, I call de cl2.findViewById method. cl2 is the layout I have just inflated.
TextView tv1 = (TextView)cl2.findViewById(cl2);
答案 28 :(得分:0)
调试和发现问题的方法:
就我而言,我在我的应用程序模块和库模块中都使用了activity_main.xml。因此,当我执行上述步骤时,不是我在库中设计的布局,而是应用模块内部的布局膨胀了。
所以我将activity_main.xml文件名更改为activity_main_lib.xml。
因此请确保您在整个项目中没有重复的布局名称。