首页 > 代码库 > 低版本系统兼容的ActionBar(六)用Fragment+ViewPager+Tab实现快速导航

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

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;    }    @Override    public void onTabReselected(Tab arg0, FragmentTransaction arg1) {            }    @Override    public void onTabSelected(Tab tab, FragmentTransaction arg1) {        if (viewPager != null && viewPager.getCurrentItem() != tab.getPosition()){            viewPager.setCurrentItem(tab.getPosition());        }    }    @Override    public 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;    }    @Override    public void onPageScrollStateChanged(int arg0) {        // TODO 自动生成的方法存根    }    @Override    public void onPageScrolled(int arg0, float arg1, int arg2) {        // TODO 自动生成的方法存根    }    @Override    public 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.ViewPager        android:id="@+id/viewPager01"        android:layout_width="match_parent"        android:layout_height="match_parent"        android:visibility="visible" />    <TextView        android: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" >    <ImageView        android:layout_width="100dp"        android:layout_height="100dp"        android:layout_gravity="center_horizontal"        android:src="@drawable/ic_launcher" />    <TextView        android: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;    @Override    protected 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;        //开始添加Tab        for (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;    }    @Override    public int getCount() {        return mViewList.size();    }    @Override    public boolean isViewFromObject(View arg0, Object arg1) {        return arg0 == arg1;    }    @Override    public void destroyItem(View arg0, int arg1, Object arg2) {        if (mViewList.get(arg1) != null) {            ((ViewPager) arg0).removeView(mViewList.get(arg1));        }    }    @Override    public 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.ViewPager        android: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组件    @Override    public 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时传入的参数的Bundle        Bundle 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;    @Override    protected 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);        }        @Override        public 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;        }        @Override        public int getCount() {            return NUM_ITEMS;        }        @Override        public 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;        // 开始添加Tab        for (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);        }        @Override        public 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;        }        @Override        public 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.PagerSlidingTabStrip        android: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.ViewPager        android: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 {    @Override    public 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;    @Override    protected 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 = { "聊天", "发现", "通讯录" };        @Override        public CharSequence getPageTitle(int position) {            return titles[position];        }        @Override        public int getCount() {            return titles.length;        }        @Override        public 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