Fragment、ViewPager、ActionBar实现TAB导航条效果

 前言:

        制作Tab书签导航条书签选项卡)有多种方法:

【特别提示:】注意几种创建Tab书签导航中Fragment生命周期的变化。

1、TabActivity+TabHost(已经过期)

2、Fragment + FragmentTabHost(取代TabActivity,不建议使用

3、Fragment + ActionBar                                        【不建议使用

4、Fragment + ActionBar + ViewPager 固定导航条【不建议使用

5、Fragment + RadioGroup      【必要时首选】    

6、Fragment + ViewPager  +  RadioGroup自定义固定导航条        推荐使用

7、Fragment + ViewPager  带滑动导航条               【推荐使用

8、Fragment + ViewPager +  HorizontalScrollView自定义滑动导航条        推荐使用

扫描二维码关注公众号,回复: 4910693 查看本文章

一、TabActivity 实现选项卡效果:

        TabActivity(已经过期,使用FragmentActivity来实现相同的效果)

(一)、相关类介绍:

1、TabHost:提供选项卡(Tab页)的窗口视图容器。

2、TabSpec每个选项卡都包含选项卡指示符、内容和用于识别选项卡的标签。

TabSpec与TabHost的关系:

        TabHost相当于浏览器中浏览器分布的集合,而TabSpec则相当于浏览器中的 每一个分页面。在Android中,每一个TabSpec可以是一个组件,也可以是一个布局,TabHost将每一个分页集中在一起,随着选项卡的切换来分别显示相应的界面。

 

(二)、TabActivity实现选项卡效果的步骤:【了解】

1、写选型卡页面特殊的布局文件

  • 根节点必须是TabHost,属性android:id="@android:id/tabhost" 是固定值;
  • 必须有子节点TabWidget,必须有属性android:id="@android:id/tabs";
  • 必须有一个FrameLayout布局节点,属性必须是android:id="@android:id/tabcontent"。

2、继承TabActivity:(以前学习的过程中都是继承android.app.Activity类,但是这里需要继承android.app.TabActivity)

3、创建TabHost对象:通过getTabHost()方法来实现。

4、分别创建TabSpec对象:

  • 通过TabHost对象的newTabSpec()方法创建TabSpec对象;
  • 通过setIndicator()设置标签和图标;
  • 通过setContent()设置内容。

5、TabHost对象添加TabSpec对象。通过TabHost对象的addTab()方法实现添加选项卡。

(三)、示例代码:

1、布局文件的代码:


<TabHost xmlns:android="http://schemas.android.com/apk/res/android"

android:id="@android:id/tabhost"

android:layout_width="fill_parent"

android:layout_height="fill_parent">


<LinearLayout

android:orientation="vertical"

android:layout_width="fill_parent"

android:layout_height="fill_parent"

android:padding="5dp">



<TabWidget

android:id="@android:id/tabs"

android:layout_width="fill_parent"

android:layout_height="wrap_content"/>


<FrameLayout

android:id="@android:id/tabcontent"

android:layout_width="fill_parent"

android:layout_height="fill_parent"

android:padding="5dp"/>

</LinearLayout>

</TabHost>

2、MainActivity中核心代码:


publicclass  MainActivity extends TabActivity {

@Override

protectedvoid onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

Resources res = getResources();

TabHost tabHost = getTabHost();

TabSpec tabSpec1 = tabHost.newTabSpec("records")

.setIndicator("记录", res.getDrawable(R.drawable.ic_launcher))

.setContent(new Intent(this, NextActivity.class));

tabHost.addTab(tabSpec1);

TabSpec tabSpec2 = tabHost.newTabSpec("records")

.setIndicator("联系人", res.getDrawable(R.drawable.contacts))

.setContent(new Intent(this, NextActivity.class));

tabHost.addTab(tabSpec2);


TabSpec tabSpec3 = tabHost.newTabSpec("collections")

.setIndicator("收藏夹", res.getDrawable(R.drawable.collections))

.setContent(new Intent(this, NextActivity.class));

tabHost.addTab(tabSpec3);
}
}

二、FragmentTabHost中实现选项卡效果:

(一)、与TabActivity中实现选项卡的不同之处:

1、TabHost对象的创建方式不同;

2、TabSpec对象的创建方式不同;

3、布局文件不同。

(二)、FragmentActivity 实现选项卡效果的步骤:【掌握

1、写选型卡页面特殊的布局文件:

  • 根节点必须是<android.support.v4.app.FragmentTabHost>;
  • 必须有一个布局节点,用来放置选项卡内容。

