findViewById() 为对话框中的视图返回 null

Posted

技术标签:

【中文标题】findViewById() 为对话框中的视图返回 null【英文标题】:findViewById() returns null for Views in a Dialog 【发布时间】:2013-04-18 00:38:56 【问题描述】:

问题是,无论我在何处或如何调用此布局的组件,它们总是返回 null。

setView(inflater.inflate(R.layout.search_layout, null))

这很好用。它显示Dialog 内的布局,但是,findViewById(R.id.some_search_layout_children) 始终将子级返回为 null。

我多次尝试清理我的项目,尝试为我的Dialog 实现另一个类,称为findViewById(),作为我的主要Activity 的成员,在initSearch() 方法内部和匿名实现内部OnClickListenerDialog,但结果相同。我还尝试将孩子们分成独立的Views 并以编程方式调用他们:

TextView text = (TextView) findResourceById(R.id.new_independant_textview);

但是,同样的结果。

这是相关代码:

public class Xyz extends Activity 
    public void onCreate(...)  // some listener will trigger initSearch() 

    private void initSearch() 
        AlertDialog.Builder searchDialog = new AlertDialog.Builder(this);
        LayoutInflater inflater = this.getLayoutInflater();
        searchDialog.setTitle("Search Photos");
        searchDialog.setMessage("Specify tag and value...");
        // R.layout.search_dialog is my custom layour, it displays fine, it works. 
        searchDialog.setView(inflater.inflate(R.layout.search_dialog, null));
        EditText tagText = (EdiText) findViewById(R.id.tagField); // WILL RETURN NULL
        searchDialog.setPositiveButton( ... ) ...
        searchDialog.show();
    

这一行:

 EditText text = (EditText) findViewById(R.id.tagField);

始终返回 null,无论以何种方式或在何处调用 - 全局、本地 final 等 - 它只返回 null。

这是我的自定义 Dialog 布局的 XML:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/search_dialog"
    android:layout_
    android:layout_
    android:orientation="vertical" >
    <TextView
        android:id="@+id/tagText" 
        android:padding="7dp"
        android:layout_
        android:layout_
        android:textSize="14sp"
        android:text="@string/tag" />
    <EditText 
        android:id="@+id/tagField"
        android:padding="7dp"
        android:layout_
        android:layout_
        android:inputType="text"/>
    <TextView
        android:id="@+id/valueText" 
        android:padding="7dp"
        android:layout_
        android:layout_
        android:textSize="14sp"
        android:text="@string/value" />
    <EditText 
        android:id="@+id/valueField"
        android:padding="7dp"
        android:layout_
        android:layout_
        android:inputType="text"/>
</LinearLayout>

这是我的R.java 文件:

public static final class id 
    public static final int action_settings=0x7f0a0011;
    public static final int add_album=0x7f0a0001;
    public static final int add_photo=0x7f0a000d;
    public static final int albums_list=0x7f0a0003;
    public static final int delete_album=0x7f0a000b;
    public static final int exit_finder=0x7f0a000f;
    public static final int new_directory=0x7f0a000e;
    public static final int open_album=0x7f0a000a;
    public static final int photos_grid=0x7f0a0000;
    public static final int rename_album=0x7f0a000c;
    public static final int search_dialog=0x7f0a0004;
    public static final int search_icon=0x7f0a0002;
    public static final int splash_rutgers=0x7f0a0009;
    public static final int tagField=0x7f0a0006; // problematic
    public static final int tagText=0x7f0a0005; / problematic
    public static final int terminate_app=0x7f0a0010;
    public static final int valueField=0x7f0a0008; // problematic
    public static final int valueText=0x7f0a0007; // problematic

【问题讨论】:

你想在另一个活动中调用 findViewById 的对话框中找到视图......祝你好运...... 听起来很有趣,但我不完全理解为什么我需要一个新的活动。那么为什么 R.layot.search_dialog 返回正确的布局但它的孩子是空的?那里没有一致性。 【参考方案1】:

调用findViewById() 将在您的Activity 的 布局中搜索视图,而不是 您的对话框的视图。您需要在设置为对话框布局的特定 View 上调用 findViewById()

试试这个

private void initSearch() 
    AlertDialog.Builder searchDialog = new AlertDialog.Builder(this);
    LayoutInflater inflater = this.getLayoutInflater();
    searchDialog.setTitle("Search Photos");
    searchDialog.setMessage("Specify tag and value...");
    // R.layout.search_dialog is my custom layour, it displays fine, it works. 
    View dialogView = inflater.inflate(R.layout.search_dialog, null);
    searchDialog.setView(dialogView);
    EditText tagText = (EdiText) dialogView.findViewById(R.id.tagField); 
    searchDialog.setPositiveButton( ... ) ...
    AlertDialog myAlert = searchDialog.create(); //returns an AlertDialog from a Builder.
    myAlert.show();

