2012-06-18 28 views
13

Fragmentsに問題があり、方向が変更されています。オリエンテーション変更後にフラグメントが正しく機能しない

MainActivityのアプリケーションでは、タブ付きアクションバーを使用してFragmentsの切り替えを処理しています。ここには、タブ付きアクションバーのコードとタブが選択されたときのコードがあります。

private class MyTabListener <T extends android.support.v4.app.Fragment> implements ActionBar.TabListener { 
    private android.support.v4.app.Fragment mFragment; 
    private final Activity mActivity; 
    private final String mTag; 
    private final Class<T> mClass; 

    public MyTabListener(SherlockFragmentActivity activity, String tag, Class<T> clz) { 
     mActivity = activity; 
     mTag = tag; 
     mClass = clz; 
    } 

    @Override 
    public void onTabSelected(Tab tab, android.support.v4.app.FragmentTransaction ft) { 
     if (mFragment == null){ // check to see if the fragment has already been initialised. If not create a new one. 
      mFragment = android.support.v4.app.Fragment.instantiate(mActivity, mClass.getName()); 
      ft.add(android.R.id.content,mFragment,mTag); 
     } else { 
      ft.attach(mFragment); // if the fragment has been initialised attach it to the current activity 
     } 
    } 

    @Override 
    public void onTabUnselected(Tab tab, android.support.v4.app.FragmentTransaction ft) { 
     if (mFragment != null){ 
      ft.detach(mFragment); // when a fragment is no longer needed, detach it from the activity but dont destroy it 
     } 
    } 

    @Override 
    public void onTabReselected(Tab tab, android.support.v4.app.FragmentTransaction ft) { 

    } 

私が見る方法は、アプリケーションがポートレートモードで最初に読み込まれたときにすべて正常に動作することです。回転すると、何らかの理由でFragment1という別のインスタンスが追加され、別のタブが選択されたときに切り離されません。これは、私が肖像画に戻って回転する場合にも当てはまります。

私はFragmentssetRetainInstance(true);を使用しようとしましたが、これは機能しません。

回転する前に私がFragmentsで何かを上書きするか、何かする必要がある方法はありますか?

ありがとうございます。

EDITこれで、アクティビティの再作成時にonTabSelectedが再度呼び出されることがわかりました。これがフラグメントが複数回接続されている私の問題の原因かもしれませんか?

ここに私の活動onCreateメソッドがあります。

super.onCreate(savedInstanceState); 

     if (savedInstanceState == null) { 
      //setContentView(R.layout.main); 

     } 
    // Create the Action Bar with tabs 
     ActionBar actionBar = getSupportActionBar(); 
     actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); 
     actionBar.setDisplayShowTitleEnabled(false); 
     //create the tab for track and add it to the action bar. 
     Tab tab = actionBar.newTab() 
          .setText("Track") 
          .setTabListener(new MyTabListener<TrackingFragment>(this,"track",TrackingFragment.class)); 
     actionBar.addTab(tab); 

     //create the tab for ski tracks and add it to the action bar. 
     tab = actionBar.newTab() 
         .setText("Something Tracks") 
         .setTabListener(new MyTabListener<TrackListFragment>(this,"somethingtracks",TrackListFragment.class)); 
     actionBar.addTab(tab); 

     //create the tab for photos and add it to the action bar. 
     tab = actionBar.newTab() 
         .setText("Photos") 
         .setTabListener(new MyTabListener<PhotoFragment>(this,"photos",PhotoFragment.class)); 
     actionBar.addTab(tab); 

答えて

16

ショート修正:にそのコードセクションを変更

onTabSelected方法では、あなたが(mFragment = getSupportFragmentManager().findFragmentByTag(mTag)を使用して)の断片を取得しようとする必要がif (mFragment == null)を使用する前に。あなたは外からこれを設定することもできますが、私はあなたがこれをやっているのを見ません。

if(savedInstanceState == null)onCreateにチェックすると、これを解決できる可能性がありますが、これはさらに優れたアプローチです。 :)

+0

私は、アクションのバーコードをonCreateメソッドに配置すると、方向変更後にアクティビティが再作成されたときに作成または表示されません。私は今supportManagerの部分を試してみる – StuStirling

+0

+1 ...私が編集している間に正しい答えでそこに忍び寄る。 :) – Barak

+0

は、setTabListenerを呼び出すときに渡されないフラグメントですか? – StuStirling

8

あなたはif(savedInstanceState == null)に包まれたあなたのonCreate方法で何かを持っていないように聞こえるので、あなたはsavedInstanceStateバンドルから復元されたものに加えて、別の断片を作成しています。

EDIT

あなたのコードをより詳しく見ると、私は私が間違っているのonCreate程度だったと思う、あなたのonTabSelectedはそれを処理する必要があります。私はあなたのif (mFragment == null)がいつもヌルになっていると思います、なぜならあなたは断片を見つけようとしないからです。

@Override 
public void onTabSelected(Tab tab, android.support.v4.app.FragmentTransaction ft) { 

    mFragment = mActivity.getSupportFragmentManager().findFragmentByTag(mTag); // add this 

    if (mFragment == null){ // check to see if the fragment has already been initialised. If not create a new one. 
     mFragment = android.support.v4.app.Fragment.instantiate(mActivity, mClass.getName()); 
     ft.add(android.R.id.content,mFragment,mTag); 
    } else { 
     ft.attach(mFragment); // if the fragment has been initialised attach it to the current activity 
    } 
} 
+0

私の断片や主な活動は何ですか? – StuStirling

+0

私は主な活動を推測する危険があります。どのようなものを設定して、最初のビューを表示します。 – Barak

+0

上記の質問に私のonCreateメソッドを追加しました – StuStirling

2

私はsetRetainInstanceが実際に無視され、android.support.v4.app.FragmentManagerによって作成されたすべてのフラグメントがonSaveInstanceStateに格納されており、onCreateで再現されていることが分かりました。

私にとってソリューションはぶっきらぼうに過剰に保存されたフラグメントを削除することでした:(savedInstanceState == null)の場合https://stackoverflow.com/a/13996054/341091

0

は常に機能していません。場合によってはsavedInstanceState!= null、横向きのために別のフラグメントを追加する必要があります。

fm.findFragmentById(R.id.frameLayoutLeft)は、向きが何であってもnullであるかどうかをテストすることです。新しいフラグメントインスタンスを作成する場合は何も行いません。ランドスケープモードで2番目のフラグメントが必要な場合は、最初にランドスケープであるかどうかを調べる必要があります.fm.findFragmentById(R.id.frameLayoutRight)がnullであるかどうかを確認してください。 nullの場合はcreate、それ以外の場合は何もしません。なぜなら、Android OSによって既に保持されているからです。

1

私は多かれ少なかれ同じ問題を抱えていましたが、上記の解決策は私の状況ではうまくいかなかったようです。最終的に私は次の解決策を見つけました:

@Override 
public void onTabSelected(Tab tab, FragmentTransaction ft) { 
    if (mFragment == null) { 
     mFragment = Fragment.instantiate(mActivity, mClass.getName()); 
     ft.replace(android.R.id.content, mFragment, mTag); // Use replace iso add 
    } 
    else { 
     ft.attach(mFragment); 
    } 
} 
関連する問題