2、继承FragmentActivity:(以前学习的过程中都是继承android.app.Activity类,但是这里需要继承android.support.v4.app.FragmentActivity

3、创建TabHost对象:通过(FragmentTabHost) findViewById(R.id.tabhost)方法来实现。

4、TabHost执行setup()方法:

        【备注:】如果使用 findViewById() 加载 TabHost,那么在新增一个选项卡之前, 需要调用 setup()方法。而在 TabActivity 中调用了 getTabHost() 方法后,你就不再需要调用setup()了。

例如:tabHost.setup(this, getSupportFragmentManager(),  R.id.layout_container_tabcontent);

5、分别创建TabSpec对象:

  • 通过TabHost对象的newTabSpec()方法创建TabSpec对象;
  • 通过setIndicator()设置标签和图标;

6、TabHost对象添加TabSpec对象。通过TabHost对象的addTab()方法实现添加选项卡。  

  • 调用TabHost对象的有三个参数的addTab()方法。第一个参数是TabSpec对象,第二个参数是Fragment类的class文件,第三个参数的往Fragment对象中传递的Bundle数据。

(三)、示例代码:

1、布局文件的代码:

<android.support.v4.app.FragmentTabHost xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/tabhost" android:layout_width="match_parent" android:layout_height="match_parent"> <TabWidget android:id="@+id/tabwidget_tabs" android:layout_width="match_parent" android:layout_height="wrap_content"/> <FrameLayout android:id="@+id/layout_container_tabcontent" android:layout_width="match_parent" android:layout_height="match_parent"/> </android.support.v4.app.FragmentTabHost>

2、MainActivity中核心代码:

publicclass MainActivity extends FragmentActivity { private FragmentTabHost tabHost; private Bundle bundle1, bundle2, bundle3; @Override protectedvoid onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tabHost = (FragmentTabHost) findViewById(R.id.tabhost); tabHost.setup(this, getSupportFragmentManager(), R.id.layout_container_tabcontent); bundle1 = new Bundle(); bundle1.putInt("tabIndex", 1); bundle2 = new Bundle(); bundle2.putInt("tabIndex", 2); bundle3 = new Bundle(); bundle3.putInt("tabIndex", 3); Resources res = getResources(); tabHost.addTab( tabHost.newTabSpec("records").setIndicator("记录", res.getDrawable(R.drawable.records)), ContentFragment.class, bundle1); tabHost.addTab( tabHost.newTabSpec("contacts").setIndicator("联系人", res.getDrawable(R.drawable.contacts)), ContentFragment.class, bundle2); tabHost.addTab( tabHost.newTabSpec("collection").setIndicator("收藏夹", res.getDrawable(R.drawable.collections)), ContentFragment.class, bundle3); } }

3、ContentFragment类中的核心代码:

publicclass ContentFragment extends Fragment { private TextView text_fragment_info; private ListView listView_fragment; privateinttabIndex = 0; private String defaultData = "未知"; private List<String> list1, list2, list3; private ArrayAdapter<String> adapter = null; @Override publicvoid onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Bundle bundle = getArguments(); if (bundle != null) { tabIndex = bundle.getInt("tabIndex"); defaultData = "您访问的是第" + tabIndex + "个栏目"; switch (tabIndex) { case 1: list1 = new ArrayList<String>(); for (int i = 0; i < 10; i++) { list1.add("记录:" + i); } break; case 2: list2 = new ArrayList<String>(); for (int i = 0; i < 10; i++) { list2.add("联系人:" + i); } break; case 3: list3 = new ArrayList<String>(); for (int i = 0; i < 10; i++) { list3.add("收藏夹:" + i); } break; default: break; } } } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_content, container, false); text_fragment_info = (TextView) view .findViewById(R.id.text_fragment_info); listView_fragment = (ListView) view .findViewById(R.id.listView_fragment); switch (tabIndex) { case 1: adapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, list1); break; case 2: adapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, list2); break; case 3: adapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, list3); break; default: break; } text_fragment_info.setText(defaultData); listView_fragment.setAdapter(adapter); return view; } }

三、ViewPager实现Tab效果:(ViewPager默认滑动导航条效果)【掌握】

(一)、ViewPager Tab效果说明:

  • 导航条利用<android.support.v4.view.PagerTabStrip>标签生成;
  • 导航条会随着ViewPager内容物的滑动而发生左右侧滑。

(二)、ViewPager 实现带滑动导航条选项卡的步骤:

1、特殊的布局文件;

  • 必须有<android.support.v4.view.ViewPager>节点;
  • 在ViewPager节点中<android.support.v4.view.PagerTabStrip>子节点或者<android.support.v4.view.PagerTitleStrip>子节点,用来显示选项卡导航条。

