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文件啦。代码如下所示:

 

[html] view plain copy
 
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="fill_parent"  
  4.     android:layout_height="fill_parent"  
  5.     android:orientation="vertical" >  
  6.   
  7.     <FrameLayout  
  8.         android:id="@+id/realtabcontent"  
  9.         android:layout_width="fill_parent"  
  10.         android:layout_height="0dip"  
  11.         android:layout_weight="1" />  
  12.   
  13.     <android.support.v4.app.FragmentTabHost  
  14.         android:id="@android:id/tabhost"  
  15.         android:layout_width="fill_parent"  
  16.         android:layout_height="wrap_content" >  
  17.   
  18.         <FrameLayout  
  19.             android:id="@android:id/tabcontent"  
  20.             android:layout_width="0dp"  
  21.             android:layout_height="0dp"  
  22.             android:layout_weight="0" />  
  23.     </android.support.v4.app.FragmentTabHost>  
  24.   
  25. </LinearLayout></span>  


这个文件中需要注意的是,FragmentTabHost跟它里面的FrameLayout中的id都是引入的id,而真正的id写在FragmentTabHost外面的FrameLayout中,至于为什么要这么写,我也不清楚,如果有哪位看官知道的话,可以私信发给我,谢谢。在写完了整体布局之后,我们就来写一下每个item的布局,tab_item代码如下:

 

 

[html] view plain copy
 
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="match_parent"  
  5.     android:gravity="center"  
  6.     android:orientation="vertical" >  
  7.   
  8.     <ImageView  
  9.         android:id="@+id/imageview"  
  10.         android:layout_width="wrap_content"  
  11.         android:layout_height="wrap_content" >  
  12.     </ImageView>  
  13.   
  14.     <TextView  
  15.         android:id="@+id/textview"  
  16.         android:layout_width="wrap_content"  
  17.         android:layout_height="wrap_content"  
  18.         android:layout_marginTop="2dp"  
  19.         android:textColor="@drawable/selector_tab_text" >  
  20.     </TextView>  
  21.   
  22. </LinearLayout></span>  

 

 

我们定义了五个子item,每个item对应一张图片跟一个标题,相信上面的布局大家都能看懂。每个item对应一个fragment,那么接下来我们把fragment的代码写出来,这里因为f五个ragment的代码差不多,我只给出HomeFragment的代码。fragment_home.xml布局文件如下:

 

[html] view plain copy
 
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="match_parent"  
  5.     android:orientation="vertical" >  
  6.   
  7.     <TextView  
  8.         android:layout_width="wrap_content"  
  9.         android:layout_height="wrap_content"  
  10.         android:text="首页Fragment"  
  11.         android:textSize="20sp" />  
  12.   
  13. </LinearLayout></span>  

 

HomeFragment.Java代码如下所示:

 

[java] view plain copy
 
  1. package com.example.fragmenttabhostdemo.fragment;  
  2.   
  3. import com.example.fragmenttabhostdemo.R;  
  4.   
  5. import android.os.Bundle;  
  6. import android.support.v4.app.Fragment;  
  7. import android.view.LayoutInflater;  
  8. import android.view.View;  
  9. import android.view.ViewGroup;  
  10.   
  11. public class HomeFragment extends Fragment {  
  12.     @Override  
  13.     public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {  
  14.         return inflater.inflate(R.layout.fragment_home, container, false);  
  15.     }  
  16. }</span>  


HomeFragment.java,这个里面不用讲吧,就是把fragment_home.xml文件中的内容填充到fragment中。接下来,我们还要继续写状态选择器selector,Eclipse在res下新建一个文件夹drawable,里面创建5个图片状态选择器跟一个文字状态选择器,这里图片状态选择器我只贴出一个,selector_icon_home.xml代码如下所示:

 

 

[html] view plain copy
 
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <selector xmlns:android="http://schemas.android.com/apk/res/android">  
  3.   
  4.     <!-- Non focused states -->  
  5.     <item android:drawable="@drawable/icon_home" android:state_focused="false" android:state_pressed="false" android:state_selected="false"/>  
  6.     <item android:drawable="@drawable/icon_home_press" android:state_focused="false" android:state_pressed="false" android:state_selected="true"/>  
  7.     <!-- Focused states -->  
  8.     <item android:drawable="@drawable/icon_home_press" android:state_focused="true" android:state_pressed="false" android:state_selected="false"/>  
  9.     <item android:drawable="@drawable/icon_home_press" android:state_focused="true" android:state_pressed="false" android:state_selected="true"/>  
  10.     <!-- Pressed -->  
  11.     <item android:drawable="@drawable/icon_home_press" android:state_pressed="true" android:state_selected="true"/>  
  12.     <item android:drawable="@drawable/icon_home_press" android:state_pressed="true"/>  
  13.   
  14. </selector></span>  

 

这里简单介绍一下,android:state_focused="false"是没有聚焦状态,相反若为true,则为获得焦点状态。

android:state_pressed="false"是没有按下状态,相反若为true,则为按下状态。

android;state_selected="false"是没有被选择状态,相反则被选择。

最后,到了最重要的MainActivity,代码如下:

 

