2016-11-20 108 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中的数据。不过,我注意到OnCreateViewOnActivityCreated方法每次被调用两次。第一次包含我的填充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()中的旧调用。你应该做的是不要总是创建这些片段,你可以通过标签或ID搜索现有的片段,而是使用Tabs中的标签。

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

请注意,如果您不想使用标签,只需使用ID和'FindFragmentByID'方法即可。无论哪种方式应该工作正常。 –