2、创建ViewPager对象:通过findViewById()方法来实现即可;

3、创建PagerTabStrip对象:通过findViewById()方法来实现即可,设置PagerTabStrip;

  • 通过PagerTabStrip 对象的setTextColor()方法设置导航条文字颜色;
  • 通过PagerTabStrip 对象的setBackgroundColor ()方法设置导航条背景颜色;
  • 通过PagerTabStrip 对象的setDrawFullUnderline()方法设置导航条下方是否有完整下划线颜色;
  • 通过PagerTabStrip 对象的setTabIndicatorColor()方法设置导航条文字下方的指示颜色;
  • 通过PagerTabStrip 对象的setTextSpacing()方法设置导航条文字的间隔。

4、定义ViewPager中的数据源List<View>,自定义PagerAdapter适配器;

5、为ViewPager对象设置适配器。

(三)、示例代码:

1、布局文件的代码:

<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical"> <android.support.v4.view.ViewPager android:id="@+id/viewpager_main" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center"> <android.support.v4.view.PagerTabStrip android:id="@+id/pagerTabStrip_main" android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="2dp" android:layout_gravity="top"> </android.support.v4.view.PagerTabStrip> </android.support.v4.view.ViewPager> </LinearLayout>

【注意事项】

    1.这里ViewPager和 PagerTabStrip都要把包名写全了,不然会ClassNotFount

    2.API中说:在布局xml把PagerTabStrip当做ViewPager的一个子标签来用,不能拿出来,不然还是会报错

    3.在PagerTabStrip标签中可以用属性android:layout_gravity=TOP|BOTTOM来指定title的位置

    4.如果要显示出PagerTabStrip某一页的title,需要在ViewPager的adapter中实现getPageTitle(int)。

2、MainActivity核心代码

publicclass MainActivity extends Activity { private List<View> list_views; private List<String> list_titles; private ViewPager viewPager_main; private PagerTabStrip pagerTabStrip_main; @Override protectedvoid onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); viewPager_main = (ViewPager) findViewById(R.id.viewpager_main); pagerTabStrip_main = (PagerTabStrip) findViewById(R.id.pagerTabStrip_main); pagerTabStrip_main.setTextColor(Color.WHITE); pagerTabStrip_main.setBackgroundColor(Color.BLACK); pagerTabStrip_main.setDrawFullUnderline(true); pagerTabStrip_main.setTabIndicatorColor(Color.CYAN); pagerTabStrip_main.setTextSpacing(50); list_views = new ArrayList<View>(); list_titles = new ArrayList<String>(); LayoutInflater inflater = LayoutInflater.from(this); View view1 = inflater.inflate(R.layout.view1_viewpager, null); View view2 = inflater.inflate(R.layout.view2_viewpager, null); View view3 = inflater.inflate(R.layout.view3_viewpager, null); View view4 = inflater.inflate(R.layout.view4_viewpager, null); list_views.add(view1); list_views.add(view2); list_views.add(view3); list_views.add(view4); list_titles.add("View1"); list_titles.add("View2"); list_titles.add("View3"); list_titles.add("View4"); viewPager_main.setAdapter(new MyAdapter(list_views, list_titles)); } class MyAdapter extends PagerAdapter { private List<View> list = null; private List<String> list_titles = null; public MyAdapter(List<View> list, List<String> list_titles) { this.list = list; this.list_titles = list_titles; } @Override publicint getCount() { if (list != null) { returnlist.size(); } return 0; } @Override publicboolean isViewFromObject(View arg0, Object arg1) { return arg0 == arg1; } @Override public Object instantiateItem(ViewGroup container, int position) { container.addView(list.get(position)); returnlist.get(position); } @Override publicvoid destroyItem(ViewGroup container, int position, Object object) { container.removeView(list.get(position)); } @Override public CharSequence getPageTitle(int position) { returnlist_titles.get(position); } } }

四、ViewPager Tab效果二:(ViewPager自定义导航条效果)

(一)、效果说明:

  • 自定义导航条;
  • 导航条固定位置,不发生左右侧滑。

(二)、ViewPager 实现自定义导航条选项卡的步骤:

1、特殊的布局文件;

  • 必须有<android.support.v4.view.ViewPager>节点;
  • 在ViewPager节点上方可自定义布局,布局内可放置TextView及ImageView等控件来自定义导航条效果。

2、初始化自定义选项卡导航条,并为选项卡设置单击监听事件OnClickListener;

3、初始化ViewPager;

  • 创建ViewPager对象:通过findViewById()方法来实现即可;
  • 定义ViewPager中的数据源List<View>;
  • 自定义PagerAdapter适配器;
  • 为ViewPager对象设置适配器;
  • 给ViewPager设置监听器(OnPageChangeListener)。

(三)、示例代码:

1、布局文件的代码:

<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical"> <LinearLayout android:id="@+id/layout_main_tabtitle" android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:textSize="24sp" android:background="#999" android:text="Tab1"/> <TextView android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:textSize="24sp" android:background="#999" android:layout_marginLeft="1dp" android:text="Tab2"/> <TextView android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:textSize="24sp" android:background="#999" android:layout_marginLeft="1dp" android:text="Tab3"/> </LinearLayout> <TextView android:layout_width="match_parent" android:layout_height="3dp" android:background="#00f" android:text=""/> <android.support.v4.view.ViewPager android:id="@+id/viewPager_main" android:layout_width="match_parent" android:layout_height="wrap_content"/> </LinearLayout>

2、MainActivity核心代码:

publicclass MainActivity extends Activity { private ViewPager viewPager_main; private List<View> list = null; private TextView[] arr_titles = null; @Override protectedvoid onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initTabView(); initViewPager(); } privatevoid initTabView() { LinearLayout layout = (LinearLayout) findViewById(R.id.layout_main_tabtitle); arr_titles = new TextView[3]; for (int i = 0; i < 3; i++) { TextView textView = (TextView) layout.getChildAt(i); arr_titles[i] = textView; arr_titles[i].setEnabled(true); arr_titles[i].setBackgroundColor(Color.GRAY); arr_titles[i].setTag(i); arr_titles[i].setOnClickListener(new OnClickListener() { @Override publicvoid onClick(View v) { // 根据当前点击的position,设置ViewPager的当前item viewPager_main.setCurrentItem((Integer) v.getTag()); } }); } arr_titles[0].setEnabled(false); arr_titles[0].setBackgroundColor(Color.BLUE); } privatevoid initViewPager() { viewPager_main = (ViewPager) findViewById(R.id.viewPager_main); list = new ArrayList<View>(); LayoutInflater inflater = LayoutInflater.from(this); View view1 = inflater.inflate(R.layout.view1_viewpager, null); View view2 = inflater.inflate(R.layout.view2_viewpager, null); View view3 = inflater.inflate(R.layout.view3_viewpager, null); list.add(view1); list.add(view2); list.add(view3); viewPager_main.setAdapter(new MyAdapter(list)); viewPager_main.setOnPageChangeListener(new OnPageChangeListener() { @Override publicvoid onPageSelected(int position) { // 当页面切换改变时,让所有的“点”都变成可操作。 for (int j = 0; j < arr_titles.length; j++) { arr_titles[j].setEnabled(true); arr_titles[j].setBackgroundColor(Color.GRAY); } // 让当前点击的“点”变成不可以操作。 arr_titles[position].setEnabled(false); arr_titles[position].setBackgroundColor(Color.BLUE); } @Override publicvoid onPageScrolled(int arg0, float arg1, int arg2) { } @Override publicvoid onPageScrollStateChanged(int arg0) { } }); } class MyAdapter extends PagerAdapter { private List<View> list = null; public MyAdapter(List<View> list) { this.list = list; } @Override publicint getCount() { returnlist.size(); } @Override publicboolean isViewFromObject(View arg0, Object arg1) { return arg0 == arg1; } @Override public Object instantiateItem(ViewGroup container, int position) { container.addView(list.get(position)); returnlist.get(position); } @Override publicvoid destroyItem(ViewGroup container, int position, Object object) { container.removeView(list.get(position)); } } }

五、Fragment  +   ActionBar实现Tab效果:

(一)、Fragment  +   ActionBar实现选项卡的步骤:

1、当前窗体Activity类要继承于FragmentActivity,而不是Activity;

2、获取ActionBar对象:通过当前上下文对象的getActionBar()方法来实现;

3、设置ActionBar对象的导航模式为Tab导航模式;

  • actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);

4、分别创建Tab对象:

  • 通过ActionBar对象的newTab()方法创建Tab对象;
  • 通过Tab对象的setText()设置选项卡文字;
  • 通过Tab对象的setTabListener()设置选项卡监听事件。

5、自定义ActionBar.TabListener的监听器;

6、为ActionBar对象添加Tab对象。通过ActionBar对象的addTab()方法实现添加选项卡。

7、现场保护和恢复现场。

(二)、示例代码:

1、MainActivity的核心代码:

publicclass MainActivity extends Activity { @Override protectedvoid onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initTabView(); } privatevoid initTabView() { ActionBar actionBar = getActionBar(); actionBar.setHomeButtonEnabled(true); actionBar.setDisplayHomeAsUpEnabled(true); actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); actionBar.addTab(actionBar.newTab().setText("动态") .setTabListener(new MyTabListener())); actionBar.addTab(actionBar.newTab().setText("群组") .setTabListener(new MyTabListener())); actionBar.addTab(actionBar.newTab().setText("好友") .setTabListener(new MyTabListener())); actionBar.addTab(actionBar.newTab().setText("会话") .setTabListener(new MyTabListener())); } @Override publicboolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.main, menu); returntrue; } @Override publicboolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case android.R.id.home: break; case R.id.action_quip: finish(); break; default: break; } returnsuper.onOptionsItemSelected(item); } class MyTabListener implements ActionBar.TabListener { @Override publicvoid onTabSelected(Tab tab, FragmentTransaction ft) { Fragment fragment = new ContentFragment(); Bundle bundle = new Bundle(); bundle.putInt("tabIndex", tab.getPosition() + 1); fragment.setArguments(bundle); FragmentTransaction transaction = getFragmentManager() .beginTransaction(); transaction.replace(R.id.layout_fragment_container, fragment); transaction.addToBackStack(null); transaction.commit(); } @Override publicvoid onTabUnselected(Tab tab, FragmentTransaction ft) { } @Override publicvoid onTabReselected(Tab tab, FragmentTransaction ft) { } } }

六、Fragment  +  ViewPager实现Tab效果:

(一)、Fragment  +   ViewPager实现选项卡的步骤:

1、特殊的布局文件;

  • 必须有<android.support.v4.view.ViewPager>节点;<android.support.v4.view.PagerTabStrip>
  • 在ViewPager节点上方可自定义布局,布局内可放置TextView及ImageView等控件来自定义导航条效果。

2、当前窗体Activity类要继承于FragmentActivity,而不是Activity;

3、初始化自定义选项卡导航条,并为选项卡设置单击监听事件OnClickListener;

4、初始化ViewPager;

  • 创建ViewPager对象:通过findViewById()方法来实现即可;
  • 定义ViewPager中的数据源List<Fragment>;
  • 自定义适配器,要继承于FragmentPagerAdapter,而不是PagerAdapter;
  • 为ViewPager对象设置适配器;
  • 给ViewPager设置监听器(OnPageChangeListener)。

【备注:】为什么要使用FragmentPagerAdapter适配器呢?

因为PagerAdapter的重写方法中:

public Object instantiateItem(ViewGroup container, int position) {

   container.addView(list.get(position));

   return list.get(position);

  }

  public void destroyItem(ViewGroup container, int position, Object object) {

   container.removeView(list.get(position));

  }

container.addView(list.get(position))和container.removeView(list.get(position))的参数都是一个View对象,而不能是Fragment对象。因为涉及到ViewPager的数据源是Fragment的情况,一定要使用FragmentPagerAdapter适配器。

因为继承于FragmentPagerAdapter来自定义适配器,自定义适配器构造方法中的第一个参数FragmentManager只能在窗体中通过getSupportFragmentManager()来获取,这就要求当前窗体必须继承于FragmentActivity类。

【补充:】View、Fragment和Activity的类目录结构:

java.lang.Object

   ↳ android.view.View  

java.lang.Object

   ↳ android.app.Fragment 

java.lang.Object

   ↳ android.support.v4.app.Fragment 

java.lang.Object

   ↳ android.content.Context

      ↳ android.content.ContextWrapper

         ↳ android.view.ContextThemeWrapper

            ↳ android.app.Activity

java.lang.Object

   ↳ android.content.Context

      ↳ android.content.ContextWrapper

         ↳ android.view.ContextThemeWrapper

            ↳ android.app.Activity

               ↳ android.support.v4.app.FragmentActivity

(二)、示例代码:

1、布局文件示例代码:

