Android Fragment嵌套ViewPager,ViewPager嵌套多个Fragment

来源:互联网 发布:中国联通ims网络快吗 编辑:程序博客网 时间:2024/06/06 02:56

前几天,项目中要实现这么一个功能。就配置了下。其实很简单,首先 需要阅读下我转载的前两篇文章,都是转载的郭神的,写的非常好。我的项目中逢者必用,其实就相当于一个很好的框架来使用,非常方便。

前两篇的项目地址Android Fragment应用实战,使用碎片向ActivityGroup说再见和Android ActionBar应用实战,高仿微信主界面的设计,认真阅读,你会感觉到受益颇深。(当然,如果你不是大神)

其实和前两篇都重复了,都不想粘贴代码了,为了便于学习,还是粘贴上吧。

首先,写了一个BaseActivity,便于封装一些方法继承

[java] view plain copy print?
  1. public class BaseActivity extends FragmentActivity {  
  2.     protected Context mContext;  
  3.   
  4.     @Override  
  5.     protected void onCreate(Bundle arg0) {  
  6.         // TODO Auto-generated method stub   
  7.         super.onCreate(arg0);  
  8.         ActionBar actionBar = getActionBar();  
  9.         actionBar.hide();//隐藏标题栏   
  10.         mContext = this;  
  11.     }  
  12.   
  13.     protected void Toasters(String message) {  
  14.         Toast.makeText(mContext, message, Toast.LENGTH_SHORT).show();  
  15.     }  
  16.   
  17. }  
首先,应用启动后会进入MainActivity,此Activity会加载三个Fragment,随便定义三个(首页,消息,我的)

效果图如下:



首页,消息,我的,三个fragment大同小异,布局在fragment类中加载出来就行,这里就不粘贴代码了。

最终要的是MainActivity,加载了三个fragment,点击效果,显示效果。其实是首次点击的时候首次加载了fragment,后来点击就隐藏了其他的fragment,显示了当前的fragment,这里需要处理隐藏其他的fragment,避免了多个fragment显示到界面上。

[java] view plain copy print?
  1. public class MainActivity extends BaseActivity implements OnClickListener {  
  2.   
  3.     /** 
  4.      * 首页 
  5.      **/  
  6.     private LinearLayout main_linear_home;  
  7.     private ImageView main_imageview_home;  
  8.     private TextView main_txtview_home;  
  9.     /** 
  10.      * 消息 
  11.      **/  
  12.     private LinearLayout main_linear_msg;  
  13.     private ImageView main_imageview_msg;  
  14.     private TextView main_txtview_msg;  
  15.     /** 
  16.      * 我的 
  17.      **/  
  18.     private LinearLayout main_linear_user;  
  19.     private ImageView main_imageview_user;  
  20.     private TextView main_txtview_user;  
  21.   
  22.     /** 
  23.      * 用于对Fragment进行管理 
  24.      */  
  25.     private FragmentManager fragmentManager;  
  26.     /** 
  27.      * 选中的颜色值 
  28.      */  
  29.     private int main_txtColor_sel = 0;  
  30.     /** 
  31.      * 正常颜色值 
  32.      */  
  33.     private int main_txtColor_nol = 0;  
  34.     /** 
  35.      * FrameLayout 
  36.      */  
  37.     private FrameLayout main_new_frame;  
  38.   
  39.     private HomeFragment homeFragment;  
  40.     private MessageFragment messageFragment;  
  41.     private MyFragment myFragment;  
  42.   
  43.     @Override  
  44.     protected void onCreate(Bundle savedInstanceState) {  
  45.         // TODO Auto-generated method stub   
  46.         super.onCreate(savedInstanceState);  
  47.         setContentView(R.layout.activity_main);  
  48.         initView();  
  49.         setOnClickEvent();  
  50.         // 初始化API   
  51.     }  
  52.   
  53.     /** 
  54.      * @Description: TODO 初始化布局控件 
  55.      * @author Sunday 
  56.      * @date 2016年3月26日 
  57.      */  
  58.     private void initView() {  
  59.         // TODO Auto-generated method stub   
  60.   
  61.         main_new_frame = (FrameLayout) findViewById(R.id.main_new_frame);  
  62.         // 布局   
  63.         main_linear_home = (LinearLayout) findViewById(R.id.main_linear_home);  
  64.         main_linear_msg = (LinearLayout) findViewById(R.id.main_linear_msg);  
  65.         main_linear_user = (LinearLayout) findViewById(R.id.main_linear_my);  
  66.         // 底部图片   
  67.         main_imageview_home = (ImageView) findViewById(R.id.main_imageview_home);  
  68.         main_imageview_msg = (ImageView) findViewById(R.id.main_imageview_msg);  
  69.         main_imageview_user = (ImageView) findViewById(R.id.main_imageview_my);  
  70.         // 底部文字   
  71.         main_txtview_home = (TextView) findViewById(R.id.main_txtview_home);  
  72.         main_txtview_msg = (TextView) findViewById(R.id.main_txtview_msg);  
  73.         main_txtview_user = (TextView) findViewById(R.id.main_txtview_my);  
  74.   
  75.         fragmentManager = getSupportFragmentManager();  
  76.         main_txtColor_nol = getBaseContext().getResources().getColor(R.color.main_txt_nor);  
  77.         main_txtColor_sel = getBaseContext().getResources().getColor(R.color.main_txt_sel);  
  78.   
  79.         setTabSelection(0);  
  80.     }  
  81.   
  82.     private void setOnClickEvent() {  
  83.         main_linear_home.setOnClickListener(this);  
  84.         main_linear_msg.setOnClickListener(this);  
  85.         main_linear_user.setOnClickListener(this);  
  86.     }  
  87.   
  88.     /* 
  89.      * 
  90.      */  
  91.     @Override  
  92.     public void onClick(View v) {  
  93.         // TODO Auto-generated method stub   
  94.   
  95.         switch (v.getId()) {  
  96.         case R.id.main_linear_home:  
  97.             setTabSelection(0);  
  98.             break;  
  99.         case R.id.main_linear_msg:  
  100.             setTabSelection(1);  
  101.             break;  
  102.         case R.id.main_linear_my:  
  103.             setTabSelection(2);  
  104.             break;  
  105.         default:  
  106.             break;  
  107.         }  
  108.     }  
  109.   
  110.     /** 
  111.      *  
  112.      * @Description: TODO 底部切换选择fragment 
  113.      * @author Sunday 
  114.      * @date 2016年3月26日 
  115.      */  
  116.     public void setTabSelection(int index) {  
  117.         // 底部切换   
  118.         clearSelection(index);  
  119.         // 开启一个Fragment事务   
  120.         FragmentTransaction transaction = fragmentManager.beginTransaction();  
  121.         // 先隐藏掉所有的Fragment,以防止有多个Fragment显示在界面上的情况  
  122.         hideFragments(transaction);  
  123.         switch (index) {  
  124.   
  125.         case 0:  
  126.             if (homeFragment == null) {  
  127.                 homeFragment = new HomeFragment();  
  128.                 transaction.add(R.id.main_new_frame, homeFragment);  
  129.   
  130.             } else {  
  131.                 transaction.show(homeFragment);  
  132.             }  
  133.             break;  
  134.   
  135.         case 1:  
  136.             if (messageFragment == null) {  
  137.                 messageFragment = new MessageFragment();  
  138.                 transaction.add(R.id.main_new_frame, messageFragment);  
  139.   
  140.             } else {  
  141.                 transaction.show(messageFragment);  
  142.             }  
  143.             break;  
  144.   
  145.         case 2:  
  146.             if (myFragment == null) {  
  147.                 myFragment = new MyFragment();  
  148.                 transaction.add(R.id.main_new_frame, myFragment);  
  149.   
  150.             } else {  
  151.                 transaction.show(myFragment);  
  152.             }  
  153.             break;  
  154.         }  
  155.         transaction.commit();  
  156.     }  
  157.   
  158.     /** 
  159.      *  
  160.      * @Description: TODO 清除选中状态 
  161.      * @author Sunday 
  162.      * @date 2016年3月26日 
  163.      */  
  164.     private void clearSelection(int index) {  
  165.         main_imageview_home.setImageResource(R.drawable.shouye_normal);  
  166.         main_txtview_home.setTextColor(main_txtColor_nol);  
  167.         main_imageview_msg.setImageResource(R.drawable.massage_normal);  
  168.         main_txtview_msg.setTextColor(main_txtColor_nol);  
  169.         main_imageview_user.setImageResource(R.drawable.my_normal);  
  170.         main_txtview_user.setTextColor(main_txtColor_nol);  
  171.   
  172.         if (index == 0) {  
  173.             main_imageview_home.setImageResource(R.drawable.shouye_pressed);  
  174.             main_txtview_home.setTextColor(main_txtColor_sel);  
  175.         }  
  176.   
  177.         if (index == 1) {  
  178.             main_imageview_msg.setImageResource(R.drawable.massage_pressed);  
  179.             main_txtview_msg.setTextColor(main_txtColor_sel);  
  180.         }  
  181.   
  182.         if (index == 2) {  
  183.             main_imageview_user.setImageResource(R.drawable.my_pressed);  
  184.             main_txtview_user.setTextColor(main_txtColor_sel);  
  185.         }  
  186.     }  
  187.   
  188.     /** 
  189.      *  
  190.      * @Description: TODO 隐藏所有的fragment,防止多个fragment显示在界面 
  191.      * @author Sunday 
  192.      * @date 2016年3月26日 
  193.      */  
  194.     private void hideFragments(FragmentTransaction transaction) {  
  195.         if (homeFragment != null) {  
  196.             transaction.hide(homeFragment);  
  197.         }  
  198.         if (messageFragment != null) {  
  199.             transaction.hide(messageFragment);  
  200.         }  
  201.         if (myFragment != null) {  
  202.             transaction.hide(myFragment);  
  203.         }  
  204.     }  
  205.   
  206.     // 定义一个变量,来标识是否退出   
  207.     private static boolean isExit = false;  
  208.   
  209.     Handler mHandler = new Handler() {  
  210.   
  211.         @Override  
  212.         public void handleMessage(Message msg) {  
  213.             super.handleMessage(msg);  
  214.             isExit = false;  
  215.         }  
  216.     };  
  217.   
  218.     /** 
  219.      * 处理返回键事件 
  220.      */  
  221.     @Override  
  222.     public boolean onKeyDown(int keyCode, KeyEvent event) {  
  223.         if (keyCode == KeyEvent.KEYCODE_BACK) {  
  224.             exit();  
  225.             return false;  
  226.         }  
  227.         return super.onKeyDown(keyCode, event);  
  228.     }  
  229.   
  230.     private void exit() {  
  231.         if (!isExit) {  
  232.             isExit = true;  
  233.             Toasters("再按一次退出应用");  
  234.             // 利用handler延迟发送更改状态信息   
  235.             mHandler.sendEmptyMessageDelayed(02000);  
  236.         } else {  
  237.             finish();  
  238.             System.exit(0);  
  239.         }  
  240.     }  
  241. }  
