7

3つのタブ(ActionBarタブ)を持つアプリケーションがあり、それぞれが一度に1つのフラグメントで構成されています。フラグメント間のトランザクションは1つのActionBarタブ内

TabListener

TabsActivity

Tab1を - > ListFragment1 - > ListFragment2 - > Fragment3

TAB2 - > Tab2Fragment

TAB3 - > Tab3Fragment

私が作成したときに問題がありますListFragment1からListFragment2へのFragmentTransaction(OnListItemClicked内)、他のt内のフラグメントabsもListFragment2に変更されます。

最後に、フラグメントをタブ内でのみ変更し、他のタブの状態を保持したいと考えています。

私はすでに状態(OnSavedInstance())を保存しています。 私はここで何が欠けているか知っていますか?

コードの一部:

public class TabsActivity extends Activity { 

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

     // setup Action Bar for tabs 
     ActionBar actionBar = getActionBar(); 
     actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); 

     // instantiate fragment for the tab 
     Fragment networksFragment = new NetworksFragment(); 
     // add a new tab and set its title text and tab listener 
     actionBar.addTab(actionBar.newTab().setText("Tab1") 
       .setTabListener(new TabsListener(ListFragment1))); 

     // instantiate fragment for the tab 
     Fragment historyFragment = new HistoryFragment(); 
     // add a new tab and set its title text and tab listener 
     actionBar.addTab(actionBar.newTab().setText("Tab2") 
       .setTabListener(new TabsListener(Tab2Fragment))); 

     // instantiate fragment for the tab 
     Fragment settingsFragment = new SettingsFragment(); 
     // add a new tab and set its title text and tab listener 
     actionBar.addTab(actionBar.newTab().setText("Tab3") 
       .setTabListener(new TabsListener(Tab3Fragment))); 
    } 
} 

public class TabsListener implements ActionBar.TabListener { 

    private Fragment frag; 


    // Called to create an instance of the listener when adding a new tab 
    public TabsListener(Fragment networksFragment) { 
     frag = networksFragment; 
    } 

    @Override 
    public void onTabReselected(Tab arg0, FragmentTransaction arg1) { 
     // TODO Auto-generated method stub 

    } 

    @Override 
    public void onTabSelected(Tab tab, FragmentTransaction ft) {  
     ft.add(R.id.fragment_container, frag, null); 
    } 

    @Override 
    public void onTabUnselected(Tab tab, FragmentTransaction ft) { 
     ft.remove(frag);   
    } 
} 

public class ListFragment1 extends ListFragment { 

    @Override 
    public void onListItemClick(ListView l, View v, int position, long id) { 

     getListView().setItemChecked(position, true); 

     ListFragment2 fragment2 = ListFragment2.newInstance(position); 

     FragmentTransaction ft = getFragmentManager().beginTransaction(); 
     ft.replace(R.id.fragment_container, fragment2); 
     ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE); 
     ft.addToBackStack(null); 
     ft.commit(); 
    } 
} 

答えて

6

あなたは何が不足していない(または私はそれをあまりにも欠けています)。

これを「適切に」実行するための方法を長く探しましたが、何も見つかりませんでした。私がやったことは、自分のバックスタックロジックを書くことです。 残念なことに私の雇用主は自分のコードを所有しているので、そのまま残しておくことはできませんが、私のアプローチは次のとおりです:

それぞれのタブごとに1つのエントリを作成します。それをTabTypeとしましょう。 HashMap<TabType, Stack<String>>のインスタンス変数tabStacksを作成します。これで各タブごとに1つのスタックをインスタンス化できます。各スタックはFragment.getTag()で指定されたタグのリストです。この方法では、Fragmentsへの参照の保存について心配する必要はなく、デバイスを回転させると消えてしまうかどうかはわかりません。 Fragmentへの参照が必要なときはいつでも、スタックから正しいタグをつかみ、FragmentManager.findFragmentByTag()を使用してください。

今度は、Fragmentをタブにプッシュするときは、新しいタグ(UUID.randomUUID().toString()を使用)を生成し、FragmentTransaction.add()への呼び出しで使用します。次に、現在表示されているタブのスタックの上にタグを押します。

は注意してください:あなたはFragmentManagerはそれがなくなって、それがクリーンアップされますので、検討していきます、ないremove()古いいずれかを実行し、古いものの上に新しいフラグメントをプッシュしたいとき。 detach()にしてください。その後、attach()にしてください。 Fragmentを恒久的にポップアップするときはremove()を使用し、初めて表示するときはadd()を使用してください。

次に、比較的簡単なロジックをTabListenerに追加する必要があります。タブが選択されていない場合、そのスタックにはpeek()、関連するフラグメントはdetatch()となります。タブが選択された場合、の先頭にあるpeek()は、のスタックであり、そのフラグメントはattach()です。

最後に、オリエンテーションの変更のようなアクティビティのライフサイクルの癖に対処する必要があります。 MapStacksと現在選択されているタブを維持し、onCreate()で再度解凍します。 (あなたは無料でこの梱包や開梱をしませんが、それはかなり簡単です。)幸いにも、TabType列挙型はSerializableですので、Bundleに入れるのは簡単です。

+1

ありがとうございます!あなたの答えは私がこの問題を解決するのを助けたStackOverflowの唯一の答えです。 –

+0

私は雇用主の義務ではないので、必要なコードをすべて含んだGistを作成しました:https://gist.github.com/4619215 –

関連する問題