[java] view plain copy
 
  1. package com.example.fragmenttabhostdemo;  
  2.   
  3. import java.util.ArrayList;  
  4. import java.util.List;  
  5.   
  6. import com.example.fragmenttabhostdemo.bean.Tab;  
  7. import com.example.fragmenttabhostdemo.fragment.CartFragment;  
  8. import com.example.fragmenttabhostdemo.fragment.CategoryFragment;  
  9. import com.example.fragmenttabhostdemo.fragment.HomeFragment;  
  10. import com.example.fragmenttabhostdemo.fragment.HotFragment;  
  11. import com.example.fragmenttabhostdemo.fragment.MineFragment;  
  12.   
  13. import android.os.Bundle;  
  14. import android.support.v4.app.FragmentActivity;  
  15. import android.support.v4.app.FragmentTabHost;  
  16. import android.view.LayoutInflater;  
  17. import android.view.View;  
  18. import android.view.Window;  
  19. import android.widget.ImageView;  
  20. import android.widget.TabHost;  
  21. import android.widget.TextView;  
  22.   
  23. public class MainActivity extends FragmentActivity {  
  24.   
  25.     /** 
  26.      * 定义FragmentTabHost对象 
  27.      */  
  28.     private FragmentTabHost mTabHost;  
  29.   
  30.     /** 
  31.      * 定义一个布局填充器对象 
  32.      */  
  33.     private LayoutInflater mInflater;  
  34.   
  35.     /** 
  36.      * 定义一个ArrayList来存放Tab 
  37.      */  
  38.     private List<Tab> mTabs = new ArrayList<Tab>(5);  
  39.   
  40.     @Override  
  41.     protected void onCreate(Bundle savedInstanceState) {  
  42.         super.onCreate(savedInstanceState);  
  43.         requestWindowFeature(Window.FEATURE_NO_TITLE);  
  44.         setContentView(R.layout.activity_main);  
  45.   
  46.         initTab();  
  47.     }  
  48.   
  49.     /** 
  50.      * 初始化Tab 
  51.      */  
  52.     private void initTab() {  
  53.         Tab tab_home = new Tab(HomeFragment.class, R.string.home, R.drawable.selector_icon_home);  
  54.         Tab tab_hot = new Tab(HotFragment.class, R.string.hot, R.drawable.selector_icon_hot);  
  55.         Tab tab_category = new Tab(CategoryFragment.class, R.string.catagory, R.drawable.selector_icon_category);  
  56.         Tab tab_cart = new Tab(CartFragment.class, R.string.cart, R.drawable.selector_icon_cart);  
  57.         Tab tab_mine = new Tab(MineFragment.class, R.string.mine, R.drawable.selector_icon_mine);  
  58.   
  59.         mTabs.add(tab_home);  
  60.         mTabs.add(tab_hot);  
  61.         mTabs.add(tab_category);  
  62.         mTabs.add(tab_cart);  
  63.         mTabs.add(tab_mine);  
  64.   
  65.         mInflater = LayoutInflater.from(this);  
  66.         mTabHost = (FragmentTabHost) this.findViewById(android.R.id.tabhost);  
  67.         mTabHost.setup(this, getSupportFragmentManager(), R.id.realtabcontent);  
  68.   
  69.         for (Tab tab : mTabs) {  
  70.   
  71.             TabHost.TabSpec tabSpec = mTabHost.newTabSpec(getString(tab.getTitle()));  
  72.   
  73.             tabSpec.setIndicator(buildIndicator(tab));  
  74.   
  75.             mTabHost.addTab(tabSpec, tab.getFragment(), null);  
  76.   
  77.         }  
  78.     }  
  79.   
  80.     /** 
  81.      * 给Tab设置图标跟文字 
  82.      *  
  83.      * @param tab 
  84.      * @return 
  85.      */  
  86.     private View buildIndicator(Tab tab) {  
  87.   
  88.         View view = mInflater.inflate(R.layout.tab_item, null);  
  89.         ImageView img = (ImageView) view.findViewById(R.id.imageview);  
  90.         TextView text = (TextView) view.findViewById(R.id.textview);  
  91.   
  92.         img.setBackgroundResource(tab.getIcon());  
  93.         text.setText(tab.getTitle());  
  94.   
  95.         return view;  
  96.     }  
  97.   
  98. }</span>  

 

看到MainActivity中的Tab了吗?我们创建一个package:com.example.fragmenttabhostdemo.bean,然后在该目录下新建一个java文件,Tab代码如下所示:

 

[java] view plain copy
 
  1. package com.example.fragmenttabhostdemo.bean;  
  2.   
  3. public class Tab {  
  4.   
  5.     private int title;  
  6.   
  7.     private int icon;  
  8.   
  9.     private Class fragment;  
  10.   
  11.     public Tab(Class fragment, int title, int icon) {  
  12.         super();  
  13.         this.title = title;  
  14.         this.icon = icon;  
  15.         this.fragment = fragment;  
  16.     }  
  17.   
  18.     public int getTitle() {  
  19.         return title;  
  20.     }  
  21.   
  22.     public void setTitle(int title) {  
  23.         this.title = title;  
  24.     }  
  25.   
  26.     public int getIcon() {  
  27.         return icon;  
  28.     }  
  29.   
  30.     public void setIcon(int icon) {  
  31.         this.icon = icon;  
  32.     }  
  33.   
  34.     public Class getFragment() {  
  35.         return fragment;  
  36.     }  
  37.   
  38.     public void setFragment(Class fragment) {  
  39.         this.fragment = fragment;  
  40.     }  
  41.   
  42. }  
  43. </span>  

好了,到这里代码就全部都写完了,让我们运行一下看看效果吧,如下图所示:

 

源码下载,请点击此处

posted @ 2016-11-30 20:50  天涯海角路  阅读(994)  评论(0)    收藏  举报