0

因此,我有3個Sherlock Fragments安裝程序,並且與ViewPageIndicator一起正常工作。我現在想要做的就是將一個TabHost放在其中一個碎片中,以便它顯示2個單獨的標籤(在底部)。我相信這意味着我需要將更多碎片放入由TabHost控制的第三片碎片內。使用ViewPageIndicator的SherlockFragment內部的Tabhost

考慮到TabHost需要在片段內創建,我不確定如何正確地創建它。

這裏是我已經得到了從this tutorial工作的片段,我已經嘗試更新添加TabHost失敗代碼:

TestFragment3.java

public class TestFragment3 extends SherlockFragment { 
private String mContent = "none"; 

public static TestFragment3 newInstance(String text) { 
    TestFragment3 fragment = new TestFragment3(); 

    // Supply num input as an argument. 
    Bundle args = new Bundle(); 
    args.putString(KEY_TAB_NUM, text); 
    fragment.setArguments(args); 

    return fragment; 
} 

@Override 
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
    View view = inflater.inflate(R.layout.activity_main, null); 
    String text = getString(R.string.tab_page_num) + mContent; 
    ((TextView)view.findViewById(R.id.text)).setText(text); 

    return view; 
} 

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    mContent = getArguments() != null ? getArguments().getString(KEY_TAB_NUM) : "none"; 
} 

} 

MainActivity.java

public class MainActivity extends SherlockFragmentActivity { 

private static final String[] TAB_TITLES = new String[] { "This", "Is", "A", "ViewPager" }; 

TestFragmentAdapter mAdapter; 
    ViewPager mPager; 
    PageIndicator mIndicator; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 

    setContentView(R.layout.simple_tabs); 

    mAdapter = new TestFragmentAdapter(getSupportFragmentManager()); 

    mPager = (ViewPager)findViewById(R.id.pager); 
    mPager.setAdapter(mAdapter); 

    mIndicator = (TabPageIndicator)findViewById(R.id.indicator); 
    mIndicator.setViewPager(mPager); 
} 

class TestFragmentAdapter extends FragmentPagerAdapter {  
    private int mCount = TAB_TITLES.length; 

    public TestFragmentAdapter(FragmentManager fm) { 
     super(fm); 
    } 

    @Override 
    public Fragment getItem(int position) { 
     return TestFragment.newInstance(String.valueOf(position)); 
    } 

    @Override 
    public int getCount() { 
     return mCount; 
    } 

    @Override 
    public CharSequence getPageTitle(int position) { 
     return TAB_TITLES[position]; 
    } 
} 
} 

是否需要創建一個新的SherlockFragmentActivity並將2個額外的SherlockFragments添加到該TabHost?如果是這樣,我如何設置3個片段的MainActivity來爲其第三個片段使用另一個Activity而不是片段?

我得到這個錯誤試圖把一個片段中的片段......

11-14 19:10:54.271: E/AndroidRuntime(2812): java.lang.IllegalStateException: Recursive entry to executePendingTransactions 
11-14 19:10:54.271: E/AndroidRuntime(2812):  at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1388) 
11-14 19:10:54.271: E/AndroidRuntime(2812):  at android.support.v4.app.FragmentManagerImpl.executePendingTransactions(FragmentManager.java:431) 
11-14 19:10:54.271: E/AndroidRuntime(2812):  at com.example.demolistview.EventInviteesFragment$TabManager.onTabChanged(EventInviteesFragment.java:152) 
11-14 19:10:54.271: E/AndroidRuntime(2812):  at android.widget.TabHost.invokeOnTabChangeListener(TabHost.java:391) 
11-14 19:10:54.271: E/AndroidRuntime(2812):  at android.widget.TabHost.setCurrentTab(TabHost.java:376) 
11-14 19:10:54.271: E/AndroidRuntime(2812):  at android.widget.TabHost.addTab(TabHost.java:236) 
... 
... 
... 

回答

4

在關於這個問題:

考慮到TabHost需要在片段內部創建,我不是 確定如何正確地創建它。

如果你看看最新的支持演示,他們有一個你試圖實現的例子。他們可以通過SDK管理器下載。

這是他們如何嵌套在片段中的標籤主機。該設置正在使用Child FragmentManager。

public class FragmentTabsFragmentSupport extends Fragment { 
    private FragmentTabHost mTabHost; 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, 
      Bundle savedInstanceState) { 
     mTabHost = new FragmentTabHost(getActivity()); 
     mTabHost.setup(getActivity(), getChildFragmentManager(), R.id.fragment1); 

     mTabHost.addTab(mTabHost.newTabSpec("simple").setIndicator("Simple"), 
       FragmentStackSupport.CountingFragment.class, null); 
     mTabHost.addTab(mTabHost.newTabSpec("contacts").setIndicator("Contacts"), 
       LoaderCursorSupport.CursorLoaderListFragment.class, null); 
     mTabHost.addTab(mTabHost.newTabSpec("custom").setIndicator("Custom"), 
       LoaderCustomSupport.AppListFragment.class, null); 
     mTabHost.addTab(mTabHost.newTabSpec("throttle").setIndicator("Throttle"), 
       LoaderThrottleSupport.ThrottledLoaderListFragment.class, null); 

     return mTabHost; 
    } 

    @Override 
    public void onDestroyView() { 
     super.onDestroyView(); 
     mTabHost = null; 
    } 
} 

我還創建一個小例子,其可見於:https://github.com/marsucsb/nested-fragments

+0

這是完美的!起初我一直在努力,因爲當我通過SDK管理器下載時,android-support-v4.jar沒有在我的項目中自動更新。但是,由於沒有XML佈局來定義Tabwidget,我怎樣才能在底部對齊呢? – jamis0n

+0

我還沒試過,但即時通訊猜測你可以在xml佈局文件中定義TabHost,並使用onCreateView中的LayoutInflater來擴充佈局,然後你可以通過id找到TabHost並添加所需的片段。 –

+0

沒有運氣。即使我膨脹佈局並從膨脹佈局中獲取tabhost,選項卡仍保留在頂部。 – jamis0n

1

沒有測試,但應該是這樣的

TabFragment extends SherlockFragment { 
TabHost mTabHost; 
    TabManager mTabManager; 

mTabHost = (TabHost)findViewById(android.R.id.tabhost); 
       mTabHost.setup(); 

       mTabManager = new TabManager(this.getActivity(), mTabHost, R.id.realtabcontent); 

       mTabManager.addTab(mTabHost.newTabSpec("first").setIndicator("First", getResources().getDrawable(R.drawable.ic_tab_first_tab)), FirstFragment.class , null); 

       mTabManager.addTab(mTabHost.newTabSpec("second").setIndicator("Second", getResources().getDrawable(R.drawable.ic_tab_second_tab)), SecondFragment.class , null); 
public static class TabManager implements TabHost.OnTabChangeListener { 
      private final FragmentActivity mActivity; 
      private final TabHost mTabHost; 
      private final int mContainerId; 
      private final HashMap<String, TabInfo> mTabs = new HashMap<String, TabInfo>(); 
      TabInfo mLastTab; 

      static final class TabInfo { 
       private final String tag; 
       private final Class<?> clss; 
       private final Bundle args; 
       private Fragment fragment; 

       TabInfo(String _tag, Class<?> _class, Bundle _args) { 
        tag = _tag; 
        clss = _class; 
        args = _args; 
       } 
      } 

      static class DummyTabFactory implements TabHost.TabContentFactory { 
       private final Context mContext; 

       public DummyTabFactory(Context context) { 
        mContext = context; 
       } 


       public View createTabContent(String tag) { 
        View v = new View(mContext); 
        v.setMinimumWidth(0); 
        v.setMinimumHeight(0); 
        return v; 
       } 
      } 

      public TabManager(FragmentActivity activity, TabHost tabHost, int containerId) { 
       mActivity = activity; 
       mTabHost = tabHost; 
       mContainerId = containerId; 
       mTabHost.setOnTabChangedListener(this); 
      } 

      public void addTab(TabHost.TabSpec tabSpec, Class<?> clss, Bundle args) { 
       tabSpec.setContent(new DummyTabFactory(mActivity)); 
       String tag = tabSpec.getTag(); 

       TabInfo info = new TabInfo(tag, clss, args); 

       // Check to see if we already have a fragment for this tab, probably 
       // from a previously saved state. If so, deactivate it, because our 
       // initial state is that a tab isn't shown. 
       info.fragment = mActivity.getSupportFragmentManager().findFragmentByTag(tag); 
       if (info.fragment != null && !info.fragment.isDetached()) { 
        FragmentTransaction ft = mActivity.getSupportFragmentManager().beginTransaction(); 
        ft.detach(info.fragment); 
        ft.commitAllowingStateLoss(); 
       } 

       mTabs.put(tag, info); 
       mTabHost.addTab(tabSpec); 
      } 


      public void onTabChanged(String tabId) { 
       TabInfo newTab = mTabs.get(tabId); 
       if (mLastTab != newTab) { 
        FragmentTransaction ft = mActivity.getSupportFragmentManager().beginTransaction(); 
        if (mLastTab != null) { 
         if (mLastTab.fragment != null) { 
          ft.detach(mLastTab.fragment); 
         } 
        } 
        if (newTab != null) { 
         if (newTab.fragment == null) { 
          newTab.fragment = Fragment.instantiate(mActivity, 
            newTab.clss.getName(), newTab.args); 
          ft.add(mContainerId, newTab.fragment, newTab.tag); 
         } else { 
          ft.attach(newTab.fragment); 
         } 
        } 

        mLastTab = newTab; 
        ft.commitAllowingStateLoss(); 
        mActivity.getSupportFragmentManager().executePendingTransactions(); 
       } 
      } 
     } 
} 

和你frament佈局

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:orientation="vertical" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    > 

<TabHost 
     android:id="@android:id/tabhost" 
     android:layout_width="fill_parent" 
     android:layout_height="fill_parent" 
     > 

    <LinearLayout 
     android:orientation="vertical" 
     android:layout_height="fill_parent" 
     android:layout_width="fill_parent"> 



     <FrameLayout 
      android:id="@android:id/tabcontent" 
      android:layout_width="fill_parent" 
      android:layout_weight="1" 
      android:layout_height="wrap_content"> 

     <FrameLayout 
      android:id="@+id/realtabcontent" 
      android:layout_width="fill_parent" 
      android:layout_height="fill_parent"/> 

     </FrameLayout> 

     <TabWidget 
      android:id="@android:id/tabs" 
      android:layout_width="fill_parent" 
      android:layout_marginBottom="-4dp" 
      android:background="#333333" 
      android:layout_height="wrap_content" 
     /> 


     </LinearLayout> 
</TabHost> 

</LinearLayout> 
+0

AHHHH,OK。所以看起來你只需要通過使用DummyTab的@JakeWharton的TabManager類添加標籤到片段。我會給這一槍! – jamis0n

+0

是的,這是非常標準的做法。如果你看看Sherlock的標籤欄源代碼。你會注意到相同的實現的片段標籤欄 – Greensy

+0

所以我得到一個遞歸入口executePendingTransactions錯誤...片段內的碎片不允許?上面更新的代碼 – jamis0n