7

我有一個帶有三個標籤(ActionBar標籤)的應用程序,每個標籤一次只有一個片段。僅在一個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

你不會錯過任何(或我失蹤它太)。

我搜索了很長時間,很難找到一種「正確」的方法,但我找不到任何東西。我最終做的是編寫我自己的backstack邏輯。 不幸的是,我的僱主擁有我的代碼,所以我不能分享任何逐字,但這裏是我的方法:

創建一個enum與您的每個選項卡一個條目。我們稱之爲TabType。 現在創建一個類型爲HashMap<TabType, Stack<String>>的實例變量tabStacks。現在,您可以爲每個選項卡實例化一個堆棧 - 每個堆棧都是一個標記列表,如Fragment.getTag()所指定。通過這種方式,您不必擔心存儲對Fragments的引用,以及在旋轉設備時它們是否會消失。任何時候您需要提及Fragment時,請從堆棧中取出正確的標籤並使用FragmentManager.findFragmentByTag()

現在,無論何時您想將Fragment推送到標籤上,都會生成一個新標籤(我使用UUID.randomUUID().toString()),並在您撥打FragmentTransaction.add()時使用它。然後將標籤推入堆棧頂部以顯示當前顯示的選項卡。

注意:當你想推一箇舊頂新的片段,不remove()老一,因爲FragmentManager會考慮去,它會被清理。一定要detach()吧,然後attach()吧。在永久彈出Fragment時只能使用remove(),並且只有在您第一次顯示時才使用add()

然後,你必須添加一些相對簡單的邏輯到你的TabListener。當選項卡未被選中時,簡單地在其堆棧peek()detatch()關聯的片段。當選項卡被選中時,peek()位於的頂端即堆棧和attach()那個片段。

最後,您將不得不處理Activity生命週期怪癖(如方向更改)。堅持您的MapStacks以及當前選擇的選項卡,並在您的onCreate()中再次解壓縮。 (你沒有得到這個包裝並且免費解包,但是這很容易做到。)幸運的是你的TabType enum是Serializable,所以把它放入Bundle應該是微不足道的。

+1

非常感謝!您的答案是StackOverflow中唯一一個幫助我解決此問題的答案。 –

+0

我沒有僱主的責任,所以我創建了一個包含所有必要代碼的Gist:https://gist.github.com/4619215 –