<?xmlversion="1.0"encoding="utf-8"?> <LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical"> <LinearLayout android:layout_width="match_parent" android:layout_height="98dp" android:background="@drawable/top_theme_blue" android:orientation="vertical"> <LinearLayout android:layout_width="match_parent" android:layout_height="48dp"> <ImageView android:id="@+id/imageView1" android:layout_width="36dp" android:layout_height="36dp" android:layout_gravity="center_vertical" android:layout_marginLeft="10dp" android:src="@drawable/headimg"/> <TextView android:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:layout_marginLeft="10dp" android:text="Android开发团队" /> <ImageView android:id="@+id/imageView2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:paddingLeft="10dp" android:src="@drawable/status_online"/> </LinearLayout> <LinearLayout android:id="@+id/layout_main_tabtitle" android:layout_width="fill_parent" android:layout_height="wrap_content" android:paddingBottom="5dp" android:paddingTop="10dp"> <TextView android:id="@+id/text_tab_activity" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="1.0" android:gravity="center" android:text="动态" android:textColor="#fff" android:textSize="18sp"/> <TextView android:id="@+id/text_tab_groups" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="1.0" android:gravity="center" android:text="群组" android:textColor="#ddd" android:textSize="18sp"/> <TextView android:id="@+id/text_tab_friends" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="1.0" android:gravity="center" android:text="好友" android:textColor="#ddd" android:textSize="18sp"/> <TextView android:id="@+id/text_tab_chat" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="1.0" android:gravity="center" android:text="会话" android:textColor="#ddd" android:textSize="18sp"/> </LinearLayout> <LinearLayout android:id="@+id/layout_indicateline" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="bottom" android:paddingBottom="2dp"> <TextView android:layout_width="0dp" android:layout_height="4dp" android:layout_marginLeft="15dp" android:layout_marginRight="15dp" android:layout_weight="1"/> <TextView android:layout_width="0dp" android:layout_height="4dp" android:layout_marginLeft="15dp" android:layout_marginRight="15dp" android:layout_weight="1"/> <TextView android:layout_width="0dp" android:layout_height="4dp" android:layout_marginLeft="15dp" android:layout_marginRight="15dp" android:layout_weight="1"/> <TextView android:layout_width="0dp" android:layout_height="4dp" android:layout_marginLeft="15dp" android:layout_marginRight="15dp" android:layout_weight="1"/> </LinearLayout> </LinearLayout> <android.support.v4.view.ViewPager android:id="@+id/viewPager_main" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:background="#fff"/> </LinearLayout>

2、Fragment文件中核心代码:同上

3、MainActivity中的核心代码:

publicclass MainActivity extends FragmentActivity { private ViewPager viewPager_main; private List<Fragment> fragmentsList; private TextView[] arr_titles; private TextView[] arr_lines; @Override protectedvoid onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initIndicateLine(); initTabView(); initViewPager(); } privatevoid initTabView() { LinearLayout layout = (LinearLayout) findViewById(R.id.layout_main_tabtitle); arr_titles = new TextView[4]; for (int i = 0; i < arr_titles.length; i++) { TextView textView = (TextView) layout.getChildAt(i); arr_titles[i] = textView; arr_titles[i].setEnabled(true); arr_titles[i].setTag(i); arr_titles[i].setOnClickListener(new OnClickListener() { @Override publicvoid onClick(View v) { viewPager_main.setCurrentItem((Integer) v.getTag()); } }); arr_titles[0].setEnabled(false); } } privatevoid initViewPager() { viewPager_main = (ViewPager) findViewById(R.id.viewPager_main); fragmentsList = new ArrayList<Fragment>(); Fragment fragment1 = new ContentFragment(); Bundle bundle1 = new Bundle(); bundle1.putInt("tabIndex", 1); fragment1.setArguments(bundle1); Fragment fragment2 = new ContentFragment(); Bundle bundle2 = new Bundle(); bundle2.putInt("tabIndex", 2); fragment2.setArguments(bundle2); Fragment fragment3 = new ContentFragment(); Bundle bundle3 = new Bundle(); bundle3.putInt("tabIndex", 3); fragment3.setArguments(bundle3); Fragment fragment4 = new ContentFragment(); Bundle bundle4 = new Bundle(); bundle4.putInt("tabIndex", 4); fragment4.setArguments(bundle4); fragmentsList.add(fragment1); fragmentsList.add(fragment2); fragmentsList.add(fragment3); fragmentsList.add(fragment4); viewPager_main.setAdapter(new MyAdapter(getSupportFragmentManager(), fragmentsList)); viewPager_main.setOnPageChangeListener(new OnPageChangeListener() { @Override publicvoid onPageScrollStateChanged(int position) { } @Override publicvoid onPageScrolled(int arg0, float arg1, int arg2) { } @Override publicvoid onPageSelected(int position) { for (int i = 0; i < arr_titles.length; i++) { arr_titles[i].setEnabled(true); arr_lines[i].setBackgroundColor(Color.TRANSPARENT); } arr_titles[position].setEnabled(false); arr_lines[position].setBackgroundColor(Color.WHITE); } }); viewPager_main.setCurrentItem(0); } privatevoid initIndicateLine() { LinearLayout layout = (LinearLayout) findViewById(R.id.layout_indicateline); arr_lines = new TextView[4]; for (int i = 0; i < arr_lines.length; i++) { TextView view = (TextView) layout.getChildAt(i); arr_lines[i] = view; arr_lines[i].setTag(i); arr_lines[i].setBackgroundColor(Color.TRANSPARENT); } arr_lines[0].setBackgroundColor(Color.WHITE); } class MyAdapter extends FragmentPagerAdapter { private List<Fragment> fragmentsList = null; public MyAdapter(FragmentManager fm) { super(fm); } public MyAdapter(FragmentManager fm, List<Fragment> fragmentsList) { super(fm); this.fragmentsList = fragmentsList; } @Override public Fragment getItem(int arg0) { returnfragmentsList.get(arg0); } @Override publicint getCount() { returnfragmentsList.size(); } } @Override publicboolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.main, menu); returntrue; } }

