2013-10-23 34 views
4

我有兩個方向的佈局 - 1個橫向和1個縱向。屏幕旋轉後,findFragmentById()返回一個片段,即使在佈局中沒有這樣的ID

/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); 
} 

接下來,我開始MainActivity.java景觀模式。在這種情況下,

  • 兩個firstFragmentsecondFragment指片段在佈局layout-land/main.xml

然後我在屏幕旋轉到肖像模式,佈局文件layout/main.xml應該被加載。在這種情況下,

  • firstFragmentR.id.fragment1
  • secondFragment referes到一個不存在的片段。訪問裏面的任何元素都會拋出NullPointerException異常。 (更準確地說,是secondFragmentnull這裏)

如何時,有沒有佈局中定義片段這個secondFragment初始化?


編輯:在http://developer.android.com/training/basics/fragments/creating.html在Android開發者文檔中找到原因:

當配置變化導致託管這些 片段重新啓動活動,它的新實例可以使用不同的佈局 不包含與之前佈局相同的片段。在這個 的情況下,所有先前的片段仍將被實例化並且在新實例中運行 。但是,與視圖層次結構中的標記關聯的任何不再 的 都不會創建它們的內容視圖,並將從isInLayout()返回false。 (這裏的代碼也顯示瞭如何確定一個片段在容器中放入 在與容器 佈局不再運行,並避免在這種情況下創建其視圖層次)。

+0

你確定第二個片段被初始化,檢查secondFragment == null – viv

+0

@viv是的,它肯定是空的檢查,它不是空的! –

+0

確保正確加載xml,嘗試更改背景,檢查是否在清單中的config參數中沒有添加任何東西 – viv

回答

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); 
      } 

} 

工作代碼:

@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"); 
      } 

} 

我希望這是有幫助的

+0

看起來不錯!只有在屏幕處於LANDSCAPE模式時才檢查方向並調用第二個片段。這肯定會解決這個問題。 (但是仍然不知道爲什麼這個片段指向一個不存在的片段!) –

0

請交叉檢查您的活動類的setContentView()。

我認爲它應該是setContentView(R.layout.main);

+0

哎呀,對不起,我改變了它的問題。這實際上意味着在問題中是'R.layout.main'! –

+1

我認爲你必須在查找片段'secondFragment'之前檢查屏幕方向。僅在橫向模式下加載第二個片段。有運行時檢查屏幕方向的功能。在方向更改期間,活動將被重新創建並嘗試查找這兩個片段。我不知道這是一個正確的方式..希望它會幫助你... –

+0

KD - 答案也提出瞭解決方案。我認爲這樣做會很好。 –

3

您可以檢查象下面這樣: 我假設你有你的findFragmentById

獲得片段片段1類
Fragment1 frg1 =getFragmentManager().findFragmentById(R.id.FrgDetalleEvento); 
boolean hayDetalle = (frg1!= null && frg1.isInLayout()); 

它解決了與我同樣的問題,希望對e有幫助非常你

+0

謝謝你添加一個答案。就像你說的,方法'frg1.isInLayout()'和檢查方向是迄今爲止最好的解決方案。 –

相關問題