2016-11-20 5 views
0

Я пытаюсь создать мероприятие с двумя вкладками, один из которых содержит FragmentA и один держатель FragmentB. Вот как я могу добавить фрагменты к деятельности:OnCreateView Вызывается дважды

[Activity(Label = "My App")] 
public class MyActivity : Activity 
{ 
    protected override void OnCreate(Bundle savedInstanceState) 
    { 
     base.OnCreate(savedInstanceState); 
     SetContentView(Resource.Layout.ConnectionMenu); 
     ActionBar.NavigationMode = ActionBarNavigationMode.Tabs; 
     AddTab("A", new FragmentA()); 
     AddTab("B", new FragmentB()); 
    } 

    private void AddTab(string tabText, Fragment fragment) 
    { 
     var tab = ActionBar.NewTab(); 
     tab.SetText(tabText); 
     tab.TabSelected += (sender, e) => 
     { 
      e.FragmentTransaction.Replace(
       Resource.Id.fragmentContainer, 
       fragment); 
     }; 
     ActionBar.AddTab(tab); 
    } 
} 

Когда я повернуть ориентацию, я хочу, чтобы поля, заполненные в фрагментах то же самое. Я сохраняю свои данные в OnSaveInstanceState и восстанавливаю данные в OnActivityCreated. Тем не менее, я замечаю, что методы OnCreateView и OnActivityCreated вызываются дважды за каждый поворот. Первый раз, когда я был заполнен Bundle, и второй раз, когда пучок был нулевым.

Я предполагаю, что моя ошибка в классе MyActivity, но если вам нужна дополнительная информация, дайте мне знать!

ответ

0

Я в конечном итоге решение вопроса. как @JonDouglas сказал, что вам нужно убедиться, что вкладка еще не загружена перед созданием нового фрагмента. Для этого фрагмент может быть загружен из класса FragmentManager с использованием тега. Во время события TabSelected, если фрагмент ранее не создавался, создается новый фрагмент и добавляется к событию FragmentTransaction с использованием тега. Во время события TabUnselected, если фрагмент был создан, он отсоединяется.

Я также добавил значение Bundle, чтобы удерживать последнюю активную вкладку.

Вот код, который я использовал для решения проблемы.

[Activity(Label = "My App")] 
public class MyActivity : Activity 
{ 
    protected override void OnCreate(Bundle savedInstanceState) 
    { 
     base.OnCreate(savedInstanceState); 
     SetContentView(Resource.Layout.ConnectionMenu); 
     ActionBar.NavigationMode = ActionBarNavigationMode.Tabs; 
     AddTab("A", "a_fragment",() => new FragmentA()); 
     AddTab("B", "b_fragment",() => new FragmentB()); 
     if (savedInstanceState != null) 
     { 
      var selectedTab = savedInstanceState.GetInt(
       "ActionBar.SelectedNavigationIndex", 0); 
      ActionBar.SetSelectedNavigationItem(selectedTab); 
     } 
    } 

    protected override void OnSaveInstanceState(Bundle savedInstanceState) 
    { 
     base.OnSaveInstanceState(savedInstanceState); 
     savedInstanceState.PutInt(
      "ActionBar.SelectedNavigationIndex", 
      ActionBar.SelectedNavigationIndex); 
    } 

    private void AddTab<TFragment>(
     string tabText, 
     string tag, 
     Func<TFragment> ctor) where TFragment : Fragment 
    { 
     var tab = ActionBar.NewTab(); 
     tab.SetText(tabText); 
     tab.SetTag(tag); 
     var fragment = FragmentManager.FindFragmentByTag<TFragment>(tag); 
     tab.TabSelected += (sender, e) => 
     { 
      if (fragment == null) 
      { 
       fragment = ctor.Invoke(); 
       e.FragmentTransaction.Add(
        Resource.Id.fragmentContainer, 
        fragment, 
        tag); 
      } 
      else 
      { 
       e.FragmentTransaction.Attach(fragment); 
      } 
     }; 
     tab.TabUnselected += (sender, e) => 
     { 
      if (fragment != null) 
      { 
       e.FragmentTransaction.Detach(fragment); 
      } 
     }; 
     ActionBar.AddTab(tab); 
    } 
} 
1

Учитывая, что вы создаете фрагмент в своем Activity.OnCreate(), у вас всегда будет 2 вызова из-за создания новых методов и сохранения старых в base.OnCreate(). Вероятно, вы должны сделать это вместо того, чтобы всегда создавать эти фрагменты, вы можете искать через тег или идентификатор для существующего фрагмента и использовать их в вкладках.

т.е.

protected override void OnCreate(Bundle savedInstanceState) 
    { 
     base.OnCreate(savedInstanceState); 
     SetContentView(Resource.Layout.ConnectionMenu); 
     ActionBar.NavigationMode = ActionBarNavigationMode.Tabs; 

     if(savedInstanceState == null) 
     { 
      AddTab("A", new FragmentA()); 
      AddTab("B", new FragmentB()); 
     } 
     else 
     { 
      Fragment a = (FragmentA)SupportFragmentManager.FindFragmentByTag("my_tag_a"); 
      Fragment b = (FragmentB)SupportFragmentManager.FindFragmentByTag("my_tag_b"); 
      AddTab("A", a); 
      AddTab("B", b); 
     } 
    } 
+0

где я могу добавить эти теги? где-то в axml? – flakes

+0

Да, вы можете добавить 'android: tag' в свой макет' .xml/.axml'. –

+0

Как примечание, если вы не хотите использовать теги, просто используйте идентификатор и метод «FindFragmentByID». В любом случае это должно работать нормально. –

Смежные вопросы