Tab经常和Fragment结合使用,这一讲我们用3种方式来实现这种快捷导航。

0、重要的两个监听器

MyTabListener,这个我们之前已经接触过了

package com.kale.actionbar05;import android.support.v4.app.FragmentTransaction;
import android.support.v4.view.ViewPager;
import android.support.v7.app.ActionBar;
import android.support.v7.app.ActionBar.Tab;/*** @author:Jack Tony* @tips  :设置tab的监听器,控制viewpager的显示* @date  :2014-7-30*/
public class MyTabListener implements ActionBar.TabListener{ViewPager viewPager;public MyTabListener(ViewPager viewPager) {this.viewPager =viewPager;}@Overridepublic void onTabReselected(Tab arg0, FragmentTransaction arg1) {}@Overridepublic void onTabSelected(Tab tab, FragmentTransaction arg1) {if (viewPager != null && viewPager.getCurrentItem() != tab.getPosition()){viewPager.setCurrentItem(tab.getPosition());}}@Overridepublic void onTabUnselected(Tab arg0, FragmentTransaction arg1) {}}

PageChangeListener(这里面是滑动ViewPager会触发的动作)

package com.kale.actionbar05;import android.support.v4.view.ViewPager;
import android.support.v7.app.ActionBar;public class PageChangeListener implements ViewPager.OnPageChangeListener {private ActionBar actionBar;public PageChangeListener(ActionBar actionBar) {this.actionBar = actionBar;}@Overridepublic void onPageScrollStateChanged(int arg0) {// TODO 自动生成的方法存根
}@Overridepublic void onPageScrolled(int arg0, float arg1, int arg2) {// TODO 自动生成的方法存根
}@Overridepublic void onPageSelected(int position) {//System.out.println("position:" + position);
        actionBar.setSelectedNavigationItem(position);}
}

一、Tab+ViewPager

先定义一个主布局,里面放入ViewPager。我们即将在这个ViewPager中放入视图

view_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"><android.support.v4.view.ViewPagerandroid:id="@+id/viewPager01"android:layout_width="match_parent"android:layout_height="match_parent"android:visibility="visible" /><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentTop="true"android:layout_centerHorizontal="true"android:text="下面是ViewPager"android:textAppearance="?android:attr/textAppearanceLarge" /></RelativeLayout>

view_item.xml

 这是准备放入ViewPager的视图。我们放3个TextView,然后再放入这整个视图

<?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" ><ImageViewandroid:layout_width="100dp"android:layout_height="100dp"android:layout_gravity="center_horizontal"android:src="@drawable/ic_launcher" /><TextViewandroid:id="@+id/viewItem_textView"android:layout_width="match_parent"android:layout_height="match_parent"android:gravity="center"android:text="No 4"android:textSize="40sp"/></LinearLayout>

ViewMainActivity

package com.kale.actionbar05.view;import java.util.ArrayList;import com.kale.actionbar05.MyTabListener;
import com.kale.actionbar05.PageChangeListener;
import com.kale.actionbar05.R;import android.os.Bundle;
import android.support.v4.view.ViewPager;
import android.support.v7.app.ActionBar;
import android.support.v7.app.ActionBarActivity;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.TextView;public class ViewMainActivity extends ActionBarActivity {private ActionBar actionBar;private ArrayList<View> viewList;ViewPager viewPager;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.view_main);initView();initActionBar();viewList = new ArrayList<View>();//得到填充器,准备获得对象LayoutInflater mLayoutInflater = getLayoutInflater();  //给适配器准备好数据,添加进list中for (int i = 0; i < 3; i++) {TextView tv  = (TextView)(mLayoutInflater.inflate(R.layout.view_item, null)).findViewById(R.id.viewItem_textView);tv.setText("No "+(i+1));viewList.add(tv);}    viewList.add(mLayoutInflater.inflate(R.layout.view_item, null));//也可以直接用布局做一个视图//内容准备好后,设置适配器viewPager.setAdapter(new MyPagerAdapter(viewList));viewPager.setOnPageChangeListener(new PageChangeListener(getSupportActionBar()));  }/***初始化actionBar和Tab */private void initActionBar() {actionBar = getSupportActionBar();//设定有Tab
        actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);ActionBar.Tab tab;//开始添加Tabfor (int i = 1; i <= 4; i++) {tab = actionBar.newTab();tab.setText("Tab " + i);tab.setTabListener(new MyTabListener(viewPager));actionBar.addTab(tab);}}private void initView() {viewPager = (ViewPager)findViewById(R.id.viewPager01);}}

