主流移动应用开发框架(2)——fragment+fragmenttabhost实现底部选项卡导航(可滑动切换)

Fragment对于我们来说可能并不陌生,在android3.0之后引进开发,对于处理平板大屏幕界面分布,fragment有着activity没有的优势,它“寄生”于activity解决了一个屏幕显示多个“分屏”的问题,管理同一个activity下多个“碎片”界面的布局显示及其数据交互。在3.0版本以下的开发环境,则需要导入V4到作为支持。

fragment的具体使用方法在这里并没有详细介绍,而主要要介绍是底部选项卡导航的实现,我们先看看效果图

实现参考了github上面的一些例子和网友的一些demo,附上自己的demo下载链接 点击打开链接

主界面代码

 

  1. package com.example.fragmenttabhost;  
  2.   
  3. import com.example.fragmentbottommenu.R;  
  4.   
  5. import android.app.Activity;  
  6. import android.content.Intent;  
  7. import android.os.Bundle;  
  8. import android.view.View;  
  9. import android.view.View.OnClickListener;  
  10. import android.widget.Button;  
  11.   
  12. /** 
  13.  *  
  14.  * @author yummy 
  15.  * email:yummyl.lau@gmail.com 
  16.  * 主菜单界面 
  17.  */  
  18. public class MainActivity extends Activity {  
  19.   
  20.     @Override  
  21.     protected void onCreate(Bundle savedInstanceState) {  
  22.         // TODO Auto-generated method stub  
  23.         super.onCreate(savedInstanceState);  
  24.         setContentView(R.layout.activity_main);       
  25.         Button nosupport = (Button) findViewById(R.id.nosupport);  
  26.         Button support = (Button) findViewById(R.id.support);  
  27.         nosupport.setOnClickListener(new OnClickListener() {  
  28.             @Override  
  29.             public void onClick(View v) {  
  30.                  Intent intent = new Intent(MainActivity.this, FragmentTab.class);  
  31.                  startActivity(intent);  
  32.             }  
  33.         });  
  34.   
  35.         support.setOnClickListener(new OnClickListener() {  
  36.             @Override  
  37.             public void onClick(View v) {  
  38.   
  39.                 Intent intent = new Intent(MainActivity.this, FragmentTabSupportSlip.class);  
  40.                 startActivity(intent);  
  41.             }  
  42.         });  
  43.     }  
  44. }  


主界面布局代码

 

  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  2.     xmlns:tools="http://schemas.android.com/tools"  
  3.     android:layout_width="fill_parent"  
  4.     android:layout_height="fill_parent"  
  5.     android:orientation="vertical" >  
  6.   
  7.     <Button  
  8.         android:layout_centerInParent="true"  
  9.         android:id="@+id/nosupport"  
  10.         android:layout_width="match_parent"  
  11.         android:layout_height="wrap_content"  
  12.         android:text="不支持滑动的菜单"/>  
  13.   
  14.     <Button  
  15.         android:layout_below="@+id/nosupport"  
  16.         android:id="@+id/support"  
  17.         android:layout_width="match_parent"  
  18.         android:layout_height="wrap_content"  
  19.         android:text="支持滑动的菜单" />  
  20.       
  21. </RelativeLayout>  


其中跳转到两个activity,一个是不支持滑动FragmentTab.java,一个是支持滑动FragmentTabSupportSlip.java

