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(); } } } }
效果: