屏幕旋转后,findFragmentById() 返回一个片段,即使布局内没有这样的 ID

Vis*_*das 5 android android-layout android-fragments

我有两种方向的一种布局 - 1 个横向和 1 个纵向。

/layout-land/main.xml有两个片段:

  • <fragment android:id="@+id/fragment1" .. />
  • <fragment android:id="@+id/fragment2" .. />

/layout/main.xml只有一个片段:

  • <fragment android:id="@+id/fragment1" .. />

这是MainActivity.java

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    firstFragment = (FirstFragment) getFragmentManager().findFragmentById(R.id.fragment1);
    secondFragment = (SecondFragment) getFragmentManager().findFragmentById(R.id.fragment2);
}
Run Code Online (Sandbox Code Playgroud)

接下来,我开始MainActivity.java横向模式。在这种情况下,

  • 和 均firstFragmentsecondFragment布局中的片段layout-land/main.xml

然后我将屏幕旋转到纵向layout/main.xml模式,并且应该加载布局文件。在这种情况下,

  • firstFragment指的是R.id.fragment1
  • secondFragment指的是不存在的片段。访问其中的任何元素都会引发 NullPointerException。(更准确地说,secondFragment不在这里 null

secondFragment当布局内没有定义片段时,如何初始化它?


编辑:在 Android 开发者文档中找到的原因: http://developer.android.com/training/basics/fragments/creating.html

当配置更改导致托管这些片段的活动重新启动时,其新实例可能会使用不同的布局,该布局不包含与先前布局相同的片段。在这种情况下,所有先前的片段仍将被实例化并在新实例中运行。但是,任何不再与视图层次结构中的标记关联的视图都不会创建其内容视图,并且会从 isInLayout() 返回 false。(此处的代码还展示了如何确定放置在容器中的片段是否不再在该容器的布局中运行,并避免在这种情况下创建其视图层次结构。)

小智 2

也许为时已晚,但我把它留给未来有这个问题的程序员,我有一个类似的问题并以这种方式解决了它。

逻辑:检查屏幕方向, findViewById(R.id.fragment2)仅在屏幕处于横向模式时调用。否则在另一个屏幕上启动一个新意图

非工作代码;

@Override
public void onEventoSeleccionado(Evento e) {

    boolean hayDetalle = (getFragmentManager().findFragmentById(R.id.FrgDetalleEvento) != null);

            if(hayDetalle) {
                SimpleDateFormat formatter = new SimpleDateFormat("dd/MM/yyyy hh:mm",Locale.ENGLISH);
                Log.i("EOLog", "Hay Detalle");
                ((DetalleEventoFragment)getFragmentManager().findFragmentById(R.id.FrgDetalleEvento)).mostrarDetalle(Long.toString(e.getId()),formatter.format(e.getFecha()));
            }
            else {
                Log.i("EOLog", "No hay detalle");           
                Intent i = new Intent(this,DetalleEventoActivity.class);                                        
                Bundle b = new Bundle();
                b.putLong("IDEV", e.getId());           
                b.putLong("FECHA", e.getFecha());           
                i.putExtras(b);
                startActivity(i);
            }

}
Run Code Online (Sandbox Code Playgroud)

工作代码:

@Override
public void onEventoSeleccionado(Evento e) {

      int orientation = getResources().getConfiguration().orientation;

            if(orientation == Configuration.ORIENTATION_LANDSCAPE) {
                SimpleDateFormat formatter = new SimpleDateFormat("dd/MM/yyyy hh:mm",Locale.ENGLISH);
                Log.i("EOLog", "Hay Detalle");
                ((DetalleEventoFragment)getFragmentManager().findFragmentById(R.id.FrgDetalleEvento)).mostrarDetalle(Long.toString(e.getId()),formatter.format(e.getFecha()));
            }
            else if(orientation == Configuration.ORIENTATION_PORTRAIT) {
                Log.i("EOLog", "No hay detalle");           
                Intent i = new Intent(this,DetalleEventoActivity.class);                                        
                Bundle b = new Bundle();
                b.putLong("IDEV", e.getId());           
                b.putLong("FECHA", e.getFecha());           
                i.putExtras(b);
                startActivity(i);
            }else
            {
                Log.i("EOLog", "Dispositivo erroneo");
            }

}
Run Code Online (Sandbox Code Playgroud)

我希望这有帮助