FragmentTab.java代码

 

  1. package com.example.fragmenttabhost;  
  2.   
  3. import com.example.fragmentbottommenu.R;  
  4.   
  5. import android.os.Bundle;  
  6. import android.support.v4.app.FragmentActivity;  
  7. import android.support.v4.app.FragmentTabHost;  
  8. import android.view.Menu;  
  9. import android.widget.RadioGroup;  
  10. import android.widget.RadioGroup.OnCheckedChangeListener;  
  11. import android.widget.TabHost.TabSpec;  
  12.   
  13. /** 
  14.  *  
  15.  * @author yummy 
  16.  * email:yummyl.lau@gmail.com 
  17.  *  
  18.  */  
  19. public class FragmentTab extends FragmentActivity  {  
  20.   
  21.     private FragmentTabHost mTabHost;  
  22.     private RadioGroup mTabRg;  
  23.   
  24.     private final Class[] fragments = { TabFragmentOne.class, TabFragmentTwo.class,  
  25.             TabFragmantThree.class, TabFragmentThree.class };  
  26.   
  27.     @Override  
  28.     protected void onCreate(Bundle savedInstanceState) {  
  29.         super.onCreate(savedInstanceState);  
  30.         setContentView(R.layout.activity_tab);  
  31.         initView();  
  32.     }  
  33.   
  34.     private void initView() {  
  35.         mTabHost = (FragmentTabHost) findViewById(android.R.id.tabhost);  
  36.         mTabHost.setup(this, getSupportFragmentManager(), R.id.realtabcontent);  
  37.         // 得到fragment的个数  
  38.         int count = fragments.length;  
  39.         for (int i = 0; i < count; i++) {  
  40.             // 为每一个Tab按钮设置图标、文字和内容  
  41.             TabSpec tabSpec = mTabHost.newTabSpec(i + "").setIndicator(i + "");  
  42.             // 将Tab按钮添加进Tab选项卡中  
  43.             mTabHost.addTab(tabSpec, fragments[i], null);  
  44.         }  
  45.   
  46.         mTabRg = (RadioGroup) findViewById(R.id.tab_rg_menu);  
  47.         mTabRg.setOnCheckedChangeListener(new OnCheckedChangeListener() {  
  48.   
  49.             @Override  
  50.             public void onCheckedChanged(RadioGroup group, int checkedId) {  
  51.                 switch (checkedId) {  
  52.                 case R.id.tab_rb_1:  
  53.                     mTabHost.setCurrentTab(0);  
  54.                     break;  
  55.                 case R.id.tab_rb_2:  
  56.                     mTabHost.setCurrentTab(1);  
  57.   
  58.                     break;  
  59.                 case R.id.tab_rb_3:  
  60.   
  61.                     mTabHost.setCurrentTab(2);  
  62.                     break;  
  63.                 case R.id.tab_rb_4:  
  64.   
  65.                     mTabHost.setCurrentTab(3);  
  66.                     break;  
  67.   
  68.                 default:  
  69.                     break;  
  70.                 }  
  71.             }  
  72.         });  
  73.   
  74.         mTabHost.setCurrentTab(0);  
  75.     }  
  76.   
  77.     @Override  
  78.     public boolean onCreateOptionsMenu(Menu menu) {  
  79.         // Inflate the menu; this adds items to the action bar if it is present.  
  80.         getMenuInflater().inflate(R.menu.main, menu);  
  81.         return true;  
  82.     }  
  83.   
  84. }  

其实现是通过tabhost设置fragment,底部采用单选按钮,通过样式控制实现效果图,单选按钮的监听实现切换fragment。

对应布局xml

 

  1. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  2.     xmlns:tools="http://schemas.android.com/tools"  
  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="0dp"  
  11.         android:layout_weight="1" />  
  12.   
  13.     <RadioGroup  
  14.         android:id="@+id/tab_rg_menu"  
  15.         android:layout_width="fill_parent"  
  16.         android:layout_height="wrap_content"  
  17.         android:background="@drawable/mmfooter_bg"  
  18.         android:orientation="horizontal" >  
  19.   
  20.         <RadioButton  
  21.             android:id="@+id/tab_rb_1"  
  22.             style="@style/tab_rb_style"  
  23.             android:checked="true"  
  24.             android:drawableTop="@drawable/tab_selector_weixing"  
  25.             android:text="微信"   
  26.             />  
  27.   
  28.         <RadioButton  
  29.             android:id="@+id/tab_rb_2"  
  30.             style="@style/tab_rb_style"  
  31.             android:drawableTop="@drawable/tab_selector_tongxunlu"  
  32.             android:text="通讯录" />  
  33.   
  34.         <RadioButton  
  35.             android:id="@+id/tab_rb_3"  
  36.             style="@style/tab_rb_style"  
  37.             android:drawableTop="@drawable/tab_selector_faxian"  
  38.             android:text="发现" />  
  39.   
  40.         <RadioButton  
  41.             android:id="@+id/tab_rb_4"  
  42.             style="@style/tab_rb_style"  
  43.             android:drawableTop="@drawable/tab_selector_wo"  
  44.             android:text="我" />  
  45.     </RadioGroup>  
  46.   
  47.     <android.support.v4.app.FragmentTabHost  
  48.         android:id="@android:id/tabhost"  
  49.         android:layout_width="match_parent"  
  50.         android:layout_height="wrap_content"  
  51.         android:visibility="gone" >  
  52.   
  53.         <FrameLayout  
  54.             android:id="@android:id/tabcontent"  
  55.             android:layout_width="0dp"  
  56.             android:layout_height="0dp"  
  57.             android:layout_weight="0" />  
  58.     </android.support.v4.app.FragmentTabHost>  
  59.   
  60. </LinearLayout>  