注意我是如何扩充视图并将其存储在名为 dialogViewView 中的。然后,要找到你的EditText 名为tagField,我使用的是dialogView.findViewById(R.id.tagField);

【讨论】:

正确答案。谢谢大家。 拯救了我的一天,谢谢 :)【参考方案2】:

ID 为text123TextView 必须在您使用setContentView 设置的Layout 中声明

【讨论】:

实际上,我认为 text123 是一个示例,因为 OP 在其“主要”代码部分中有 EditText tagText = (EdiText) findViewById(R.id.tagField); // WILL RETURN NULL。但是这个答案确实让我笑了。 +1。 @TronicZomB 我读了这个 EditText text = (EditText) findViewById(R.id.text123); // 返回 null,总是 @Fer 你试过像EditText text = (EditText) getDialog().findViewById()这样的东西吗? 在 initSearc() 中,在 setTitle 和 setMessage 之后,您可以执行以下操作:AlertDialog dialog = searchDialog.create(); dialog.setContentView(R.layout.search_dialog); dialog.findViewById(R.id.tagField);它应该工作。它对我有用 TronicZomB 和 blackbelt 都击中了钉子。谢谢小伙伴们的知识。我错过了实际对话中的上下文。【参考方案3】:

您的问题是您尝试在 AlertDialog Builder 上执行 .show(),而不是 AlertDialog 本身。

试试下面的代码:

public class Xyz extends Activity 
public void onCreate(...)  // some listener will trigger initSearch() 

private void initSearch() 
    AlertDialog.Builder searchDialog = new AlertDialog.Builder(this);
    LayoutInflater inflater = this.getLayoutInflater();
    searchDialog.setTitle("Search Photos");
    searchDialog.setMessage("Specify tag and value...");
    // R.layout.search_dialog is my custom layour, it displays fine, it works. 
    searchDialog.setView(inflater.inflate(R.layout.search_dialog, null));
    EditText tagText = (EdiText) findViewById(R.id.tagField); // WILL RETURN NULL
    searchDialog.setPositiveButton( ... ) ...
    AlertDialog myAlert = searchDialog.create(); //returns an AlertDialog from a Builder.
    myAlert.show();

【讨论】:

实际上,可以在Builder 上调用show(),它只是创建AlertDialog 并显示它。 developer.android.com/reference/android/app/… @Zabri 哦,好的。我不知道。谢谢! 好方法。解决方法是创建一个shell Dialog,用Builder实例化它,在Dialog上setContentView,在Builder上setView,然后在dialog实例上findViewById。 @Fer 哦,谢谢!我通常使用 DialogFragments 并返回 builder.create() 然后在需要时显示它,因此我不知道 .show() 会在一行中创建并显示它。虽然很高兴知道。【参考方案4】:

我在编写多语言应用程序时遇到了完全相同的问题。 最终我发现我忘记更新某些布局的活动 [xml] 文件中的标签。

每个活动我有 3 个:

<activity_name>.xml
<activity_name>.xml(land)
<activity_name>.xml(iw)

我只更新了第一个,忘记更新另一个如下:

这三个都有一个 TextView,其 id 为:

    <TextView
    android:id="@+id/loading_textbox"
    .../>

然后我将该文本视图的 id 的名称(仅在第一个文件中)更改为:

    <TextView
    android:id="@+id/status_textbox"
    .../>

当然,在 Activity 的 Java 代码中(使用所有三个...):

    TextView tv = findViewByID(R.id.status_textbox);

这适用于常规(英语&lt;activity_name&gt;.xml)版本。

但是当我使用 IW 语言时(希伯来语 &lt;activity_name&gt;xml(iw)tv 得到了 null 值,我什至有些迷恋。

当我将其他文件的文本视图 ID 更改为 "@+id/status_textbox" 时,一切都像魅力一样......

因此,只需确保您的所有 ID 都已更新并在您的所有布局和语言中得到体现。

无论如何,这解决了我的问题..

【讨论】:

以上是关于findViewById() 为对话框中的视图返回 null的主要内容,如果未能解决你的问题,请参考以下文章

findviewbyid 在对话框中返回 null

所有视图(图像、文本等)从 mainActivity 的 findViewById() 返回 null

是否建议在每次 findViewById 调用时检查视图是否为空?

对于自定义Dialog需调用啥方法将动态创建的视图dialogview显示到Dialog上?

Xamarin Adapter FindViewById返回null

findViewById() 为布局 XML 中的自定义组件返回 null,而不是其他组件