findViewByID返回null

首先,是的,我读了关于这个话题的所有其他帖子。不仅仅是这个网站的人…(你看,我有点沮丧)

它们中的大多数都建议在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.findViewByIdView.findViewById的差异。所以我存储上下文传递给本地的海关视图构造函数,并尝试:

...
TextView tv = (TextView) ((Activity) context).findViewById( R.id.txtLat );

它也返回null

然后,我更改了自定义视图,扩展了ViewGroup而不是View,并更改了location_layout.xml,让TextView成为自定义视图的直接子视图,这样View.findViewById就应该像假设的那样工作。令人惊讶的是:它并没有解决任何问题。

我到底做错了什么?

欢迎任何意见。

204916 次浏览

返回null

可能是因为你说得太早了。等到onFinishInflate()下面是一个示例项目演示了访问其内容的自定义View

确保你的布局没有针对不同屏幕密度的多个版本。我曾经遇到过这个问题,当添加一个新的id到现有的布局,但忘记更新hdpi版本。如果你忘记更新所有版本的布局文件,它将工作的一些屏幕密度,但不是其他。

可能,你在调用setContentView之前调用了findViewById ? 如果是这种情况,尝试调用findViewById 调用setContentView

对于那些使用ExpandableListView并根据它的标题遇到这个问题的人来说,这是一个答案。

我有这个错误试图与TextViews在我的孩子和组视图作为一个expandabelistview实现的一部分。

您可以在getChildView()和getGroupView()方法的实现中使用如下内容。

        if (convertView == null) {
LayoutInflater inflater =  (LayoutInflater) myContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.child_layout, null);
}

我发现这个在这里

在我的例子中,我使用的是expandabelistview,并且我设置了android:transcriptMode="normal"。这导致可扩展组中的几个孩子消失,我习惯了在我使用滚动列表时得到NULL异常。

在我的例子中,我的项目中有2个活动,main.xmlmain2.xml。从一开始,main2main的副本,一切都工作得很好,直到我向main2添加了新的TextView,所以R.id.textview1对应用程序的其余部分可用。然后我试图通过标准调用获取它:

TextView tv = (TextView) findViewById( R.id.textview1 );

它总是空的。事实证明,在onCreate构造函数中,我实例化的不是main2,而是另一个。我有:

setContentView(R.layout.main);

而不是

setContentView(R.layout.main2);

我到这里后,在工地上注意到了这一点。

对我来说,同一个活动有两个xml布局——一个竖屏模式,一个横屏模式。当然,我已经在landscape xml中更改了一个对象的id,但忘记在portrait版本中做同样的更改。如果您更改了一个xml,请确保对另一个xml也执行相同的操作,否则在运行/调试它之前不会得到错误,并且它无法找到未更改的id。哦,愚蠢的错误,你为什么要这样惩罚我?

根据我的经验,这似乎也会发生在你的代码被调用后OnDestroyView(当片段是在后面的堆栈)。如果您正在根据BroadCastReceiver的输入更新UI,则应该检查是否存在这种情况。

我对Android/Eclipse很陌生,我错误地将UI的东西添加到activity_main.xml而不是fragment_main.xml。我花了好几个小时才弄明白……

    @Override
protected void onStart() {
// use findViewById() here instead of in onCreate()
}

设置布局资源的活动内容。 即,setContentView(R.layout.basicXml); < / p >

我也有同样的问题。我使用了一个第三方库,它允许你覆盖GridView的适配器,并为每个GridView单元指定自己的布局。

我终于意识到发生了什么。Eclipse仍然在为GridView中的每个单元格使用库的布局xml文件,尽管它没有给出这一点指示。在我的自定义适配器中,它表明它正在使用来自我自己项目的xml资源,尽管在运行时并不是这样。

所以我所做的是确保我的自定义xml布局和id与那些仍然坐在库中,清理项目,然后它开始读取正确的自定义布局,在我的项目中。

简而言之,如果要覆盖第三方库的适配器并指定自己的布局xml供适配器使用,请小心。如果项目中的布局与库中的布局具有相同的文件名,那么您可能会遇到一个非常难以找到的错误!

除了在其他地方提到的经典原因之外:

  • 确保在findViewById()之前调用了setContentView()
  • 确保你想要的id在你给setContentView()的视图或布局中
  • 确保id不会在不同的布局中被意外复制

我在标准布局中找到了一个自定义视图,这与文档相悖:

理论上,您可以创建一个自定义视图并将其添加到布局中(在这里看到的)。然而,我发现在这种情况下,有时id属性适用于布局中的所有视图,除了自定义视图。我使用的解决方案是:

  1. 将每个自定义视图替换为FrameLayout,该FrameLayout具有您希望自定义视图具有的相同布局属性。给它一个合适的id,比如frame_for_custom_view
  2. onCreate < p >:

    setContentView(R.layout.my_layout);
    FrameView fv = findViewById(R.id.frame_for_custom_layout);
    MyCustomView cv = new MyCustomView(context);
    fv.addView(cv);
    

    将自定义视图放入帧中

在我的情况下,我已经膨胀布局,但子视图返回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:

  • footerView.findViewById……

在我的特殊情况下,我试图添加一个页脚到一个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);

除了上面的解决方案,你要确保
tools:context=".TakeMultipleImages" 布局中的值与mainfest.xml文件中的值相同:
android:name=".TakeMultipleImages"为相同的活动元素。 当使用复制和粘贴创建新的活动

时发生

如果在自定义视图中调用了错误的超级构造函数,FindViewById可以为空。ID标记是attrs的一部分,因此如果忽略attrs,则删除ID。

这是错误的

public CameraSurfaceView(Context context, AttributeSet attrs) {
super(context);
}

这是正确的

public CameraSurfaceView(Context context, AttributeSet attrs) {
super(context,attrs);
}
我也有同样的问题,但我认为值得和你们分享。 如果你必须在自定义布局中找到viewbyid,例如:

public class MiniPlayerControllBar extends LinearLayout {
//code
}

你不能在构造函数中得到视图。 你应该在视图膨胀后调用findViewById。 这是一个你可以覆盖onFinishInflate

的方法

膨胀布局!!(包含id)

在我的例子中,findViewById()返回null,因为元素被写入的布局没有被膨胀…

< p >。 fragment_layout.xml < / p >
<ListView
android:id="@+id/listview">

findViewById(R.id.listview)返回null,因为我没有做 inflater.inflate (R.layout.fragment_layout……,……); 之前它。< / p >

希望这个答案能帮助到你们。

我的解决办法是清理项目。

我只是想把我的具体案子提出来。也许能帮到别人。

我使用的指令在我的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">
FWIW,我没有看到任何人以我需要的相同方式解决这个问题。在编译时没有抱怨,但我在运行时得到一个空视图,并以适当的顺序调用东西。也就是说, findViewById () setContentView()。 问题是,我的视图是在content_main.xml中定义的,但在activity_main.xml中,我缺少这一条语句:

<include layout="@layout/content_main" />

当我将其添加到activity_main.xml时,不再有NullPointer。

如果你在Fragment中,findViewById也可以返回null。如上所述:在Fragment中找到viewbyid

你应该调用getView()来返回Fragment中最顶层的View。然后你可以找到布局项(按钮,文本视图等)

我试过以上所有的方法,但都没有效果。所以我必须让我的ImageView静态 public static ImageView texture;,然后texture = (ImageView) findViewById(R.id.texture_back);,我不认为这是一个很好的方法,但这确实适用于我的情况:)

我的情况不像上面那样,没有解决方案。我认为我的观点过于深入布局层次结构。我向上移动了一层,它就不再是空了。

在我的例子中,当我将调用从父对象移动到由父对象实例化的适配器对象时,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);

它崩溃了,因为我的活动id中的一个字段与其他活动的id匹配。我通过给出一个唯一的id来修复它。

在我的loginActivity.xml密码字段id是“password”。在我的注册活动中,我只是通过给出id r_password来修复它,然后它返回非空对象:

password = (EditText)findViewById(R.id.r_password);

当我试图为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);

调试和查找问题的方法:

  • 注释掉活动中的所有findViewById。
  • 注释掉所有的东西,除了onCreate和setContentView
  • 运行项目并查看是否设置了任何布局

在我的情况下,我使用activity_main.xml在我的应用程序模块和我的库模块。所以当我执行上面的步骤,而不是我在库中设计的布局,app模块内的布局是膨胀的。

因此,我将activity_main_xml文件名称改为activity_main_lib.xml。

所以确保在整个项目中没有任何重复的布局名称

对我来说,问题是我有两个具有相同文件名activity_main.xml的布局。(布局在不同的库中,但在同一个应用程序中)通过将其中一个重命名为唯一的名称解决了这个问题。

对我来说,它返回null,因为给定的控件是(以编程方式)隐藏的。当我只在控件可见时调用findViewByID(id)时,它又开始工作了。

对我来说,它只在使用IDE的计算表达式调试表视图时为空。