FragmentTabSupportSlip.java代码

 

  1. package com.example.fragmenttabhost;  
  2.   
  3. import java.util.ArrayList;  
  4.   
  5. import com.example.fragmentbottommenu.R;  
  6.   
  7. import android.content.Context;  
  8. import android.os.Bundle;  
  9. import android.support.v4.app.Fragment;  
  10. import android.support.v4.app.FragmentActivity;  
  11. import android.support.v4.app.FragmentPagerAdapter;  
  12. import android.support.v4.app.FragmentTabHost;  
  13. import android.support.v4.view.ViewPager;  
  14. import android.view.View;  
  15. import android.view.ViewGroup;  
  16. import android.widget.RadioButton;  
  17. import android.widget.RadioGroup;  
  18. import android.widget.RadioGroup.OnCheckedChangeListener;  
  19. import android.widget.TabHost;  
  20. import android.widget.TabHost.TabSpec;  
  21. import android.widget.TabWidget;  
  22.   
  23. /** 
  24.  *  
  25.  * @author yummy 
  26.  * email:yummyl.lau@gmail.com 
  27.  *  
  28.  */  
  29. public class FragmentTabSupportSlip extends FragmentActivity   
  30.          {  
  31.   
  32.     private FragmentTabHost mTabHost;  
  33.     private RadioGroup mTabRg;  
  34.     private ViewPager mViewPage;  
  35.     TabsAdapter mTabsAdapter;  
  36.     private final Class[] fragments = { TabFragmentOne.class, TabFragmentTwo.class,  
  37.             TabFragmantThree.class, TabFragmentThree.class };  
  38.   
  39.     @Override  
  40.     protected void onCreate(Bundle savedInstanceState) {  
  41.         super.onCreate(savedInstanceState);  
  42.         setContentView(R.layout.activity_tab_supportslip);  
  43.         initView();  
  44.         if (savedInstanceState != null) {  
  45.             mTabHost.setCurrentTabByTag(savedInstanceState.getString("tab"));  
  46.         }  
  47.     }  
  48.   
  49.     private void initView() {  
  50.   
  51.         mTabHost = (FragmentTabHost) findViewById(android.R.id.tabhost);  
  52.         mTabHost.setup(this, getSupportFragmentManager());  
  53.         mViewPage = (ViewPager) findViewById(R.id.pager);  
  54.         mTabRg = (RadioGroup) findViewById(R.id.tab_rg_menu);  
  55.         mTabsAdapter = new TabsAdapter(this, mTabHost, mViewPage, mTabRg);  
  56.         // 得到fragment的个数  
  57.         int count = fragments.length;  
  58.         for (int i = 0; i < count; i++) {  
  59.             // 为每一个Tab按钮设置图标、文字和内容  
  60.             TabSpec tabSpec = mTabHost.newTabSpec(i + "").setIndicator(i + "");  
  61.             // 将Tab按钮添加进Tab选项卡中  
  62.             mTabHost.addTab(tabSpec, fragments[i], null);  
  63.   
  64.             mTabsAdapter.addTab(mTabHost.newTabSpec(i + "")  
  65.                     .setIndicator(i + ""), fragments[i], null);  
  66.         }  
  67.   
  68.         //定义滑动的监听  
  69.         mTabRg.setOnCheckedChangeListener(new OnCheckedChangeListener() {  
  70.   
  71.             @Override  
  72.             public void onCheckedChanged(RadioGroup group, int checkedId) {  
  73.                 switch (checkedId) {  
  74.                 case R.id.tab_rb_1:  
  75.                     mTabHost.setCurrentTab(0);  
  76.                     break;  
  77.                 case R.id.tab_rb_2:  
  78.                     mTabHost.setCurrentTab(1);  
  79.   
  80.                     break;  
  81.                 case R.id.tab_rb_3:  
  82.   
  83.                     mTabHost.setCurrentTab(2);  
  84.                     break;  
  85.                 case R.id.tab_rb_4:  
  86.   
  87.                     mTabHost.setCurrentTab(3);  
  88.                     break;  
  89.   
  90.                 default:  
  91.                     break;  
  92.                 }  
  93.             }  
  94.         });  
  95.         // mTabHost.setCurrentTab(0);  
  96.     }  
  97.   
  98.     @Override  
  99.     protected void onSaveInstanceState(Bundle outState) {  
  100.         super.onSaveInstanceState(outState);  
  101.         outState.putString("tab", mTabHost.getCurrentTabTag());  
  102.     }  
  103.   
  104.   
  105.     /** 
  106.      * This is a helper class that implements the management of tabs and all 
  107.      * details of connecting a ViewPager with associated TabHost. It relies on a 
  108.      * trick. Normally a tab host has a simple API for supplying a View or 
  109.      * Intent that each tab will show. This is not sufficient for switching 
  110.      * between pages. So instead we make the content part of the tab host 0dp 
  111.      * high (it is not shown) and the TabsAdapter supplies its own dummy view to 
  112.      * show as the tab content. It listens to changes in tabs, and takes care of 
  113.      * switch to the correct paged in the ViewPager whenever the selected tab 
  114.      * changes. 
  115.      */  
  116.     public static class TabsAdapter extends FragmentPagerAdapter implements  
  117.             TabHost.OnTabChangeListener, ViewPager.OnPageChangeListener {  
  118.         private final Context mContext;  
  119.         private final TabHost mTabHost;  
  120.         private final ViewPager mViewPager;  
  121.         private final RadioGroup mTabRg;  
  122.         private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>();  
  123.   
  124.         static final class TabInfo {  
  125.             private final String tag;  
  126.             private final Class<?> clss;  
  127.             private final Bundle args;  
  128.   
  129.             TabInfo(String _tag, Class<?> _class, Bundle _args) {  
  130.                 tag = _tag;  
  131.                 clss = _class;  
  132.                 args = _args;  
  133.             }  
  134.         }  
  135.   
  136.         static class DummyTabFactory implements TabHost.TabContentFactory {  
  137.             private final Context mContext;  
  138.   
  139.             public DummyTabFactory(Context context) {  
  140.                 mContext = context;  
  141.             }  
  142.   
  143.             @Override  
  144.             public View createTabContent(String tag) {  
  145.                 View v = new View(mContext);  
  146.                 v.setMinimumWidth(0);  
  147.                 v.setMinimumHeight(0);  
  148.                 return v;  
  149.             }  
  150.         }  
  151.   
  152.         public TabsAdapter(FragmentActivity activity, TabHost tabHost,  
  153.                 ViewPager pager, RadioGroup tabRg) {  
  154.             super(activity.getSupportFragmentManager());  
  155.             mContext = activity;  
  156.             mTabHost = tabHost;  
  157.             mViewPager = pager;  
  158.             mTabRg = tabRg;  
  159.             mTabHost.setOnTabChangedListener(this);  
  160.             mViewPager.setAdapter(this);  
  161.             mViewPager.setOnPageChangeListener(this);  
  162.         }  
  163.   
  164.         public void addTab(TabHost.TabSpec tabSpec, Class<?> clss, Bundle args) {  
  165.             tabSpec.setContent(new DummyTabFactory(mContext));  
  166.             String tag = tabSpec.getTag();  
  167.   
  168.             TabInfo info = new TabInfo(tag, clss, args);  
  169.             mTabs.add(info);  
  170.             mTabHost.addTab(tabSpec);  
  171.             notifyDataSetChanged();  
  172.         }  
  173.   
  174.         @Override  
  175.         public int getCount() {  
  176.             return mTabs.size();  
  177.         }  
  178.   
  179.         @Override  
  180.         public Fragment getItem(int position) {  
  181.             TabInfo info = mTabs.get(position);  
  182.             return Fragment.instantiate(mContext, info.clss.getName(),  
  183.                     info.args);  
  184.         }  
  185.   
  186.         @Override  
  187.         public void onTabChanged(String tabId) {  
  188.             int position = mTabHost.getCurrentTab();  
  189.             mViewPager.setCurrentItem(position);  
  190.             ((RadioButton) mTabRg.getChildAt(position)).setChecked(true);  
  191.         }  
  192.   
  193.         @Override  
  194.         public void onPageScrolled(int position, float positionOffset,  
  195.                 int positionOffsetPixels) {  
  196.         }  
  197.   
  198.         @Override  
  199.         public void onPageSelected(int position) {  
  200.             TabWidget widget = mTabHost.getTabWidget();  
  201.             int oldFocusability = widget.getDescendantFocusability();  
  202.             widget.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);  
  203.             mTabHost.setCurrentTab(position);  
  204.             widget.setDescendantFocusability(oldFocusability);  
  205.         }  
  206.   
  207.         @Override  
  208.         public void onPageScrollStateChanged(int state) {  
  209.         }  
  210.     }  
  211.   
  212.   
  213. }  

