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

我有一个res/layout/main.xml包括这些元素和其他:

 <some.package.MyCustomView android:id="@+id/foo" (some other params) /> <TextView android:id="@+id/boring" (some other params) /> 

在我的Activity的onCreate中,我这样做:

 setContentView(R.layout.main); TextView boring = (TextView) findViewById(R.id.boring); // ...find other elements... MyCustomView foo = (MyCustomView) findViewById(R.id.foo); if (foo == null) { Log.d(TAG, "epic fail"); } 

其他元素被成功find,但是foo返回null。 MyCustomView有一个构造函数MyCustomView(Context c, AttributeSet a)和一个Log.d(...)在构造函数的最后成功出现在logcat之前的“史诗般的失败”。

为什么foo空?

因为在构造函数中,我super(context)而不是super(context, attrs)

有意义的是,如果你不传入属性,如id,那么视图将没有id,因此不能使用该idfind。 🙂

我有同样的问题。 我的错误是:我写了

  LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE); View layout=inflater.inflate(R.layout.dlg_show_info, null); alertDlgShowInfo.setView(layout); TableRow trowDesc=(TableRow)findViewById(R.id.trowDesc); 

当我使用inflater从XML文件“加载”视图时,最后一行是错误的。 要解决这个问题,我必须写下:

 TableRow trowDesc=(TableRow)layout.findViewById(R.id.trowDesc); 

我写了我的解决scheme,以防有人遇到同样的问题。

似乎有多种原因。 我只是在Eclipse中使用“Clean …”来解决类似的问题。 (FindViewByID之前工作,由于某种原因开始返回null。)

我有同样的问题,因为在我的自定义视图中,我重写了构造函数,但调用超级构造函数与attrs参数。 那是复制粘贴)

我以前的构造函数版本:

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

我现在有:

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

那可行!

同样的问题,但不同的解决scheme:我没有打电话

 setContentView(R.layout.main) 

之前我试图find这里所述的观点

如果您有多个布局版本(取决于屏幕密度,SDK版本),请确保它们都包含您正在查找的元素。

在我的情况下,findViewById返回null,因为我的自定义视图在主XML中看起来像这样:

  <com.gerfmarquez.seekbar.VerticalSeekBar android:id="@+id/verticalSeekBar" android:layout_width="wrap_content" android:layout_height="fill_parent" /> 

我发现当我添加了xmlns的东西,它的工作是这样的:

  <com.gerfmarquez.seekbar.VerticalSeekBar xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/verticalSeekBar" android:layout_width="wrap_content" android:layout_height="fill_parent" /> 

确保在findViewById(...)语句之前调用setContentView(R.layout.main) findViewById(...)语句;

对我来说,当我将res文件夹添加到项目设置中的Java Build Path中的Source时,问题就解决了。

我遇到同样的问题,当我通过布局XML添加一个自定义视图,然后尝试附加在应用程序的其他地方callback…

我创build了一个自定义视图,并将其添加到我的“layout_main.xml”

 public class MUIComponent extends SurfaceView implements SurfaceHolder.Callback { public MUIComponent (Context context, AttributeSet attrs ) { super ( context, attrs ); } // .. } 

在主Activity中,我想附加一些callback,并从XML中获取对UI元素的引用。

 public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // ... MUIInitializer muiInit = new MUIInitializer(); muiInit.setupCallbacks(this); muiInit.intializeFields(this); } } 

initilizer没有做任何事情,但是它试图对自定义视图(MUIComponent)或其他非自定义 UI元素进行的任何更改都不会在应用程序中出现。

 public class MUIInitializer { // ... public void setupCallbacks ( Activity mainAct ) { // This does NOT work properly // - The object instance returned is technically an instance of my "MUICompnent" view // but it is a *different* instance than the instance created and shown in the UI screen // - Callbacks never get triggered, changes don't appear on UI, etc. MUIComponent badInst = (MUIComponent) mainAct.findViewById(R.id.MUIComponent_TESTSURF); // ... // This works properly LayoutInflater inflater = (LayoutInflater) mainAct.getSystemService(Context.LAYOUT_INFLATER_SERVICE); View inflatedLayout = inflater.inflate ( R.layout.activity_main, null ); MUIComponent goodInst = (MUIComponent) inflatedLayout.findViewById(R.id.MUIComponent_TESTSURF); // Add callbacks // ... } } 

“badInst”和“goodInst”之间的区别是:

  • badInst使用Activity的findViewByID
  • goodInst膨胀布局,并使用膨胀的布局来进行查找

这发生在我身上的是Wear的一个自定义组件,但是这是一个通用的build议。 如果你使用的是存根(比如我使用的是WatchViewStub ),那么你不能只把调用放到findViewById()任何地方。 存根(stub)内的所有东西都必须首先被膨胀,这不仅发生在setContentView() 。 因此,你应该写这样的事情,以等待发生:

 protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_wear); final WatchViewStub stub = (WatchViewStub) findViewById(R.id.watch_view_stub); stub.setOnLayoutInflatedListener(new WatchViewStub.OnLayoutInflatedListener() { @Override public void onLayoutInflated(WatchViewStub stub) { myCustomViewInst = (MyCustomView) findViewById(R.id.my_custom_view); ... 

我的问题是一个错字。 我写了android.id (点),而不是android:id 。 :P

显然,在我的自定义组件xml中没有语法检查。 🙁

有同样的问题。

我有几个孩子的布局。 从一个他们的构造函数,我试图获得引用(通过使用context.findViewById)给其他孩子。 这是不行的,因为第二个孩子是在布局进一步定义。

我已经解决了这个问题:

 setContentView(R.layout.main); MyView first = findViewById(R.layout.first_child); first.setSecondView(findViewById(R.layout.second_child)); 

如果孩子们的顺序是相反的,那也是一样,但是我想一般应该像上面这样做。

当layout的根没有android:id属性时, findViewById()方法有时会返回null 。 用于生成布局xml文件的Eclipse向导不会自动为根元素生成android:id属性。

在我的情况下,视图是在父母不是在我试图调用它的视图。所以在子视图中,我不得不打电话:

 RelativeLayout relLayout = (RelativeLayout) this.getParent(); View view1 = relLayout.findViewById(R.id.id_relative_layout_search); 

“干净”选项为我工作。

在我的情况下,根本原因是源代码驻留在networking共享,我的工作站和文件服务器没有正确同步,并已漂移了5秒。 由Eclipse创build的文件的时间戳过去(因为它们由文件服务器分配)与工作站的时钟相关,导致Eclipse错误地parsing生成的文件和源文件之间的依赖关系。 在这种情况下,一个“干净的”似乎工作,因为它强制一个完整的重build,而不是依赖于错误的时间戳的增量构build。

一旦我在我的工作站上修复了NTP设置,问题再也没有发生过。 如果没有正确的NTP设置,每隔几个小时就会发生一次,因为时钟漂移很快。

要添加另一个微不足道的错误的答案要留意:

检查你是否正在编辑正确的布局XML文件…

我有同样的问题,因为我忘了更新所有我的布局文件夹中的视图ID。