我有res/layout/main.xml
包含这些元素和其他元素:
<some.package.MyCustomView android:id="@+id/foo" (some other params) />
<TextView android:id="@+id/boring" (some other params) />
在我的活动on 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"); }
成功找到其他元素,但foo
返回null。 MyCustomView有一个构造函数MyCustomView(Context c, AttributeSet a)
,并且该构造函数末尾的Log.d(...)
在“史诗失败”之前的logcat中成功出现。
为什么foo
为空?
答案 0 :(得分:171)
因为在构造函数中,我有super(context)
而不是super(context, attrs)
。
有道理,如果你没有传递属性,比如id,那么视图将没有id,因此无法使用该id找到。 : - )
答案 1 :(得分:22)
我有同样的问题,因为在我的自定义视图中,我覆盖了构造函数,但调用了超级构造函数和attrs参数。那是复制粘贴)
我以前的构造函数版本:
public TabsAndFilterRelativeLayout(Context context, AttributeSet attrs) {
super(context);
}
现在我有:
public TabsAndFilterRelativeLayout(Context context, AttributeSet attrs) {
super(context, attrs);}
这有效!
答案 2 :(得分:18)
我遇到了同样的问题。我的错误是:我写了
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);
我写了我的解决方案,以防有人遇到同样的问题。
答案 3 :(得分:18)
似乎有多种原因。我只是在Eclipse中使用“Clean ...”来解决类似的问题。 (FindViewByID之前已经工作过,并且由于某种原因开始返回null。)
答案 4 :(得分:11)
答案 5 :(得分:4)
如果您有多个版面版本(取决于屏幕密度,SDK版本),请确保所有版面都包含您要查找的元素。
答案 6 :(得分:2)
在我的情况下,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"
/>
答案 7 :(得分:2)
确保在setContentView(R.layout.main)
语句之前调用findViewById(...)
语句;
答案 8 :(得分:1)
对我来说,当我在项目设置中将res文件夹添加到Java Build Path中的Source时,问题就解决了。
答案 9 :(得分:1)
我遇到了一个针对Wear的自定义组件,但这是一个通用的建议。如果您正在使用存根(例如我使用的是WatchViewStub
),则您无法将呼叫置于findViewById()
的任何位置。存根中的所有内容必须首先膨胀,这不会在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);
...
答案 10 :(得分:1)
当我通过布局XML和添加自定义视图时,我遇到了同样的问题 然后尝试在应用程序的其他地方附加一个回调...
我创建了一个自定义视图并将其添加到我的“layout_main.xml”
public class MUIComponent extends SurfaceView implements SurfaceHolder.Callback {
public MUIComponent (Context context, AttributeSet attrs ) {
super ( context, attrs );
}
// ..
}
在主Activity中我想附加一些回调并从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”之间的区别是:
答案 11 :(得分:0)
'干净'选项对我有用。
就我而言,根本原因是源代码驻留在网络共享上,而我的工作站和文件服务器未正确同步,并且漂移了5秒。 Eclipse创建的文件的时间戳是过去的(因为它们是由文件服务器分配的)w.r.t.工作站的时钟,导致Eclipse错误地解决生成和源文件之间的依赖关系。在这种情况下,'clean'似乎有效,因为它强制完全重建而不是依赖于错误时间戳的增量构建。
在我的工作站上修复NTP设置后,问题再也没有发生过了。如果没有适当的NTP设置,它会每隔几个小时发生一次,因为时钟会快速漂移。
答案 12 :(得分:0)
在我的情况下,视图位于我试图调用它的视图中的父视图中。所以在子视图中我不得不调用:
RelativeLayout relLayout = (RelativeLayout) this.getParent();
View view1 = relLayout.findViewById(R.id.id_relative_layout_search);
答案 13 :(得分:0)
当布局的根没有findViewById()
属性时,null
方法有时会返回android:id
。用于生成布局xml文件的Eclipse向导不会自动为根元素生成android:id
属性。
答案 14 :(得分:0)
要在答案中添加另一个微不足道的错误,请注意:
检查您是否正在编辑正确的布局XML文件...
答案 15 :(得分:0)
我有同样的问题,因为我忘了更新所有布局文件夹中的视图ID。
答案 16 :(得分:0)
有同样的问题。
我有几个孩子的布局。从他们的构造函数我试图获得引用(通过使用context.findViewById)到其他子。它没有用,因为第二个孩子在布局中被进一步定义。
我已经解决了这个问题:
setContentView(R.layout.main);
MyView first = findViewById(R.layout.first_child);
first.setSecondView(findViewById(R.layout.second_child));
如果孩子的顺序相反,它也会起作用,但我想通常应该如上所述。
答案 17 :(得分:0)
我的问题是拼写错误。我写了android.id
(点)而不是android:id
。 :P
显然我的自定义组件xml中没有语法检查。 :(