TabHost基本实现(三)
一、回顾
上一篇帖子,使用了静态fragment+自定义布局的tab来实现,tabHost功能。本文在以前基础上进行改版,使用了TabManager动态的管理fragment,及 mTabHost.setOnTabChangedListener(this),监听tab选项卡的变化,并且使用系统的选项卡TabWidget作为选项卡 。
二、代码讲解
1、首先准备工作,创建四个fragment文件,SecondHandPhoneFragment.java、ReleasePhoneFragment.java
、Mobile_Raiders_Fragment.java、Hot_Fragment.java
public class SecondHandPhoneFragment extends Fragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view=inflater.inflate(R.layout.secondhand_fragment, container,false);
return view;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
}
2、布局文件main_tabhost.xml
<TabHost
android:id="@android:id/tabhost"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/app_background">
<!-- 使用了 -->
<FrameLayout
android:id="@+android:id/realtabcontent"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"/>
<!-- 未使用FrameLayout的id属性必须为 @android:id/tabcontent-->
<FrameLayout
android:id="@android:id/tabcontent"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="0"/>
<!-- TabWidget的id属性必须为 @android:id/tabs-->
<TabWidget
android:id="@android:id/tabs"
android:orientation="horizontal"
android:layout_alignParentBottom="true"
android:layout_gravity="bottom|center_horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
</TabHost>
3、布局问价每个tab布局main_tab.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:orientation="vertical">
<ImageView
android:id="@+id/tab_icon"
android:layout_width="30dp"
android:layout_height="30dp"/>
<TextView
android:id="@+id/tab_font"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#878787"
android:textSize="@dimen/three_size"/>
</LinearLayout>
4、主要java文件MainTabHostActivity.java
文件较多,附上部分核心文件,主要是通过TabManager来动态添加fragment,
public class MainTabHostActivity extends FragmentActivity implements OnClickListener {
private static final String TAG = "MainTabHostActivity";
private TabHost tabhost;
private Context mContext;
private LinearLayout tab1, tab2, tab3, tab4, tab5;
private SlidingMenu Menu;
private RelativeLayout personal_settings;
private Button menu_btn_left,menu_btn_right;
/**
* 设置tabhost中的tab标识
*/
private String home = "home", promotion = "promotion",
activity = "activity", user = "user", more = "more";
/**
* 管理tab
*/
private TabManager mTabManager;
private LinearLayout my_camera,layout_camera;
private Boolean isAnimation=true,IsCamera=false;
private ImageView camera_tab_icon;
private TextView camera_tab_font;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mContext = this;
setContentView(R.layout.main_tabhost);
my_camera=(LinearLayout) findViewById(R.id.my_camera);
Menu = new SlidingMenu(this);// 初始化组件
setTabview();// 设置tabhost的标签布局
tabhost.setup();// 添加tab时调用TabHost的setup()方法-----R.id.realtabcontent
mTabManager = new TabManager(this, tabhost,R.id.realtabcontent);
initTab();// 初始化选显卡
/** 选项卡设置初始化界面 */
setIsOnclick("ishome");// 设置选中选项卡的变化
if (savedInstanceState != null) {
tabhost.setCurrentTabByTag(savedInstanceState.getString("tab"));
}
Init();
}
/**
* 设置选项卡按钮的字体颜色
*/
private String defaultTextColor = "#999999", pressedTextColor = "#DF380F";
/**
* 初始化各个tab的样式
*/
private void setTabview() {
tabhost = (TabHost) findViewById(android.R.id.tabhost);
LinearLayout layout = (LinearLayout) tabhost.getChildAt(0);// 获得tabhost标签下的各个标签
FrameLayout frameLayout = (FrameLayout) layout.getChildAt(2);
//tabwidget:选项卡组件
TabWidget tabwidget = (TabWidget) frameLayout.getChildAt(0);
// 从外部加载布局,为TabWidget设置布局样式
LayoutInflater lf = LayoutInflater.from(this);
Log.e(TAG, "---------1111-------------");
/**
* inflate(resource,root,attachToRoot);
* resource:需要加载布局文件的id,意思是需要将这个布局文件中加载到Activity中来操作。
root:生成的层次结构的根视图.
需要附加到resource资源文件的根控件,什么意思呢,就是inflate()会返回一个View对象,
如果第三个参数attachToRoot为true,就将这个root作为根对象返回,
否则仅仅将这个root对象的LayoutParams属性附加到resource对象的根布局对象上,
也就是布局文件resource的最外层的View上,比如是一个LinearLayout或者其它的Layout对象。
attachToRoot:填充的层次结构的根视图。如果参数root提供了,那么root就是根视图;
否则填充的XML文件的根就是根视图。
是否将root附加到布局文件的根视图上
*/
tab1 = (LinearLayout) lf.inflate(R.layout.main_tab, tabwidget,false);
settabstyle(tab1, R.drawable.home, R.string.used_phones,defaultTextColor);// 为每个tab设置数据
tab2 = (LinearLayout) lf.inflate(R.layout.main_tab, tabwidget,false);
settabstyle(tab2, R.drawable.gonglue, R.string.repair_web,defaultTextColor);
tab3 = (LinearLayout) lf.inflate(R.layout.main_tab, tabwidget,false);
//R.drawable.person----R.string.fitting_recommend
settabstyle(tab3,R.drawable.person,R.string.repair_web,defaultTextColor);
tab4 = (LinearLayout) lf.inflate(R.layout.main_tab, tabwidget,false);
settabstyle(tab4, R.drawable.gonglue, R.string.popular_num,defaultTextColor);
tab5 = (LinearLayout) lf.inflate(R.layout.main_tab, tabwidget,false);
settabstyle(tab5, R.drawable.person, R.string.release_phone,defaultTextColor);
//拍摄
}
private void settabstyle(LinearLayout linearly, int imageResource,
int homeFont, String textcolor) {
ImageView imagev;
TextView textv;
imagev = (ImageView) linearly.getChildAt(0);
textv = (TextView) linearly.getChildAt(1);
imagev.setImageResource(imageResource);
textv.setText(homeFont);
textv.setTextColor(Color.parseColor(textcolor));
}
/**
* 初始化选项卡
*/
private void initTab() {
if (mTabManager!=null) {
mTabManager.addTab(tabhost.newTabSpec(home).setIndicator(tab1),SecondHandPhoneFragment.class,null);
mTabManager.addTab(tabhost.newTabSpec(promotion).setIndicator(tab2),Mobile_Raiders_Fragment.class, null);
mTabManager.addTab(tabhost.newTabSpec(activity).setIndicator(tab3),AccessRecommendFragment.class, null);
mTabManager.addTab(tabhost.newTabSpec(user).setIndicator(tab4),Hot_Fragment.class, null);
mTabManager.addTab(tabhost.newTabSpec(more).setIndicator(tab5),ReleasePhoneFragment.class, null);
}
}
/**
* 设置 选项卡默认
*/
private void defaultTabhost() {
//String mydefaultTextColor = "#DF380F";
settabstyle(tab1, R.drawable.home, R.string.used_phones,defaultTextColor);
settabstyle(tab2, R.drawable.gonglue, R.string.repair_web,defaultTextColor);
settabstyle(tab3, R.drawable.home, R.string.used_phones,defaultTextColor);
settabstyle(tab4, R.drawable.gonglue, R.string.popular_num,defaultTextColor);
settabstyle(tab5, R.drawable.person, R.string.release_phone,defaultTextColor);
/*camera_tab_icon.setImageResource(R.drawable.person);
camera_tab_font.setText(R.string.fitting_recommend);
camera_tab_font.setTextColor(this.getResources().getColor(R.color.gray_carmera));*/
}
/**
* 设置选项卡选中
* @param isTrue描述,true:选中选项卡,false:未选中
*/
private void setIsOnclick(String isTrue) {
defaultTabhost();
if (isTrue.equalsIgnoreCase("ishome")) {
settabstyle(tab1, R.drawable.home_down, R.string.used_phones,pressedTextColor);
}
if (isTrue.equalsIgnoreCase("ispromotion")) {
settabstyle(tab2, R.drawable.gonglue_down,R.string.repair_web, pressedTextColor);
}
if (isTrue.equalsIgnoreCase("isactivity")) {
settabstyle(tab3, R.drawable.person_down,R.string.fitting_recommend, pressedTextColor);// 为每个tab设置数据
}
if (isTrue.equalsIgnoreCase("isuser")) {
settabstyle(tab4, R.drawable.wode_down, R.string.popular_num,pressedTextColor);// 为每个tab设置数据
}
if (isTrue.equalsIgnoreCase("ismore")) {
settabstyle(tab5, R.drawable.more_down1, R.string.release_phone,pressedTextColor);// 为每个tab设置数据
}
if (isTrue.equalsIgnoreCase("isCamera")) {
camera_tab_icon.setImageResource(R.drawable.person_down);
camera_tab_font.setText(R.string.fitting_recommend);
camera_tab_font.setTextColor(this.getResources().getColor(R.color.right_carmera));
}
}
private void changeMenuBtn(String type){
if (type.equals("home")) {
setIsOnclick("ishome");// 设置选中选项卡的变化
} else if(type.equals("promotion")){
setIsOnclick("ispromotion");
}else if(type.equals("activity")){
setIsOnclick("isactivity");
}else if(type.equals("user")){
setIsOnclick("isuser");
}else if(type.equals("more")){
setIsOnclick("ismore");
}else if(type.equals("isCamera")){
setIsOnclick("isCamera");
}
}
主要TabManager文件
/**
* This is a helper class that implements a generic mechanism for
* associating fragments with the tabs in a tab host. It relies on a
* trick. Normally a tab host has a simple API for supplying a View or
* Intent that each tab will show. This is not sufficient for switching
* between fragments. So instead we make the content part of the tab host
* 0dp high (it is not shown) and the TabManager supplies its own dummy
* view to show as the tab content. It listens to changes in tabs, and takes
* care of switch to the correct fragment shown in a separate content area
* whenever the selected tab changes.
*/
public 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;
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;
}
}
class DummyTabFactory implements TabHost.TabContentFactory {
private final Context mContext;
public DummyTabFactory(Context context) {
mContext = context;
}
@Override
public View createTabContent(String tag) {
View v = new View(mContext);
v.setMinimumWidth(0);
v.setMinimumHeight(0);
return v;
}
}
/**
*
* @param activity
* @param tabHost:获得tabhost
* @param containerId:获得装载内容的布局
*/
public TabManager(FragmentActivity activity, TabHost tabHost, int containerId) {
mActivity = activity;
mTabHost = tabHost;
mContainerId = containerId;
/**
* mTabHost:选项卡切换的监听
*/
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.commit();
}
mTabs.put(tag, info);
if (mTabHost!=null) {
mTabHost.addTab(tabSpec);
}
}
@Override
public void onTabChanged(String tabId) {
if (tabId.equals("activity")) {
Toast.makeText(mContext, "*activity**", 1).show();
/*tab_icon.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
Toast.makeText(mContext, "*activity1111**", 1).show();
changeMenuBtn("activity");
MyCamere();
}
});*/
} else {
changeMenuBtn(tabId);
if (!isAnimation) {
hideMyCamere();
}
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) {
if (newTab.clss!=null) {
newTab.fragment = Fragment.instantiate(mActivity,
newTab.clss.getName(), newTab.args);
ft.add(mContainerId, newTab.fragment, newTab.tag);
} else {
Toast.makeText(mContext, "***", 1).show();
}
} else {
ft.attach(newTab.fragment);
}
}
mLastTab = newTab;
ft.commit();
mActivity.getSupportFragmentManager().executePendingTransactions();
}
}
}
}
效果: