2015-04-24 51 views
1

我在SupportV4 tabhost內的碎片存在問題,該問題在單個選項卡更改期間加載兩個碎片。 (Tabhost used; android/support/v4/app/FragmentTabHost)如何防止在TabChange中創建自己的片段的SupportV4(片段)Tabhost?

發生這個問題是因爲我想使用MVVMCross和它的ViewModels,所以我需要在碎片內部加載ViewModels。

爲了清楚起見,我使用了以下流程; - 負載ActionActivity然後加載片段舉行標籤 - AddTabs(內片段) - 添加每TabChange切換片段與SupportFragmentManager

我的片段保存選項卡有以下幾點:

public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
    var ignored = base.OnCreateView(inflater, container, savedInstanceState); 
    var rootView = this.BindingInflate(LayoutId, null); 

    activityTabHost = (FragmentTabHost) rootView.FindViewById(Android.Resource.Id.TabHost); 
    activityTabHost.Setup(Activity, ChildFragmentManager, Resource.Id.realtabcontent); 

    var savedcurrentTabTag = string.Empty; 

    AddTabs(savedInstanceState); 

    if (savedInstanceState != null) { 
     savedcurrentTabTag = savedInstanceState.GetString(SavedTabIndexStateKey); 
     activityTabHost.SetCurrentTabByTag(savedcurrentTabTag); 
    } 

    if (lookup.Any()) { 
     OnTabChanged(string.IsNullOrWhiteSpace(savedcurrentTabTag) ? lookup.First().Key : savedcurrentTabTag); 
    } 

    activityTabHost.SetOnTabChangedListener(this); 

    return rootView; 
} 

TabLoading(一個接一個)

private static void AddTab(Fragment fragment, // Check incomming (was MvxTabsFragmentActivity) 
TabHost tabHost, 
Android.Widget.TabHost.TabSpec tabSpec, 
MvxTabFragmentInfo tabInfo) { 
    // Attach a Tab view factory to the spec 
    tabSpec.SetContent(new MvxTabFragmentFactory(fragment.Activity)); 
    var tag = tabSpec.Tag; 

    // Check to see if we already have a CachedFragment for this tab, probably 
    // from a previously saved state. If so, deactivate it, because our 
    // initial state is that a tab isn't shown. 
    tabInfo.CachedFragment = fragment.ChildFragmentManager.FindFragmentByTag(tag); 
    if (tabInfo.CachedFragment != null && !tabInfo.CachedFragment.IsDetached) { 
     var ft = fragment.ChildFragmentManager.BeginTransaction(); 
     ft.Detach(tabInfo.CachedFragment); 
     ft.Commit(); 
     fragment.ChildFragmentManager.ExecutePendingTransactions(); 
    } 

    tabHost.AddTab(tabSpec, Class.FromType(tabInfo.FragmentType), tabInfo.Bundle); 
} 

標籤更改:

public virtual void OnTabChanged(string tag) { 
    var newTab = lookup[tag]; 
    if (currentTab != newTab) { 
     var ft = ChildFragmentManager.BeginTransaction(); 
     OnTabFragmentChanging(tag, ft); 
     if (currentTab != null) { 
      if (currentTab.CachedFragment != null) { 
       ft.Detach(currentTab.CachedFragment); 
      } 
     } 

     if (newTab != null) { 
      if (newTab.CachedFragment == null) { 
       // CAUTION!!! 
       // This adds a NEW fragment to the ChildFragmentManager, but the TabHost creates its own Fragment to! 
       // (that one needs to be cancled, regocnized by the lack of a ViewModel) 
       newTab.CachedFragment = Instantiate(Activity, FragmentJavaName(newTab.FragmentType), newTab.Bundle); 
       FixupDataContext(newTab); 
       ft.Add(TabContentId, newTab.CachedFragment, newTab.Tag); 
      } else { 
       FixupDataContext(newTab); 
       ft.Attach(newTab.CachedFragment); 
      } 
     } 

     currentTab = newTab; 
     currentTabTag = (newTab != null) ? newTab.Tag : string.Empty; 
     ft.Commit(); 
     ChildFragmentManager.ExecutePendingTransactions(); 
    } 

    TabHost.ViewTreeObserver.RemoveOnTouchModeChangeListener(TabHost); 
} 

正如您所看到的,我當前加載了我自己的片段,然後將ViewModel附加到片段。很好地說,ViewModels已經存在,它來自一個父ViewModel,它包含4個ViewModel,每個Tab都有一個ViewModel。

但是! TabHost在TabChange期間創建自己的片段,但沒有ViewModel,因爲它沒有自動加載到該MvxFragment中。

這是我的解決方法,取消片段中沒有得到一個ViewModel (否則我會去碎片上的eachother)。

public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
    if (ViewModel == null) { 
     return null; 
    } 

    base.OnCreateView(inflater, container, savedInstanceState); 
    return this.BindingInflate(Resource.Layout.GroupedFragmentView, null); 
} 

這是一個解決方法,我想要更多地控制創建碎片的Tabhost。

有誰知道如何進入SupportV4 tabhost來控制片段的創建?或者其他任何人有一個很好的解決方案,而不是我的解決方法?

+1

改爲使用ViewPager和ViewPagerIndicator。選項卡是舊學校... – Cheesebaron

+0

是的,ViewPager是在議程上。但是,如果有一個好的/簡單的Tabs解決方案,那就太棒了。 –

回答

1

答案將是解決方法; (但更好的解決方案是Cheesebaron的建議)

public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) 
{ 
    if (ViewModel == null) 
    { 
     return null; 
    } 

    base.OnCreateView(inflater, container, savedInstanceState); 
    return this.BindingInflate(Resource.Layout.GroupedFragmentView, null); 
}