• 低版本系统兼容的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

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

    最后,向ActionBarSherlock-4.4.0致敬!

  • 相关阅读:
    如何使用SQL语句 查看存储过程的内容
    sl第一篇
    winForm连接数据库(sqlserver2005)
    Format
    dual使用
    ThreadLocal与事务
    oracle中的常用函数
    Oracle中merge into的使用
    API设计中token的思路
    SVN常用功能
  • 原文地址:https://www.cnblogs.com/tianzhijiexian/p/3878806.html
Copyright © 2020-2023  润新知