Xamarin.Android中无法通过Resource Id获取视图问题咨询
刚接触Xamarin.Forms就上手自定义相机,这步子迈得挺实在!我来帮你排查下Android端通过ContentPageRenderer获取视图时遇到的异常问题,通常都是这几个常见原因导致的:
1. Resource Id引用的命名空间错了
千万别把系统的Android.Resource.Id和你项目里的YourAppName.Droid.Resource.Id搞混!系统的Id是安卓自带的控件id,而你布局里自定义的id是在项目的Resource类里生成的。比如你布局里写了android:id="@+id/camera_preview",那获取的时候得这么写:
// 确保用的是你自己项目的Resource命名空间 var previewView = FindViewById<TextureView>(Resource.Id.camera_preview);
如果不小心用了Android.Resource.Id.camera_preview,肯定会找不到视图抛异常。
2. 获取视图的时机太早
在Renderer的生命周期里,绝对不能在构造函数里去FindViewById!要等视图布局完成,正确的时机是在OnElementChanged方法中,当e.NewElement != null的时候,先Inflate布局,再去获取控件:
protected override void OnElementChanged(ElementChangedEventArgs<ContentPage> e) { base.OnElementChanged(e); if (e.NewElement != null) { // 先加载自定义相机布局 var cameraLayout = LayoutInflater.FromContext(Context).Inflate(Resource.Layout.CustomCameraPage, this, false); SetContentView(cameraLayout); // 现在再去获取目标视图 var previewTexture = cameraLayout.FindViewById<TextureView>(Resource.Id.camera_preview); if (previewTexture == null) { // 这里可以加日志排查,或者抛明确的异常提示 throw new InvalidOperationException("找不到camera_preview控件,请检查布局文件中的id是否正确"); } // 接下来初始化相机逻辑... } }
3. 布局id没正确生成到Resource.designer.cs
如果你的布局xml里已经写了android:id="@+id/xxx",但代码里Resource.Id却找不到这个id,大概率是没重新编译项目。Resource.designer.cs是自动生成的文件,修改布局后记得重新编译Android项目,或者直接清理解决方案再重新生成,避免缓存导致的资源文件不更新。
4. 调用FindViewById的对象不对
如果你是Inflated了一个布局,然后直接用this.FindViewById,可能会找不到控件——因为此时Renderer的ContentView还没设置成这个布局。正确的做法是要么先SetContentView(cameraLayout),再用this.FindViewById;要么直接用Inflated的布局对象调用cameraLayout.FindViewById,后者更稳妥,避免生命周期里的视图层级问题。
按照上面这几点逐一排查,应该就能解决你获取视图时的异常啦!
内容的提问来源于stack exchange,提问作者Wai Yan Hein