MyPagerAdapter(这里设置适配器,从list中得到一个个View,然后展现出来)

package com.kale.actionbar05.view;import java.util.ArrayList;import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.View;
import android.view.ViewGroup;public class MyPagerAdapter extends PagerAdapter {private ArrayList<View> mViewList;private int pagerNum = 0;public MyPagerAdapter(ArrayList<View> viewList) {mViewList = viewList;}public int getPagerNum() {return pagerNum;}@Overridepublic int getCount() {return mViewList.size();}@Overridepublic boolean isViewFromObject(View arg0, Object arg1) {return arg0 == arg1;}@Overridepublic void destroyItem(View arg0, int arg1, Object arg2) {if (mViewList.get(arg1) != null) {((ViewPager) arg0).removeView(mViewList.get(arg1));}}@Overridepublic Object instantiateItem(View arg0, int arg1) {try {if (mViewList.get(arg1).getParent() == null) {((ViewPager) arg0).addView(mViewList.get(arg1), 0);} else {/** 很难理解新添加进来的view会自动绑定一个父类,由于一个儿子view不能与两个父类相关, 所以得解绑不这样做否则会产生* viewpager java.lang.IllegalStateException: The specified* child already has a parent. You must call removeView() on the* child's parent first.*/((ViewGroup) mViewList.get(arg1).getParent()).removeView(mViewList.get(arg1));((ViewPager) arg0).addView(mViewList.get(arg1), 0);}} catch (Exception e) {e.printStackTrace();} finally {pagerNum = arg1;}return mViewList.get(arg1);}}

二、Tab+Fragment+ViewPager

fragment_main.xml (主布局)

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"><android.support.v4.view.ViewPagerandroid:id="@+id/viewPager02"android:layout_width="match_parent"android:layout_height="match_parent"android:visibility="visible" /></RelativeLayout>

DummyFragment(准备填充进去的Fragment,这里面接受一个参数用来方便说明)

