FragmentTabHost+Fragment实现底部导航栏,仿淘宝
相信大家都会认定淘宝是在手机上最火的应用之一了,几乎每个人的手机上都装上了淘宝。淘宝除了功能强大之外,界面也是做得相当美观,它的FragmentTabHost让人赏心悦目,如下图所示:
作为手机应用程序中的技术标杆,我们自然应该多多向微信学习,那么今天实战的主题,就是模仿淘宝底部导航栏的实现。
什么是FragmentTabHost?
在Android较早的API中,使用导航栏一般是采用TabActibvity+TabHost+Activity,但自从Android 3.0中引入了Fragment后,上述方式则不再被官方推荐,而是推荐使用FragmentActivity+FragmentTabHost+Fragement。这样做的原因,想必大家都明白:因为Fragment比Activity更灵活,且更省资源。因为Fragment是3.0中才引入的,Google为了保持向下兼容的风格,提供了v4包:android.support.v4.app.FragmentTabHost。
FragmentTabHost三个步骤:
1.调用FragmentTabHost的setup方法;
2.创建TabHost.TabSpec对象,每一个对象对应一个item;
3.调用FragmentTabHost的addTab方法,把TabHost.TabSpec对象添加进来。
详细代码编写
首先先建一个Android项目,起名为FragmentTabHostDemo,既然要实现FragmentTabHost,那么第一步当然是编辑layout目录下的layout_main.xml文件啦。代码如下所示:
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:orientation="vertical" >
- <FrameLayout
- android:id="@+id/realtabcontent"
- android:layout_width="fill_parent"
- android:layout_height="0dip"
- android:layout_weight="1" />
- <android.support.v4.app.FragmentTabHost
- android:id="@android:id/tabhost"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content" >
- <FrameLayout
- android:id="@android:id/tabcontent"
- android:layout_width="0dp"
- android:layout_height="0dp"
- android:layout_weight="0" />
- </android.support.v4.app.FragmentTabHost>
- </LinearLayout></span>
这个文件中需要注意的是,FragmentTabHost跟它里面的FrameLayout中的id都是引入的id,而真正的id写在FragmentTabHost外面的FrameLayout中,至于为什么要这么写,我也不清楚,如果有哪位看官知道的话,可以私信发给我,谢谢。在写完了整体布局之后,我们就来写一下每个item的布局,tab_item代码如下:
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:gravity="center"
- android:orientation="vertical" >
- <ImageView
- android:id="@+id/imageview"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content" >
- </ImageView>
- <TextView
- android:id="@+id/textview"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="2dp"
- android:textColor="@drawable/selector_tab_text" >
- </TextView>
- </LinearLayout></span>
我们定义了五个子item,每个item对应一张图片跟一个标题,相信上面的布局大家都能看懂。每个item对应一个fragment,那么接下来我们把fragment的代码写出来,这里因为f五个ragment的代码差不多,我只给出HomeFragment的代码。fragment_home.xml布局文件如下:
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical" >
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="首页Fragment"
- android:textSize="20sp" />
- </LinearLayout></span>
HomeFragment.Java代码如下所示:
- package com.example.fragmenttabhostdemo.fragment;
- import com.example.fragmenttabhostdemo.R;
- import android.os.Bundle;
- import android.support.v4.app.Fragment;
- import android.view.LayoutInflater;
- import android.view.View;
- import android.view.ViewGroup;
- public class HomeFragment extends Fragment {
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
- return inflater.inflate(R.layout.fragment_home, container, false);
- }
- }</span>
HomeFragment.java,这个里面不用讲吧,就是把fragment_home.xml文件中的内容填充到fragment中。接下来,我们还要继续写状态选择器selector,Eclipse在res下新建一个文件夹drawable,里面创建5个图片状态选择器跟一个文字状态选择器,这里图片状态选择器我只贴出一个,selector_icon_home.xml代码如下所示:
- <?xml version="1.0" encoding="utf-8"?>
- <selector xmlns:android="http://schemas.android.com/apk/res/android">
- <!-- Non focused states -->
- <item android:drawable="@drawable/icon_home" android:state_focused="false" android:state_pressed="false" android:state_selected="false"/>
- <item android:drawable="@drawable/icon_home_press" android:state_focused="false" android:state_pressed="false" android:state_selected="true"/>
- <!-- Focused states -->
- <item android:drawable="@drawable/icon_home_press" android:state_focused="true" android:state_pressed="false" android:state_selected="false"/>
- <item android:drawable="@drawable/icon_home_press" android:state_focused="true" android:state_pressed="false" android:state_selected="true"/>
- <!-- Pressed -->
- <item android:drawable="@drawable/icon_home_press" android:state_pressed="true" android:state_selected="true"/>
- <item android:drawable="@drawable/icon_home_press" android:state_pressed="true"/>
- </selector></span>
这里简单介绍一下,android:state_focused="false"是没有聚焦状态,相反若为true,则为获得焦点状态。
android:state_pressed="false"是没有按下状态,相反若为true,则为按下状态。
android;state_selected="false"是没有被选择状态,相反则被选择。
最后,到了最重要的MainActivity,代码如下:
- package com.example.fragmenttabhostdemo;
- import java.util.ArrayList;
- import java.util.List;
- import com.example.fragmenttabhostdemo.bean.Tab;
- import com.example.fragmenttabhostdemo.fragment.CartFragment;
- import com.example.fragmenttabhostdemo.fragment.CategoryFragment;
- import com.example.fragmenttabhostdemo.fragment.HomeFragment;
- import com.example.fragmenttabhostdemo.fragment.HotFragment;
- import com.example.fragmenttabhostdemo.fragment.MineFragment;
- import android.os.Bundle;
- import android.support.v4.app.FragmentActivity;
- import android.support.v4.app.FragmentTabHost;
- import android.view.LayoutInflater;
- import android.view.View;
- import android.view.Window;
- import android.widget.ImageView;
- import android.widget.TabHost;
- import android.widget.TextView;
- public class MainActivity extends FragmentActivity {
- /**
- * 定义FragmentTabHost对象
- */
- private FragmentTabHost mTabHost;
- /**
- * 定义一个布局填充器对象
- */
- private LayoutInflater mInflater;
- /**
- * 定义一个ArrayList来存放Tab
- */
- private List<Tab> mTabs = new ArrayList<Tab>(5);
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- requestWindowFeature(Window.FEATURE_NO_TITLE);
- setContentView(R.layout.activity_main);
- initTab();
- }
- /**
- * 初始化Tab
- */
- private void initTab() {
- Tab tab_home = new Tab(HomeFragment.class, R.string.home, R.drawable.selector_icon_home);
- Tab tab_hot = new Tab(HotFragment.class, R.string.hot, R.drawable.selector_icon_hot);
- Tab tab_category = new Tab(CategoryFragment.class, R.string.catagory, R.drawable.selector_icon_category);
- Tab tab_cart = new Tab(CartFragment.class, R.string.cart, R.drawable.selector_icon_cart);
- Tab tab_mine = new Tab(MineFragment.class, R.string.mine, R.drawable.selector_icon_mine);
- mTabs.add(tab_home);
- mTabs.add(tab_hot);
- mTabs.add(tab_category);
- mTabs.add(tab_cart);
- mTabs.add(tab_mine);
- mInflater = LayoutInflater.from(this);
- mTabHost = (FragmentTabHost) this.findViewById(android.R.id.tabhost);
- mTabHost.setup(this, getSupportFragmentManager(), R.id.realtabcontent);
- for (Tab tab : mTabs) {
- TabHost.TabSpec tabSpec = mTabHost.newTabSpec(getString(tab.getTitle()));
- tabSpec.setIndicator(buildIndicator(tab));
- mTabHost.addTab(tabSpec, tab.getFragment(), null);
- }
- }
- /**
- * 给Tab设置图标跟文字
- *
- * @param tab
- * @return
- */
- private View buildIndicator(Tab tab) {
- View view = mInflater.inflate(R.layout.tab_item, null);
- ImageView img = (ImageView) view.findViewById(R.id.imageview);
- TextView text = (TextView) view.findViewById(R.id.textview);
- img.setBackgroundResource(tab.getIcon());
- text.setText(tab.getTitle());
- return view;
- }
- }</span>
看到MainActivity中的Tab了吗?我们创建一个package:com.example.fragmenttabhostdemo.bean,然后在该目录下新建一个java文件,Tab代码如下所示:
- package com.example.fragmenttabhostdemo.bean;
- public class Tab {
- private int title;
- private int icon;
- private Class fragment;
- public Tab(Class fragment, int title, int icon) {
- super();
- this.title = title;
- this.icon = icon;
- this.fragment = fragment;
- }
- public int getTitle() {
- return title;
- }
- public void setTitle(int title) {
- this.title = title;
- }
- public int getIcon() {
- return icon;
- }
- public void setIcon(int icon) {
- this.icon = icon;
- }
- public Class getFragment() {
- return fragment;
- }
- public void setFragment(Class fragment) {
- this.fragment = fragment;
- }
- }
- </span>
好了,到这里代码就全部都写完了,让我们运行一下看看效果吧,如下图所示:

浙公网安备 33010602011771号