android之FragmentTabHost使用
在使用淘寶和京東這類購物類App的時候,他們這些應用都有一個底面的導航欄,看起來還是比較好看的。順便想實現一個購物類的app。這個正好可以用上。
類似的方法
之前在看別人的項目中,看到有有過類似的實現。但是在印象中是使用TabHost+RadioGroup實現的,由於不是記得很清楚了,於是去網上google了一把。發現了有如下幾種設計思路:
第一種:使用TabHost+TabSpec實現
第二種:使用TabHost+RadioGroup實現
第三種:就是FragmentTabHost實現
其他兩種都可以算是比較過時的用法,
簡單的使用
使用FragmentTabHost還是比較簡單的,但是也有幾點需要注意。
首先是佈局:
<android.support.v4.app.FragmentTabHost
android:id="@android:id/tabhost"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:id="@android:id/tabcontent"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TabWidget
android:id="@android:id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:paddingBottom="0dp"></TabWidget>
</FrameLayout>
</android.support.v4.app.FragmentTabHost>
在FragmentTabHost
中可以放一個FrameLayout
和一個TabWidget
,其中TabWidget
是用來放選項卡的內容的,FrameLayout
是用來承載每個選項卡所對應的界面的。在使用佈局的時候需要注意的是這三個控件的id
。
FragmentTabHost
的id
需要是@android:id/tabhost
,FrameLayout
的id
需要是@android:id/tabcontent
,TabWidget
的id
需要是@android:id/tabs
。當佈局處理完成之後。需要在Activity
中進行初始化。
mTabHost = (FragmentTabHost) view.findViewById(android.R.id.tabhost);
mTabHost.setup(getActivity(), getFragmentManager(), android.R.id.tabcontent);
需要調用setup()
方法對FragmentTabHost
進行一些初始化操作,然後就可以添加一些選項卡了。
Tag homeTag = new Tag(R.string.tag_home, R.drawable.selector_home, HomeFragment.class);
Tag categoryTag = new Tag(R.string.tag_category, R.drawable.selector_category, CategoryFragment.class);
Tag hotTag = new Tag(R.string.tag_hot, R.drawable.selector_hot, HotFragment.class);
Tag mineTag = new Tag(R.string.tag_mine, R.drawable.selector_mine, MineFragment.class);
Tag cartTag = new Tag(R.string.tag_cart, R.drawable.selector_cart, CartFragment.class);
mTabHost.addTab(mTabHost.newTabSpec("home").setIndicator(setTagIndicator(homeTag)), homeTag.getFragment(), null);
mTabHost.addTab(mTabHost.newTabSpec("category").setIndicator(setTagIndicator(categoryTag)), categoryTag.getFragment(), null);
mTabHost.addTab(mTabHost.newTabSpec("hot").setIndicator(setTagIndicator(hotTag)), hotTag.getFragment(), null);
mTabHost.addTab(mTabHost.newTabSpec("cart").setIndicator(setTagIndicator(cartTag)), cartTag.getFragment(), null);
mTabHost.addTab(mTabHost.newTabSpec("mine").setIndicator(setTagIndicator(mineTag)), mineTag.getFragment(), null);
其中setTagIndicator()
是爲選項卡設置佈局
:
private View setTagIndicator(Tag tag) {
View view = mInflater.inflate(R.layout.tab_view, null);
ImageView image = (ImageView) view.findViewById(R.id.tab_iamge);
TextView dest = (TextView) view.findViewById(R.id.tab_dest);
image.setImageResource(tag.getPic());
dest.setText(tag.getDest());
return view;
}
到這這裏我就完成了簡單的選項卡界面的搭建。效果如下:
一些問題
爲Fragment設置Presenter
在使用FragmentTabHost
的時候,因爲想跟上時代的潮流,使用一把MVP。但是在FragmentTabHost
遇到了一些挫折。在Google的官方的MVP例子中,使用Fragment
作爲View。在Activity
中向Fragment
設置Presenter
,但是在FragmentTabHost
中我不能按照demo
中的樣子設置Presenter
,原因在於,在Activity
中,我能夠拿到Fragment
的實例,但是在使用FragmentTabHost
中不能很好的拿到我想要的Fragment
的實例。雖然可以在FragmentTabHost
的OnTabChangedListener
中拿到Fragment
的實例,但是,這個所拿到的實例是不是當其點的選項卡所應該展示的實例,因此該路徑放棄了。然後想到,我爲這些Fragment
設置了Tag
那我應該能夠通過這些Tag
取到對應Fragment
,但實驗下來,還是不行。因此我只能在Fragmnet
的onCreate()
方法中,爲該Fragment
設置Presenter
。
Fragment使用懶加載
之前逛掘金的時候,發現有人對Fragment
使用了所謂的懶加載技術,之前在寫項目的時候,因爲在ViewPager
中使用了Fragment
,如果不使用懶加載技術時,ViewPager
中的Fragment
將會被全部加載,這種感覺體驗不好。在FragmentTabHost
中也腦子沒動,直接對FragmentTabHost
中的Fragment
使用懶加載技術,因爲感覺FragmentTabHost
和ViewPager
類似,都可以包裹多個Fragment
。當寫完進行測試的時候,什麼鬼?,在setUserVisibleHint()
方法中所打的log
完全沒有信息。當時就懷疑是否是自己參考錯了,重新去看了一遍使用說明,確認自己寫的方法沒有錯誤。反覆的測試,還是一樣的效果。只能帶着困惑去google。原來使用FragmentTagHost
並沒有像ViewPager
一樣使用了預加載,沒有預加載,何來的懶加載呢?