package com.kale.actionbar05.fragment;import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;public class DummyFragment extends Fragment {public static final String BUNDLE_SECTION_NUMBER = "section_number";// 该返回值就是这个Fragment显示的view组件
    @Overridepublic View onCreateView(LayoutInflater inflater,@Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {super.onCreateView(inflater, container, savedInstanceState);TextView textView = new TextView(getActivity());textView.setGravity(Gravity.CENTER);// 获取创建该Fragment时传入的参数的BundleBundle bundle = getArguments();textView.setText("Fragment 0" + bundle.getInt(BUNDLE_SECTION_NUMBER));textView.setTextSize(50);return textView;}
}

FragmentMainActivity

package com.kale.actionbar05.fragment;import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.app.FragmentStatePagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.app.ActionBar;
import android.support.v7.app.ActionBarActivity;
import android.view.ViewGroup;import com.kale.actionbar05.MyTabListener;
import com.kale.actionbar05.PageChangeListener;
import com.kale.actionbar05.R;/*** @author:Jack Tony* @tips :出于使用FragmentPagerAdapter 时,Fragment对象会一直存留在内存中.*       所以当有大量的显示页时,就不适合用FragmentPagerAdapter了*       ,FragmentPagerAdapter适用于只有少数的page情况。*       多的话请考虑使用FragmentStatePagerAdapter,当使用FragmentStatePagerAdapter时,*       如果Fragment不显示,那么Fragment对象会被销毁,但在回调onDestroy()方法之前*       会回调onSaveInstanceState(Bundle outState)方法来保存Fragment的状态,*       下次Fragment显示时通过onCreate(Bundle savedInstanceState)把存储的状态值取出来,*       FragmentStatePagerAdapter 比较适合页面比较多的情况,像一个页面的ListView* @date :2014-7-30*/
public class FragmentMainActivity extends ActionBarActivity {ActionBar actionBar;ViewPager viewPager;@Overrideprotected void onCreate(Bundle savedInstanceState) {// TODO 自动生成的方法存根super.onCreate(savedInstanceState);setContentView(R.layout.fragment_main);initView();initActionBar();viewPager.setAdapter(new MyFragmentPagerAdapter(getSupportFragmentManager()));//下面是用另一种适配器的方式,其实就是换个名字。主要针对的是很多个fragment的情况//viewPager.setAdapter(new MyFragmentStaticAdapter(getSupportFragmentManager()));viewPager.setOnPageChangeListener(new PageChangeListener(actionBar));}public class MyFragmentPagerAdapter extends FragmentPagerAdapter {private int NUM_ITEMS = 4;public MyFragmentPagerAdapter(FragmentManager fm) {super(fm);}@Overridepublic Fragment getItem(int position) {Fragment fragment = new DummyFragment();Bundle args = new Bundle();args.putInt(DummyFragment.BUNDLE_SECTION_NUMBER, position + 1);fragment.setArguments(args);return fragment;}@Overridepublic int getCount() {return NUM_ITEMS;}@Overridepublic void destroyItem(ViewGroup container, int position, Object object) {// 这里Destroy的是Fragment的视图层次,并不是Destroy Fragment对象super.destroyItem(container, position, object);//Log.i("INFO", "Destroy Item " + position);
        }}private void initView() {viewPager = (ViewPager) findViewById(R.id.viewPager02);}/*** 初始化actionBar和Tab*/private void initActionBar() {actionBar = getSupportActionBar();// 设定有Tab
        actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);ActionBar.Tab tab;// 开始添加Tabfor (int i = 1; i <= 4; i++) {tab = actionBar.newTab();tab.setText("Tab " + i);tab.setTabListener(new MyTabListener(viewPager));actionBar.addTab(tab);}}public class MyFragmentStaticAdapter extends FragmentStatePagerAdapter {private int NUM_ITEMS = 5;public MyFragmentStaticAdapter(FragmentManager fm) {super(fm);}@Overridepublic Fragment getItem(int position) {Fragment fragment = new DummyFragment();Bundle args = new Bundle();args.putInt(DummyFragment.BUNDLE_SECTION_NUMBER, position + 1);fragment.setArguments(args);return fragment;}@Overridepublic int getCount() {return NUM_ITEMS;}}
}

三、PagerSlidingTabStrip+ViewPager+Fragment

tab_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical" xmlns:app="http://schemas.android.com/apk/res/com.kale.actionbar05"><com.astuetz.PagerSlidingTabStripandroid:id="@+id/tabs"android:layout_width="match_parent"android:layout_height="40dp"app:pstsShouldExpand="true"app:pstsUnderlineHeight="1dp"app:pstsIndicatorHeight="4dp"app:pstsIndicatorColor="#45c01a"app:pstsSelectedTabTextColor="#45c01a"app:pstsTabTextSize="16sp"app:pstsTabTextColor="#666666"app:pstsDividerColor="@android:color/transparent"/><android.support.v4.view.ViewPagerandroid:id="@+id/viewPager03"android:layout_width="match_parent"android:layout_height="match_parent"android:visibility="visible" /></LinearLayout>

ChatFragment (其中的一个Fragment,其余的都一样,就是文字变了)
package com.kale.actionbar05.tab;import android.app.ActionBar.LayoutParams;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.TextView;public class ChatFragment extends Fragment {@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);FrameLayout fl = new FrameLayout(getActivity());fl.setLayoutParams(params);DisplayMetrics dm = getResources().getDisplayMetrics();final int margin = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 8, dm);TextView v = new TextView(getActivity());params.setMargins(margin, margin, margin, margin);v.setLayoutParams(params);v.setLayoutParams(params);v.setGravity(Gravity.CENTER);v.setText("聊天界面");v.setTextSize((int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 12, dm));fl.addView(v);return fl;}
}

TabMainActivity(定义个Tab,然后设定个ViewPager就行了。Fragment在适配器中设置)

