【问题标题】:Why does FindViewById return null when switching from portrait to landscape?为什么从纵向切换到横向时 FindViewById 返回 null?
【发布时间】:2015-05-07 12:47:38
【问题描述】:

我的一项活动的 InitView 方法调用了它的属性

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

...它指的是一个 ListView,它定义为我的 Android 项目的“layout”文件夹中的 RelativeLayout“MainMenuLayout.axml”的一部分:

    <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 问题,还是我误解了什么?

【问题讨论】:

  • 您在 layout-land 文件夹中有第二个文件吗?
  • 不,文件夹 layout-land 不存在。 (layout-sw820dp 和 layout-sw720dp-port 可以,但它们都不包含类似命名的 axml 文件)。
  • 尝试以横向模式启动并切换到纵向,它会启动吗?会发生什么?
  • 你在使用片段吗?
  • 以横向模式启动会立即导致 NullReferenceException。我没有使用片段,为什么?感谢您的输入 :) (另外,将视图文件添加到 layout-land 文件夹不会导致任何改进)。

标签: android xamarin


【解决方案1】:

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”文件夹中。 “布局”中的一个具有包含指令

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

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

故事的寓意:在布局中使用包含指令时,请保持房屋井井有条。

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

【讨论】:

    【解决方案2】:

    1) 创建一个名为 drawable-land 的文件夹

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

    【讨论】:

      【解决方案3】:

      我不确定进行空值检查是否会对其他人有所帮助,毫无意义的是,默认情况下应该断言空引用。此外,不应在每次访问时加载视图,只有当它不存在时才应分配它......但这只是my2cents

      在我的例子中 findViewByID 返回了一个空值,因为我在 Activity 中调用了它,但是视图在层次上属于片段。

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

      myFragment.MainMenu
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-03-05
        • 1970-01-01
        • 1970-01-01
        • 2017-10-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多