为什么FindViewById在从纵向切换到横向时返回null?

时间:2015-05-07 12:47:39

标签: android xamarin

我的一个活动的InitView方法调用其属性

protected ListView MainMenu
    {
        get
        {
            return FindViewById<ListView>(Resource.Id.mainmenu);
        }
    }

...指的是ListView被定义为RelativeLayout&#34; MainMenuLayout.axml&#34;的一部分。位于&#34;布局&#34;我的Android项目中的文件夹:

    <ListView
    android:id="@+id/mainmenu"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:choiceMode="singleChoice"
    android:layout_below="@id/mainmenuHeader"
    android:divider="#e5e5e5"
    android:dividerHeight="1dp"
    android:background="#fff" />

在纵向模式下,此操作符合预期。但是,当切换到横向模式时,对上面的FindViewById的调用返回null。据我所知,Android应该使用布局文件夹进行纵向和横向模式。 Resource.designer.cs还包含

public const int mainmenu = 2131492931;

正如所料。值得注意的是,通过设置ConfigurationChanges = ConfigChanges.Orientation和ConfigChanges.ScreenSize手动处理方向更改会导致横向模式正常工作。这是一个Xamarin问题,还是我误解了什么?

3 个答案:

答案 0 :(得分:2)

在纵向模式下为此活动生成的布局中不存在ID为“mainmenu”的元素。因此FindViewById返回null。您需要确保纵向模式布局包含“mainmenu”元素,或者进行空检查,例如:

if (MainMenu != null) {
    MainMenu.Visibility = ViewStates.Visible;
}

...在您访问MainMenu属性之前。 (注意:在访问所有布局中不存在的元素之前,只需检查设备方向可能会导致细微的错误,不应该这样做。)

我自己的问题的答案很长,这个活动实际上并没有在其InitView中调用SetContentView(Resource.Layout.MainMenuLayout),而是使用SetContentView(Resource.Layout.MasterLayout)。所以我们需要查看MasterLayout.axml,而不是MainMenuLayout.axml。踢球者是MasterLayout.axml有两个版本,一个在“layout-port”文件夹中,另一个在“layout”中。 “layout”中的那个具有include指令

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

...但是“layout-port”中的版本没有这个包含。这就是元素“mainmenu”仅存在于横向布局而不是纵向的原因。

故事的道德:在布局中使用include指令时,保持房屋整洁。

[编辑:要详细说明此响应中的“细微错误”注意事项:如果在访问仅存在于例如的元素之前使用WindowManager.DefaultDisplay.Rotation检查设备方向。纵向模式,FindViewById可以仍然返回null。在Xamarin上,Activity可以处于设备方向为纵向但尚未创建纵向视图元素的情况。如果您在切换活动后立即快速翻转设备,则会发生这种情况。 Activity的不一致版本将很快停止并使用正确的配置恢复,但它可以持续足够长的时间以使代码执行并获得NullReferenceException。这就是你应该检查FindViewById是否返回null的原因,而不仅仅是查看设备配置。

答案 1 :(得分:0)

1)创建一个名为drawable-land

的文件夹

2)将您的xml文件复制并粘贴到此文件夹中,然后再次运行该应用并尝试更改方向。

答案 2 :(得分:0)

我不确定进行空检查是否会帮助其他人,毫无价值地说默认情况下应该声明空引用。此外,只有当视图不存在时,才应该在每次访问时加载视图...但这只是mymy2cents

在我的情况下,findViewByID返回一个空值,因为我在Activity中调用它,但视图属于层次结构。

所以你可以将MainMenu属性移动到片段,然后通过Activity中的片段访问它:

myFragment.MainMenu