2015-04-24 2 views
1

У меня возникла проблема с фрагментами в табуляции SupportV4, которая загружает два фрагмента во время изменения одной вкладки. (Tabhost used; android/support/v4/app/FragmentTabHost)Как предотвратить SupportV4 (Фрагмент) Tabhost, создающий собственный фрагмент в TabChange?

Проблема возникает из-за того, что я хочу использовать MVVMCross и его ViewModels, поэтому мне нужно загрузить ViewModels внутри фрагментов (находящихся внутри вкладки).

Чтобы устранить проблему, я использовал следующий поток; - Load 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); 
} 

Tab Изменение:

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 ViewModels, по одному для каждой вкладки.

НО! 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 для управления созданием фрагмента? или у кого-нибудь еще есть хорошее решение вместо моего обходного пути?

+1

Вместо этого используйте ViewPager с ViewPagerIndicator. Вкладки - старая школа ... – Cheesebaron

+0

Да, ViewPager был на повестке дня. Но если есть хорошее/простое решение для вкладок, это было бы здорово. –

ответ

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); 
} 
Смежные вопросы