七、Fragment  +  ActionBar + ViewPager 实现Tab书签导航效果:

(一)、实现步骤:

  1. 窗体继承FragmentActivity ,自定义Fragment;
  2. 初始化ActionBar,设置ActionBar导航模式,for循环设置AcitonBar的监听器setTabListener , 自定义TabListener;
  3. 初始化ViewPager,for循环生成适配器的数据源LIst<Fragment>  ,设置适配器FragmentPagerAdapter,自定义适配器;设置ViewPager监听器setOnPageChangeListener。

(二)、核心代码:

publicclass MainActivity extends FragmentActivity implements ActionBar.TabListener { /** * The {@link android.support.v4.view.PagerAdapter} that will provide * fragments for each of the sections. We use a * {@link android.support.v4.app.FragmentPagerAdapter} derivative, which * will keep every loaded fragment in memory. If this becomes too memory * intensive, it may be best to switch to a * {@link android.support.v4.app.FragmentStatePagerAdapter}. */ SectionsPagerAdapter mSectionsPagerAdapter; /** * The {@link ViewPager} that will host the section contents. */ ViewPager mViewPager; @Override protectedvoid onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // Set up the action bar. final ActionBar actionBar = getActionBar(); actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); // Create the adapter that will return a fragment for each of the three // primary sections of the app. mSectionsPagerAdapter = new SectionsPagerAdapter( getSupportFragmentManager()); // Set up the ViewPager with the sections adapter. mViewPager = (ViewPager) findViewById(R.id.pager); mViewPager.setAdapter(mSectionsPagerAdapter); // When swiping between different sections, select the corresponding // tab. We can also use ActionBar.Tab#select() to do this if we have // a reference to the Tab. mViewPager .setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() { @Override publicvoid onPageSelected(int position) { actionBar.setSelectedNavigationItem(position); } }); // For each of the sections in the app, add a tab to the action bar. for (int i = 0; i < mSectionsPagerAdapter.getCount(); i++) { // Create a tab with text corresponding to the page title defined by // the adapter. Also specify this Activity object, which implements // the TabListener interface, as the callback (listener) for when // this tab is selected. actionBar.addTab(actionBar.newTab() .setText(mSectionsPagerAdapter.getPageTitle(i)) .setTabListener(this)); } } @Override publicboolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); returntrue; } @Override publicvoid onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) { // When the given tab is selected, switch to the corresponding page in // the ViewPager. mViewPager.setCurrentItem(tab.getPosition()); } @Override publicvoid onTabUnselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) { } @Override publicvoid onTabReselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) { } /** * A {@link FragmentPagerAdapter} that returns a fragment corresponding to * one of the sections/tabs/pages. */ publicclass SectionsPagerAdapter extends FragmentPagerAdapter { public SectionsPagerAdapter(FragmentManager fm) { super(fm); } @Override public Fragment getItem(int position) { // getItem is called to instantiate the fragment for the given page. // Return a DummySectionFragment (defined as a static inner class // below) with the page number as its lone argument. Fragment fragment = new DummySectionFragment(); Bundle args = new Bundle(); args.putInt(DummySectionFragment.ARG_SECTION_NUMBER, position + 1); fragment.setArguments(args); return fragment; } @Override publicint getCount() { // Show 3 total pages. return 3; } @Override public CharSequence getPageTitle(int position) { Locale l = Locale.getDefault(); switch (position) { case 0: return getString(R.string.title_section1).toUpperCase(l); case 1: return getString(R.string.title_section2).toUpperCase(l); case 2: return getString(R.string.title_section3).toUpperCase(l); } returnnull; } } /** * A dummy fragment representing a section of the app, but that simply * displays dummy text. */ publicstaticclass DummySectionFragment extends Fragment { /** * The fragment argument representing the section number for this * fragment. */ publicstaticfinal String ARG_SECTION_NUMBER = "section_number"; public DummySectionFragment() { } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.fragment_main_dummy, container, false); TextView dummyTextView = (TextView) rootView .findViewById(R.id.section_label); dummyTextView.setText(Integer.toString(getArguments().getInt( ARG_SECTION_NUMBER))); return rootView; } } }

【备注:】

一、FragmentPagerAdapter

FragmentPagerAdapter 继承自 PagerAdapter。相比通用的 PagerAdapter,该类更专注于每一页均为 Fragment 的情况。如文档所述,该类内的每一个生成的 Fragment 都将保存在内存之中,因此适用于那些相对静态的页,数量也比较少的那种;如果需要处理有很多页,并且数据动态性较大、占用内存较多的情况,应该使用FragmentStatePagerAdapter。

FragmentPagerAdapter总体上来说,相对于继承自PagerAdapter,更方便一些。

1、getItem()

        该类中新增的一个虚方法。该方法的目的为生成新的 Fragment 对象。重载该方法时需要注意这一点。在需要时,该方法将被 instantiateItem() 所调用。

        如果需要向 Fragment 对象传递相对静态的数据时,我们一般通过 Fragment.setArguments() 来进行,这部分代码应当放到 getItem()。它们只会在新生成 Fragment 对象时执行一遍。

        如果需要在生成 Fragment 对象后,将数据集里面一些动态的数据传递给该 Fragment,那么,这部分代码不适合放到 getItem() 中。因为当数据集发生变化时,往往对应的 Fragment 已经生成,如果传递数据部分代码放到了 getItem() 中,这部分代码将不会被调用。这也是为什么很多人发现调用 PagerAdapter.notifyDataSetChanged() 后,getItem() 没有被调用的一个原因。

2、instantiateItem()

        该方法中判断一下要生成的 Fragment 是否已经生成过了,如果生成过了,就使用旧的,旧的将被 Fragment.attach();如果没有,就调用 getItem() 生成一个新的,新的对象将被 FragmentTransation.add()。

        FragmentPagerAdapter 会将所有生成的 Fragment 对象通过 FragmentManager 保存起来备用,以后需要该 Fragment 时,都会从 FragmentManager 读取,而不会再次调用 getItem() 方法。

        如果需要在生成 Fragment 对象后,将数据集中的一些数据传递给该 Fragment,这部分代码应该放到这个方法的重载里。在我们继承的子类中,重载该方法,并调用 FragmentPagerAdapter.instantiateItem() 取得该方法返回 Fragment 对象,然后,我们该 Fragment 对象中对应的方法,将数据传递过去,然后返回该对象。

        否则,如果将这部分传递数据的代码放到 getItem()中,在 PagerAdapter.notifyDataSetChanged() 后,这部分数据设置代码将不会被调用。

3、destroyItem()

        该方法被调用后,会对 Fragment 进行 FragmentTransaction.detach()。这里不是 remove(),只是 detach(),因此 Fragment 还在 FragmentManager 管理中,Fragment 所占用的资源不会被释放。

二、FragmentStatePagerAdapter

FragmentStatePagerAdapter 和前面的 FragmentPagerAdapter 一样,是继承子 PagerAdapter。但是,和 FragmentPagerAdapter 不一样的是,正如其类名中的 'State' 所表明的含义一样,该 PagerAdapter 的实现将只保留当前页面,当页面离开视线后,就会被消除,释放其资源;而在页面需要显示时,生成新的页面(就像 ListView 的实现一样)。这么实现的好处就是当拥有大量的页面时,不必在内存中占用大量的内存。

1、getItem()

        一个该类中新增的虚方法。

        方法的目的为生成新的 Fragment 对象。

        Fragment.setArguments() 这种只会在新建 Fragment 时执行一次的参数传递代码,可以放在这里。

        由于 FragmentStatePagerAdapter.instantiateItem() 在大多数情况下,都将调用 getItem() 来生成新的对象,因此如果在该方法中放置与数据集相关的 setter 代码,基本上都可以在 instantiateItem() 被调用时执行,但这和设计意图不符。毕竟还有部分可能是不会调用 getItem() 的。因此这部分代码应该放到 instantiateItem() 中。

2、instantiateItem()

        除非碰到 FragmentManager 刚好从 SavedState 中恢复了对应的 Fragment 的情况外,该方法将会调用 getItem() 方法,生成新的 Fragment 对象。新的对象将被 FragmentTransaction.add()。

        FragmentStatePagerAdapter 就是通过这种方式,每次都创建一个新的 Fragment,而在不用后就立刻释放其资源,来达到节省内存占用的目的的。

3、destroyItem()

        将 Fragment 移除,即调用 FragmentTransaction.remove(),并释放其资源。

猜你喜欢

转载自blog.csdn.net/dubo_csdn/article/details/86216017
今日推荐