package com.kale.actionbar05.tab;import android.graphics.Color;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.app.ActionBarActivity;
import android.util.DisplayMetrics;
import android.util.TypedValue;import com.astuetz.PagerSlidingTabStrip;
import com.kale.actionbar05.R;public class TabMainActivity extends ActionBarActivity {private ChatFragment chatFragment;private FoundFragment foundFragment;private ContactsFragment contactsFragment;/*** PagerSlidingTabStrip的实例*/private PagerSlidingTabStrip tabs;private ViewPager viewPager;@Overrideprotected void onCreate(Bundle savedInstanceState) {// TODO 自动生成的方法存根super.onCreate(savedInstanceState);setContentView(R.layout.tab_main);initView();//initTabs();  //用代码来设置tab的样式,因为我在xml中已经设置了,所以就不在代码中写了viewPager.setAdapter(new MyPagerAdapter(getSupportFragmentManager()));tabs.setViewPager(viewPager);}/*** @author:Jack Tony* @tips :定义适配器,返回一个fragment对象* @date :2014-7-30*/public class MyPagerAdapter extends FragmentPagerAdapter {public MyPagerAdapter(FragmentManager fm) {super(fm);}private final String[] titles = { "聊天", "发现", "通讯录" };@Overridepublic CharSequence getPageTitle(int position) {return titles[position];}@Overridepublic int getCount() {return titles.length;}@Overridepublic Fragment getItem(int position) {switch (position) {case 0:if (chatFragment == null) {chatFragment = new ChatFragment();}return chatFragment;case 1:if (foundFragment == null) {foundFragment = new FoundFragment();}return foundFragment;case 2:if (contactsFragment == null) {contactsFragment = new ContactsFragment();}return contactsFragment;default:return null;}}}/***定义的属性,参考:https://github.com/astuetz/PagerSlidingTabStrip */private void initTabs() {/*** 获取当前屏幕的密度*/DisplayMetrics dm;dm = getResources().getDisplayMetrics();// 设置Tab是自动填充满屏幕,也就是均分屏幕宽度,每个tab的weight都是一致的    app:pstsShouldExpand="true"tabs.setShouldExpand(true);// 设置Tab的分割线是透明的     app:pstsDividerColor="@android:color/transparent"
        tabs.setDividerColor(Color.TRANSPARENT);// 设置Tab底部与下面分割的细线的高度    app:pstsUnderlineHeight="1dp"tabs.setUnderlineHeight((int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 1, dm));// 设置Tab 指示器的高度        app:pstsIndicatorHeight="4dp"tabs.setIndicatorHeight((int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 4, dm));// 设置Tab标题文字的大小        app:pstsTabTextSize="16sp"tabs.setTextSize((int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 16, dm));// 设置Tab Indicator的颜色        app:pstsIndicatorColor="#45c01a"tabs.setIndicatorColor(Color.parseColor("#45c01a"));// 设置选中Tab文字的颜色         app:pstsSelectedTabTextColor="#45c01a"tabs.setSelectedTextColor(Color.parseColor("#45c01a"));// 取消点击Tab时的背景色        app:pstsTabBackground="0"tabs.setTabBackground(0);}private void initView() {tabs = (PagerSlidingTabStrip) findViewById(R.id.tabs);viewPager = (ViewPager) findViewById(R.id.viewPager03);}
}

源码下载:http://download.csdn.net/detail/shark0017/7696295

题外话:通过这几篇文章的学习,我可以肯定的说:我们已经不需要ActionBarSherlock(最高版本4.4.0)这个开源库了。其实这是件好事,很感谢国外的这个团体开发的这么有效稳定的库,给我们开发者带来了极大的帮助。离开这个未免有些伤感,我还记得之前看到它的Demo时那种激动,整天学习它代码的那种苦,还有找到解决办法的兴奋。但无论怎样,那都是历史了。我们需要迎接新的科技,迎接更好的明天!

最后,向ActionBarSherlock-4.4.0致敬!

低版本系统兼容的ActionBar(六)用Fragment+ViewPager+Tab实现快速导航相关推荐

  1. 低版本系统兼容的ActionBar(四)添加Tab+添加自定义的Tab视图+Fragment

    在ActionBar中添加Tab是很有用的技巧.在support V7库的支持下,我们几乎可以用和之前一样的方式来添加Tab,对于Tab来说,我们可以和MenuItem一样,给他定义自己的视图.我这里 ...

  2. Android实现一键复制粘贴,兼容低版本系统(api 11以下)

    Android实现一键复制粘贴,兼容低版本系统(api11以下) /**         * 实现文本复制功能         * @param content         * @return t ...

  3. android 兼容包(可兼容低版本系统)

    android 兼容包(可兼容低版本系统) 高Level为了兼容低Level版本,从而推出了兼容包android-support-v* 目前发现的只有三个 android-support-v4   a ...

  4. html表单居中_如何在IE低版本中兼容HTML5表单属性placeholder属性

    WEB开发数据提交是必不可少的,为了更友好的用户体验,通常需要给输入框一个默认的提示信息.HTML5技术提供了一个表单属性placeholder专门用于输入框默认提示,但是在IE低版本中根本不兼容. ...

  5. MacBook装低版本系统需要的系统包

    MacBook装低版本系统需要的系统包! 前因后果: 老MBP装了Catalina后偶尔有点卡.吃资源厉害,就想降回Sierra. 搜了一天国内网站.发现dmg包很少.而且都是网盘下载(百度云盘居多) ...

  6. android低版本系统部分手机加载不出H5页面

    我这个问题出现在android6.0以下的机子上,  其他版本没问题. 解决方法(前三种方法需要Android同学改,第四种需要web前端同学改): 1.启用mixed content 在Androi ...

  7. 如何将高版本服务器系统转为低版本,iOS高版本备份恢复到低版本系统的方法

    一般来说,在更新iOS系统的时候我们都会建议大家先用iTunes对系统进行完整备份.但时不时都会有人偷懒,或者使用手机OTA升级而没有对系统备份,最终导致不满意新系统了,想降级却无备份可以恢复的尴尬局 ...

  8. HTML data属性简介以及低版本浏览器兼容算法

    实例 使用 data-* 属性来嵌入自定义数据: <ul> <li data-animal-type="bird">Owl</li> <l ...

  9. 低版本浏览器兼容处理

    1.HTML5新标签对IE低版本浏览器的兼容处理 问题概述:IE8浏览器中还没有添加对HTML5新标签的支持,当在页面中使用HTML5新标签时,新标签不兼容 1)使用JavaScript新增元素的方法 ...

最新文章

  1. Cell Host综述-建立因果关系:合成菌群在植物菌群研究中的机会
  2. 机器学习(MACHINE LEARNING)MATLAB蚁群算法解决TSP问题
  3. 基于tiny4412的Linux内核移植 -- eMMC驱动移植(六)
  4. python详细下载安装教程-Python下载并安装图形教程[超级详细]
  5. oracle的redo和undo,OracleUndoRedo通俗理解
  6. 汇编中断知识之INT 1CH
  7. 教你50招提升ASP.NET性能(十五):解决性能问题时不要低估UI的价值
  8. 忘记mysql的root密码后,修改密码
  9. java环境变量_Java的下载及环境变量的配置
  10. 系统服务启动交互式程序(C++)
  11. Unity sendmessage发送多个参数
  12. Springboot整合Drools规则引擎
  13. java线程游戏之随机小球游戏V1
  14. win下装django
  15. 运用Python 模拟太阳-地球-月亮运动模型
  16. 程序员考公指南1-59
  17. boot版本是什么 cent os_CentOS下载及版本选择-CentOS LiveCD、LiveDVD和BinDVD区别
  18. Python中int32转int64
  19. android 对话框 美化,Android修改Dialog样式
  20. tokenizer.encode_plus方法

热门文章

  1. python django下载_简单了解django文件下载方式
  2. easyui treenode java_easyui tree的简单使用
  3. win2003无法进入桌面_电脑桌面怎么建立便签,可以在电脑桌面显示的便签
  4. 后渗透后门_TheFatRat:Msfvenom傻瓜化,小白也可以学渗透
  5. cp分解实现_对标Eureka的AP一致性,Nacos如何实现Raft算法
  6. Scala学习笔记05:函数
  7. 【CF 543D】Road Improvement,树形DP
  8. 【BZOJ3223】文艺平衡树,Splay反转区间
  9. gtx780有html接口吗,笔记本玩转游戏大作 达人外接GTX780Ti
  10. 2017.7.18 树上距离=k 思考记录