2016-11-20 152 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'方法即可。無論哪種方式應該工作正常。 –