其实就这么简单的实现了框架的搭建,开发中其实很多项目都是采用了这种框架。

现在,我们再来研究下,让首页加载ViewPager,ViewPager嵌套了三个fragment,fragment可以点击切换,也可以滑动切换。

tab滑动的效果,我们任然是使用的第三方的开源框架PagerSlidingTabStrip,稳定性非常好,还可以随意修改源码。

首先需要将PagerSlidingTabStrip的源码下载下来,并集成到我们的项目当中,PagerSlidingTabStrip的GitHub主页地址是:https://github.com/astuetz/PagerSlidingTabStrip 。

最重要的HomeFragment的代码如下:

[java] view plain copy print?
  1. public class HomeFragment extends Fragment {  
  2.   
  3.     /** 
  4.      * PagerSlidingTabStrip的实例 
  5.      */  
  6.     private PagerSlidingTabStrip tabs;  
  7.   
  8.     /** 
  9.      * 获取当前屏幕的密度 
  10.      */  
  11.     private DisplayMetrics dm;  
  12.   
  13.     private OneFragment oneFragment;  
  14.     private TwoFragment twoFragment;  
  15.     private ThreeFragment threeFragment;  
  16.     /*  
  17.      * 
  18.      */  
  19.   
  20.     @Override  
  21.     public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {  
  22.         // TODO Auto-generated method stub   
  23.         View view = inflater.inflate(R.layout.fragment_home, null);  
  24.         setOverflowShowingAlways();  
  25.         dm = getResources().getDisplayMetrics();  
  26.         ViewPager pager = (ViewPager)view. findViewById(R.id.pager);  
  27.         pager.setOffscreenPageLimit(0);//设置ViewPager的缓存界面数,默认缓存为2  
  28.         tabs = (PagerSlidingTabStrip) view.findViewById(R.id.tabs);  
  29.         pager.setAdapter(new MyPagerAdapter(getChildFragmentManager()));  
  30.         tabs.setViewPager(pager);  
  31.         setTabsValue();  
  32.         return view;  
  33.     }  
  34.   
  35.     /** 
  36.      * 对PagerSlidingTabStrip的各项属性进行赋值。 
  37.      */  
  38.     private void setTabsValue() {  
  39.         // 设置Tab是自动填充满屏幕的   
  40.         tabs.setShouldExpand(true);  
  41.         // 设置Tab的分割线是透明的   
  42.         tabs.setDividerColor(Color.TRANSPARENT);  
  43.         // 设置Tab底部线的高度   
  44.         tabs.setUnderlineHeight((int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 1, dm));  
  45.         // 设置Tab Indicator的高度   
  46.         tabs.setIndicatorHeight((int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 3, dm));  
  47.         // 设置Tab标题文字的大小   
  48.         tabs.setTextSize((int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 16, dm));  
  49.         // 设置Tab Indicator的颜色   
  50.         tabs.setIndicatorColor(Color.parseColor("#d83737"));//#d83737   #d83737(绿)  
  51.         // 设置选中Tab文字的颜色 (这是我自定义的一个方法)   
  52.         tabs.setSelectedTextColor(Color.parseColor("#ffffff"));  
  53.         // 取消点击Tab时的背景色   
  54.         tabs.setTabBackground(0);  
  55.     }  
  56.   
  57.     public class MyPagerAdapter extends FragmentPagerAdapter {  
  58.   
  59.         public MyPagerAdapter(FragmentManager fm) {  
  60.             super(fm);  
  61.         }  
  62.   
  63.         private final String[] titles = { "TAB1""TAB2""TAB3" };  
  64.   
  65.         @Override  
  66.         public CharSequence getPageTitle(int position) {  
  67.             return titles[position];  
  68.         }  
  69.   
  70.         @Override  
  71.         public int getCount() {  
  72.             return titles.length;  
  73.         }  
  74.   
  75.         @Override  
  76.         public Fragment getItem(int position) {  
  77.             switch (position) {  
  78.             case 0:  
  79.                 if (oneFragment == null) {  
  80.                     oneFragment = new OneFragment();  
  81.                 }  
  82.                 return oneFragment;  
  83.             case 1:  
  84.                 if (twoFragment == null) {  
  85.                     twoFragment = new TwoFragment();  
  86.                 }  
  87.                 return twoFragment;  
  88.             case 2:  
  89.                 if (threeFragment == null) {  
  90.                     threeFragment = new ThreeFragment();  
  91.                 }  
  92.                 return threeFragment;  
  93.             default:  
  94.                 return null;  
  95.             }  
  96.         }  
  97.   
  98.     }  
  99.       
  100.     private void setOverflowShowingAlways() {  
  101.         try {  
  102.             ViewConfiguration config = ViewConfiguration.get(getParentFragment().getActivity());  
  103.             Field menuKeyField = ViewConfiguration.class  
  104.                     .getDeclaredField("sHasPermanentMenuKey");  
  105.             menuKeyField.setAccessible(true);  
  106.             menuKeyField.setBoolean(config, false);  
  107.         } catch (Exception e) {  
  108.             e.printStackTrace();  
  109.         }  
  110.     }  
  111.   
  112. }  

其次,布局文件也拿上来了

[java] view plain copy print?
  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.    <com.sunday.slidetabfragment.view.PagerSlidingTabStrip  
  8.         android:id="@+id/tabs"  
  9.         android:layout_width="match_parent"  
  10.         android:layout_height="45dp"  
  11.         android:background="@color/light_black_bg" />  
  12.   
  13.     <android.support.v4.view.ViewPager  
  14.         android:id="@+id/pager"  
  15.         android:layout_width="match_parent"  
  16.         android:layout_height="wrap_content" />  
  17.   
  18. </LinearLayout>  

最终的效果图如下:


效果就如期待的那样,是不是觉得超级简单。如果要是觉得难看,tab样式和颜色当然是可以修改的,图片也可以使用UI设计的。

源码地址,点击下载