其实现是通过viewpager设置fragment,底部采用单选按钮,通过样式控制实现效果图,单选按钮的监听实现切换fragment/而且在viewpager的监听器setOnCheckChangeListenter中也监听了单选按钮的所有监听了功能。

对应布局xml

 

  1. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  2.     xmlns:tools="http://schemas.android.com/tools"  
  3.     android:layout_width="fill_parent"  
  4.     android:layout_height="fill_parent"  
  5.     android:orientation="vertical" >  
  6.   
  7.     <android.support.v4.view.ViewPager  
  8.         android:id="@+id/pager"  
  9.         android:layout_width="match_parent"  
  10.         android:layout_height="0dp"  
  11.         android:layout_weight="1" />  
  12.   
  13.     <RadioGroup  
  14.         android:id="@+id/tab_rg_menu"  
  15.         android:layout_width="fill_parent"  
  16.         android:layout_height="wrap_content"  
  17.         android:background="@drawable/mmfooter_bg"  
  18.         android:orientation="horizontal" >  
  19.   
  20.         <RadioButton  
  21.             android:id="@+id/tab_rb_1"  
  22.             style="@style/tab_rb_style"  
  23.             android:checked="true"  
  24.             android:drawableTop="@drawable/tab_selector_weixing"  
  25.             android:text="微信" />  
  26.   
  27.         <RadioButton  
  28.             android:id="@+id/tab_rb_2"  
  29.             style="@style/tab_rb_style"  
  30.             android:drawableTop="@drawable/tab_selector_tongxunlu"  
  31.             android:text="通讯录" />  
  32.   
  33.         <RadioButton  
  34.             android:id="@+id/tab_rb_3"  
  35.             style="@style/tab_rb_style"  
  36.             android:drawableTop="@drawable/tab_selector_faxian"  
  37.             android:text="发现" />  
  38.   
  39.         <RadioButton  
  40.             android:id="@+id/tab_rb_4"  
  41.             style="@style/tab_rb_style"  
  42.             android:drawableTop="@drawable/tab_selector_wo"  
  43.             android:text="我" />  
  44.     </RadioGroup>  
  45.   
  46.     <android.support.v4.app.FragmentTabHost  
  47.         android:id="@android:id/tabhost"  
  48.         android:layout_width="match_parent"  
  49.         android:layout_height="wrap_content"  
  50.         android:visibility="gone" >  
  51.   
  52.         <FrameLayout  
  53.             android:id="@android:id/tabcontent"  
  54.             android:layout_width="0dp"  
  55.             android:layout_height="0dp"  
  56.             android:layout_weight="0" />  
  57.     </android.support.v4.app.FragmentTabHost>  
  58.   
  59. </LinearLayout>  


里面对应跳转的四个fragment类对应tabFragmentOne.java TabFragmentTwo.java TabFragmentThree.java TabFragmentFour.java 布局比较简单,在onCreateView直接加载,具体见demo。如有疑问,欢迎一起探讨

posted @ 2016-11-11 21:19  天涯海角路  阅读(133)  评论(0)    收藏  举报