Android进阶:步骤四:Viewpager的基本使用


借鉴:https://blog.csdn.net/weixin_39251617/article/details/79399592


大致内容:


ViewPager实践的三种效果


1. 引导界面 ViewPager

2. FragmentPageAdapter

3. 常见Tab切换效果

一、简介

Viewpager,视图翻页工具,提供了多页面切换的效果。Android 3.0后引入的一个UI控件,位于v4包中。低版本使用需要导入v4包,但是现在我们开发的APP一般不再兼容3.0及以下的系统版本,另外现在大多数使用Android studio进行开发,默认导入v7包,v7包含了v4,所以不用导包,越来越方便了。


Viewpager使用起来就是我们通过创建adapter给它填充多个view,左右滑动时,切换不同的view。Google官方是建议我们使用Fragment来填充ViewPager的,这样 可以更加方便的生成每个Page,以及管理每个Page的生命周期

 


二、基本使用

1.xml(主布局main_acitivity.xml作为容器)

<?xml version="1.0" encoding="utf-8"?>

<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"

    tools:context=".MainActivity">

 

    <android.support.v4.view.ViewPager

        android:id="@+id/id_viewpager"

        android:layout_width="match_parent"

        android:layout_height="match_parent">

    </android.support.v4.view.ViewPager>

 

 

</RelativeLayout>

2.pager布局(可以复用一个,也可以创建多个)我这里写了first...four四个布局都是一样的

<?xml version="1.0" encoding="utf-8"?>

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

    android:layout_width="match_parent"

    android:layout_height="match_parent">

 

    <TextView

        android:layout_width="match_parent"

        android:layout_height="match_parent"

        android:text="first"

        android:textSize="30dp" />

</RelativeLayout>

3.MainAcitivity中

import android.support.v4.view.ViewPager;

import android.support.v7.app.AppCompatActivity;

import android.os.Bundle;

import android.view.View;

import com.demo.viewpagerdemo.adapter.MyPagerAdapter;

 

import java.util.ArrayList;

import java.util.List;

 

public class MainActivity extends AppCompatActivity {

 

    //全局变量

    private ViewPager mViewPager;

    private int[] mLayoutIDs = {//每一个视图id数组

            R.layout.view_first,

            R.layout.view_second,

            R.layout.view_third,

            R.layout.view_four

    };

    private List<View> views;

 

    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

        mViewPager = findViewById(R.id.id_viewpager);

        //初始化数据即视图

        views = new ArrayList<>();

        for (int index = 0; index < mLayoutIDs.length; index++) {

            //1.构造视图

            View view = getLayoutInflater().inflate(mLayoutIDs[index], null);

            views.add(view);

//            //2.也可以直接用图片视图

//            ImageView imageView = new ImageView(this);

//            imageView.setImageResource(R.mipmap.ic_launcher);

//            views.add(imageView);

        }

        //设置adapter

        mViewPager.setAdapter(new MyPagerAdapter(this, views));

        //将页面缓存不回收

        mViewPager.setOffscreenPageLimit(4);

    }

 

}

总结三步:


1.设置视图源(你要展示的视图)


2.构造适配器(自定义MyPageraAdapter基础PagerAdapter)


3. 设置适配器(视图源和组件的连接)


4.自定义适配器

import android.content.Context;

import android.support.annotation.NonNull;

import android.support.v4.view.PagerAdapter;

import android.view.View;

import android.view.ViewGroup;

 

import java.util.List;

 

public class MyPagerAdapter extends PagerAdapter {

 

    //全局变量

    private Context context;

    private List<View> views;

 

    /**

     * 构造函数

     * 传入上下文和视图集合地址

     */

    public MyPagerAdapter(Context context, List<View> views) {

        //当前定义的context和views指向传进来的

        this.context = context;

        this.views = views;

    }

 

    /**

     * 1.获取view的数量

     *

     * @return

     */

    @Override

    public int getCount() {

        return views.size();

    }

 

    /**

     * instantiateItem方法中返回的视图是否等于这个对象

     * 以便下次再利用

     */

    @Override

    public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {

        return view == object;

    }

 

    /**

     * 实例化视图

     *

     * @param container

     * @param position

     * @return

     */

    @NonNull

    @Override

    public Object instantiateItem(@NonNull ViewGroup container, int position) {

        View child = views.get(position);//找到该位置的视图

        container.addView(child);//将视图加进去

        return child;//返回

    }

 

    /**

     * 释放视图

     * @param container 视图容器

     * @param position  位置

     * @param object    对象

     */

    @Override

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

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

    }

 

}

PageAdapter 必须重写的四个函数:


int getCount()  获取视图数量

boolean isViewFromObject(View view, Object object)  判断视图是否为当前对象,如果是即可以重新利用

void destroyItem(ViewGroup container, int position,Object object) 释放视图避免oom

Object instantiateItem(ViewGroup container, int position) 实例化视图

简单的效果




直接加载图片的做法:不需要创建布局


        views = new ArrayList<>();

        for (int index = 0; index < mLayoutIDs.length; index++) {

            //直接用图片视图

            //1.新建一个图片

            ImageView imageView = new ImageView(this);

            //2.给图片设置图片资源,如果想加载不同的图片,可以参考加载不同布局,设置一个图片数组

            imageView.setImageResource(R.mipmap.ic_launcher);

            //3.添加到list里面去

            views.add(imageView);

        }

三、使用ViewPager实现引导页

1.添加底部的引导点

在主布局xml中添加一个引导点的容器Linearlayout布局设置id为dot_layout


    <!--下方引导点的容器-->

    <LinearLayout

        android:id="@+id/dot_layout"

        android:layout_width="120dp"

        android:layout_height="30dp"

        android:layout_alignParentBottom="true"

        android:layout_centerHorizontal="true"

        android:layout_marginBottom="30dp"

        android:gravity="center"

        android:orientation="horizontal">

 

    </LinearLayout>

 

2.动态添加引导点

import android.support.v4.view.ViewPager;

import android.support.v7.app.AppCompatActivity;

import android.os.Bundle;

import android.view.View;

import android.view.ViewGroup;

import android.widget.ImageView;

import android.widget.LinearLayout;

 

import com.demo.viewpagerdemo.adapter.MyPagerAdapter;

 

import java.util.ArrayList;

import java.util.List;

 

public class MainActivity extends AppCompatActivity {

 

    //全局变量

    private ViewPager mViewPager;

    private int[] mLayoutIDs = {//每一个视图id数组

            R.layout.view_first,

            R.layout.view_second,

            R.layout.view_third,

            R.layout.view_four

    };

    private List<View> views;

    //装dot的容器

    private ViewGroup mDotViewGroup;

 

    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

        mViewPager = findViewById(R.id.id_viewpager);

        //初始化装dot的容器

        mDotViewGroup = findViewById(R.id.dot_layout);

        //初始化数据即视图

        views = new ArrayList<>();

        for (int index = 0; index < mLayoutIDs.length; index++) {

            //1.构造视图

            View view = getLayoutInflater().inflate(mLayoutIDs[index], null);

            views.add(view);

          //2.也可以直接用图片视图

//            ImageView imageView = new ImageView(this);

//            imageView.setImageResource(R.mipmap.ic_launcher);

//            views.add(imageView);

 

            //给dot视图添加图片

            ImageView dot = new ImageView(this);

            dot.setImageResource(R.mipmap.ic_launcher);

 

            //给每个dot通过代码来设置每个图片的参数 宽高为20

            LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(20, 20);

            layoutParams.leftMargin = 20;//每个距离左边20

            dot.setLayoutParams(layoutParams);//将这个代码的参数添加到dot这个图片里面

            dot.setEnabled(false);//不可点击

 

            //添加到dot视图集合中才能显示出来

            mDotViewGroup.addView(dot);

        }

        //设置adapter

        mViewPager.setAdapter(new MyPagerAdapter(this, views));

        //将页面缓存不回收

        mViewPager.setOffscreenPageLimit(4);

    }

 

}

增加一内容


1.设置dot的容器就是上面增加的linearlayout


    //装dot的容器

    private ViewGroup mDotViewGroup;


2.oncreate中初始化


        //初始化装dot的容器

        mDotViewGroup = findViewById(R.id.dot_layout);


 3.在循环中动态添加(有多少个页面就有多少个点)


        for (int index = 0; index < mLayoutIDs.length; index++) {

            //1.构造视图

            View view = getLayoutInflater().inflate(mLayoutIDs[index], null);

            views.add(view);

 

            //给dot视图添加图片

            ImageView dot = new ImageView(this);

            dot.setImageResource(R.mipmap.ic_launcher);

 

            //给每个dot通过代码来设置每个图片的参数 宽高为20

            LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(20, 20);

            layoutParams.leftMargin = 20;//每个距离左边20

            dot.setLayoutParams(layoutParams);//将这个代码的参数添加到dot这个图片里面

            dot.setEnabled(false);//不可点击

 

            //添加到dot视图集合中才能显示出来

            mDotViewGroup.addView(dot);

 

        }

实现效果:发现只是出现了响应的点而已,并不会随着页面显示而改变,怎么办?往下看3




3.实现翻页的监听

1. 设置方法

addOnPageChangeListener()


2. 翻页监听接口

ViewPager.OnPageChangeListener


3. 重写方法

onPageScrolled(int position, float positionOffset, int positionOffsetPixels)   //页面滑动状态停止前一直调用(滑动中)


position:当前点击滑动页面的位置 

positionOffset:当前页面偏移的百分比 

positionOffsetPixels:当前页面偏移的像素位置


 onPageSelected(int position)    //滑动后显示的页面和滑动前不同,调用(滑动的页面)


position:选中显示页面的位置


onPageScrollStateChanged(int state) //页面状态改变时调用(滑动的状态改变)


state:当前页面的状态


SCROLL_STATE_IDLE:空闲状态 

SCROLL_STATE_DRAGGING:滑动状态 

SCROLL_STATE_SETTLING:滑动后滑翔的状态


4. 使用

1.定义一个集合装要显示的dot


//设置dot的视图资源集合

private List<ImageView> mDotViews = new ArrayList<>();

2.在上面的for循环中将定义好的dot装进去


//将dot放到点集合中

mDotViews.add(dot);

3.设置滑动监听


只用到了OnpageSelected方法


       /**

         * 滑动监听

         */

        mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {

            //页面在滑动中

            @Override

            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

 

            }

            //选中的页面

            @Override

            public void onPageSelected(int position) {

                setDotView(position);

 

            }

            //页面的状态

            @Override

            public void onPageScrollStateChanged(int state) {

            }

        });

 

 

    }

setDotView的方法:参数是position当前的页面的位置,如果等于原来的图片的位置,就要更换成另外一张的图片


 

    private void setDotView(int position) {

        for (int index = 0; index < mDotViews.size(); index++) {

            //当页面滑到对应位置的图片时,对应位置的图片做出改变

            //使用的是三目运算符 如果==好为true执行第一个,否则执行第二个

            mDotViews.get(index).setImageResource(

                    position == index ? R.drawable.dot : R.mipmap.ic_launcher);

        }

    }

4.设置页面初始的位置在oncreate方法中


//设置初始是展示第一页的

mViewPager.setCurrentItem(0);

//对应的dot也是要显示出来

setDotView(0);

实现效果:




5.拓展 翻页动画:开源框架ViewPagerTransforms


要想实现选款的翻页效果


里面有十几种翻页动画,基本够用了 

Github地址:ViewPagerTransforms


四、使用ViewPager配合Fragment

参考:https://blog.csdn.net/weixin_39251617/article/details/79399592 


与Fragment结合使用其实也一样,只是用Fragment代替原先的View,填充Viewpager;然后就是Adapter不一样,配合Fragment使用的有两个Adapter:


FragmentPagerAdapter和FragmentStatePagerAdapter。


相同点: 

FragmentPagerAdapter和FragmentStatePagerAdapter都继承自PagerAdapter


不同点: 

卸载不再需fragment时,各自采用的处理方法有所不同

 


1.FragmentStatePagerAdapter会销毁不需要的fragment。


事务提交后, activity的FragmentManager中的fragment会被彻底移除。 FragmentStatePagerAdapter类名中的“state”表明:在销毁fragment时,可在onSaveInstanceState(Bundle)方法中保存fragment的Bundle信息。用户切换回来时,保存的实例状态可用来恢复生成新的fragment


2.FragmentPagerAdapter有不同的做法。


对于不再需要的fragment, FragmentPagerAdapter会选择调用事务的detach(Fragment)方法来处理它,而非remove(Fragment)方法。也就是说, FragmentPagerAdapter只是销毁了fragment的视图, fragment实例还保留在FragmentManager中。因此,FragmentPagerAdapter创建的fragment永远不会被销毁


也就是:在destroyItem()方法中,FragmentStatePagerAdapter调用的是remove()方法,适用于页面较多的情况;FragmentPagerAdapter调用的是detach()方法,适用于页面较少的情况。但是有页面数据需要刷新的情况,不管是页面少还是多,还是要用FragmentStatePagerAdapter,否则页面会因为没有重建得不到刷新


3.简单使用 


1.主页面布局xml fragment_viewpager.xml


<?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.support.v4.view.ViewPager

    android:id="@+id/id_fragment_viewpager"

    android:layout_width="match_parent"

    android:layout_height="match_parent">

 

</android.support.v4.view.ViewPager>

</LinearLayout>

2.fragment的fragment_test.xml布局


<?xml version="1.0" encoding="utf-8"?>

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

    android:layout_width="match_parent"

    android:layout_height="match_parent">

 

    <TextView

        android:layout_width="match_parent"

        android:layout_height="wrap_content"

        android:layout_centerInParent="true"

        android:gravity="center"

        android:text="我是fragment"

        android:textSize="36dp" />

</RelativeLayout>

3.Fragment创建的代码 TestFragment.java


import android.os.Bundle;

import android.support.annotation.NonNull;

import android.support.annotation.Nullable;

import android.support.v4.app.Fragment;

import android.view.LayoutInflater;

import android.view.View;

import android.view.ViewGroup;

 

public class TestFragment extends Fragment {

    @Nullable

    @Override

    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

        View view = inflater.inflate(R.layout.fragment_test, null);

        return view;

    }

}

4.主界面代码TabViewPagerAdapter.java


 

import android.os.Bundle;

import android.support.annotation.Nullable;

import android.support.v4.app.Fragment;

import android.support.v4.app.FragmentPagerAdapter;

import android.support.v4.view.ViewPager;

import android.support.v7.app.AppCompatActivity;

 

public class TabViewPagerAdapter extends AppCompatActivity {

 

    private ViewPager viewPager;

 

    @Override

    protected void onCreate(@Nullable Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.fragment_viewpager);

        viewPager = findViewById(R.id.id_fragment_viewpager);

        //设置 适配器

        viewPager.setAdapter(new FragmentPagerAdapter(getSupportFragmentManager())

        {

            @Override

            public Fragment getItem(int position) {

                //这是自定义的fragment

                return new TestFragment();

            }

 

            @Override

            public int getCount() {

                //定义数量

                return 4;

            }

        });

 

    }

}

 这样就可以实现了


效果:




5.给fragment传值


每次的页面都是一样的,怎么在不同的页面显示不同的东西呢?


简单实现:将每个fragment里面的textview显示当前的position


1.在FragmentPagerAdapter的getItem(int position)将position传到Fragment里面去显示


2.不建议直接在new testFragment()中传


3.在TestFragment中写一个获取Fragment实例的静态方法,同时将position传进去


具体实现:


TestFragment.java增加


一个创建实例并传参的方法 (setArguments)

一个oncreate接受传进来的参数(getArgument)

oncreate拿到参数后oncreateView显示

public class TestFragment extends Fragment {

 

    public static final String POSITION = "position";

    private String position;

    private TextView fragment_tv;

 

    /**

     * 在主界面中获取fragment的方法

     * 并且将position的传进来在对应的布局上显示

     *

     * @param position

     * @return

     */

    public static TestFragment newInstance(int position) {

        TestFragment fragment = new TestFragment();

        Bundle b = new Bundle();

        b.putInt(POSITION, position);

        fragment.setArguments(b);

        return fragment;

    }

 

    @Override

    public void onCreate(@Nullable Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        //接受传进来的值

        //setArguments 之后通过 getArguments来拿

        if (getArguments() != null) {

            //将int转成String以便显示

            position = String.valueOf(getArguments().getInt(POSITION));

        }

 

    }

 

    @Nullable

    @Override

    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

        View view = inflater.inflate(R.layout.fragment_test, null);

        fragment_tv = view.findViewById(R.id.fragment_tv);

        fragment_tv.setText(position);

        return view;

    }

}

 TabViewPagerAdapter.java代码中


设置适配器,的 getItem方法中返回的是


TestFragment.newInstance(position); 将position传到当前fragment中显示了


 viewPager.setAdapter(new FragmentPagerAdapter(getSupportFragmentManager()) {

            @Override

            public Fragment getItem(int position) {

                //这是自定义的fragment

                //position是当前fragment的位置

                return TestFragment.newInstance(position);

            }

 

            @Override

            public int getCount() {

                //定义数量

                return 4;

            }

        });

 具体效果:




 


五、结合上面的fragment案例实现底部导航和ViewPager联动效果



先了解一下TabHost


1. TabHost常用组件

TabWidget : 该组件就是TabHost标签页中上部 或者 下部的按钮, 可以点击按钮切换选项卡;


TabSpec : 代表了选项卡界面, 添加一个TabSpec即可添加到TabHost中;


-- 创建选项卡 : newTabSpec(String tag), 创建一个选项卡;


-- 添加选项卡 : addTab(tabSpec);


2. TabHost使用步骤

a. 定义布局 : 在XML文件中使用TabHost组件, 并在其中定义一个FrameLayout选项卡内容;


(下面的案例FrameLayout设置为不可见,因为它的是ViewPager,FragmentLayout就用不上了)


b. 继承TabActivity : 显示选项卡组件的Activity继承TabActivity;


c. 获取组件 : 通过调用getTabHost()方法, 获取TabHost对象;


d. 创建添加选项卡 : 通过TabHost创建添加选项卡;


 


1.主布局的xml要改变


底部的按钮是用tabHost来实现


tabHost作为根部局

添加tabWidget id命名要为@android:id/tabs

要想tabWidget显示还有加一个id 为@android:id/tabcontent 的FragmentLayout 设置为不可见就好

<?xml version="1.0" encoding="utf-8"?>

<TabHost 

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

    android:id="@+id/tab_host"

    android:layout_width="match_parent"

    android:layout_height="match_parent">

 

    <RelativeLayout

        android:layout_width="match_parent"

        android:layout_height="match_parent">

 

        <android.support.v4.view.ViewPager

            android:id="@+id/id_fragment_viewpager"

            android:layout_width="match_parent"

            android:layout_height="match_parent"

            android:layout_above="@id/tab_divider">

 

        </android.support.v4.view.ViewPager>

 

 

        <FrameLayout

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

            android:layout_width="match_parent"

            android:layout_height="match_parent"

            android:layout_above="@id/tab_divider"

            android:visibility="gone">

 

        </FrameLayout>

 

        <View

            android:id="@+id/tab_divider"

            android:layout_width="match_parent"

            android:layout_height="1dp"

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

            android:background="#000" />

 

        <!--tabhost 里面包含tabwidget-->

        <!--tabwidget要想显示必须有一个id为:

        @android:id/tabcontent的fragment-->

        <!--不设置分割线android:showDividers="none"-->

        <TabWidget

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

            android:layout_width="match_parent"

            android:layout_height="60dp"

            android:showDividers="none"

            android:layout_alignParentBottom="true">

 

        </TabWidget>

    </RelativeLayout>

</TabHost>

2.给每个TabWidget设置布局


TabWidget : 该组件就是TabHost标签页中上部 或者 下部的按钮, 可以点击按钮切换选项卡;


<?xml version="1.0" encoding="utf-8"?>

<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">

 

    <LinearLayout

        android:layout_width="match_parent"

        android:layout_height="match_parent"

        android:layout_centerInParent="true"

        android:gravity="center"

        android:orientation="vertical">

 

        <ImageView

            android:id="@+id/tab_img"

            android:layout_width="30dp"

            android:layout_height="30dp"

            android:layout_marginTop="4dp"

            android:background="@mipmap/ic_launcher" />

 

        <TextView

            android:id="@+id/tab_title"

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:layout_marginTop="5dp"

            tools:text="我是标题" />

 

    </LinearLayout>

</RelativeLayout>

3.给标题和按钮图片设置selector,要实现点击下变换颜色的效果


color_tab_txt.xml 在color目录下创建color_tab_txt.xml


<?xml version="1.0" encoding="utf-8"?>

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

    <!--选中的颜色-->

    <item android:color="#4dd0c8" android:state_selected="true" />

    <!--按下的颜色-->

    <item android:color="#4dd0c8" android:state_pressed="true" />

    <!--默认的颜色-->

    <item android:color="#dddd" />

</selector>

图片的selector:在drawable目录下创建tab_main_icon_home.xml


<?xml version="1.0" encoding="utf-8"?>

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

    <!--注意写的顺序,默认加载按顺序来的-->

    <item android:drawable="@drawable/tabbar_home_pressed" android:state_selected="true" />

    <item android:drawable="@drawable/tabbar_home_pressed" android:state_pressed="true" />

    <item android:drawable="@drawable/tabbar_home" />

 

</selector>

 其他两个类似


4.实现显示到主界面上


1.设置tab的标题数据、和图片icon

2.将设置好的数据利用循环来显示到tab上

3.实现联动效果是tab对viewpager进行监听和viewpager对tab进行监听

4.在TabHost添加选项卡有个setContent(this)是要实现接口的TabHost.TabContentFactory 返回一个空view即可以了

    private void initTabHost() {

        mTabHost = findViewById(R.id.tab_host);

        mTabHost.setup();

        //三个tab做出来

 

        //1.init data 设置标题的数据源,我这里定义在string里也可以直接写

        int[] titleIDs = {

                R.string.home,

                R.string.msg,

                R.string.me

        };

        //设置按钮图片的数据源(定义好的selector)

        int[] drawableIDs = {

                R.drawable.tab_main_icon_home,

                R.drawable.tab_main_icon_msg,

                R.drawable.tab_main_icon_me

        };

 

        //2、 data 显示到——>view上

        for (int index = 0; index < titleIDs.length; index++) {

            //这是每一个Tab的布局

            //解析成view

            View view = getLayoutInflater().inflate(R.layout.tab_layout, null, false);

            ImageView icon = view.findViewById(R.id.tab_img);

            TextView title = view.findViewById(R.id.tab_title);

            //设置图标资源

            icon.setImageResource(drawableIDs[index]);

            //设置标题资源

            title.setText(titleIDs[index]);

            //给每个Tag根部局设置背景色

            View tab = view.findViewById(R.id.tab_bg);

            tab.setBackgroundColor(getResources().getColor(R.color.white));

 

            //3。添加选项卡

            mTabHost.addTab(

                    mTabHost.newTabSpec(getString(titleIDs[index]))

                            .setContent(this)//要实现TabHost.TabContentFactory实现createTabContent方法

                            .setIndicator(view));

 

            //4.tab控制viewpager的显示

            //点击第几个tab就显示第几个viewpager

            mTabHost.setOnTabChangedListener(new TabHost.OnTabChangeListener() {

                @Override

                public void onTabChanged(String s) {

                    if (mTabHost != null) {

                        int position = mTabHost.getCurrentTab();

                        viewPager.setCurrentItem(position);

                    }

                }

            });

 

            //5.viewpager控制tab的显示

            viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {

                @Override

                public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

 

                }

 

                @Override

                public void onPageSelected(int position) {

                    //滑动到第几页就第几个tab就被选中

                    if (mTabHost != null) {

                        mTabHost.setCurrentTab(position);

                    }

                }

 

                @Override

                public void onPageScrollStateChanged(int state) {

 

                }

            });

 

        }

    }

 

    //返回的view就是addTab()里面的content,这里用不上这个view

    @Override

    public View createTabContent(String s) {

        View view = new View(this);

        return view;

    }

当然fragment也可以定义数组来显示(这里变成了字符串类型,之前是int类型要修改一下)


   // 三个fragment组成的viewpager

 

        final Fragment[] fragments = new Fragment[]{

                TestFragment.newInstance("home"),

                TestFragment.newInstance("message"),

                TestFragment.newInstance("me")

        };

返回这个数组让它对应就好 


 public Fragment getItem(int position) {

                return fragments[position];

            }

完整代码


import android.os.Bundle;

import android.support.annotation.Nullable;

import android.support.v4.app.Fragment;

import android.support.v4.app.FragmentPagerAdapter;

import android.support.v4.view.ViewPager;

import android.support.v7.app.AppCompatActivity;

import android.view.View;

import android.widget.ImageView;

import android.widget.TabHost;

import android.widget.TextView;

 

public class TabViewPagerAdapter extends AppCompatActivity implements TabHost.TabContentFactory {

 

    private ViewPager viewPager;

    private TabHost mTabHost;

 

    @Override

    protected void onCreate(@Nullable Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.fragment_viewpager);

        viewPager = findViewById(R.id.id_fragment_viewpager);

        //设置 适配器

        viewPager.setAdapter(new FragmentPagerAdapter(getSupportFragmentManager()) {

            @Override

            public Fragment getItem(int position) {

                //这是自定义的fragment

                //position是当前fragment的位置

                return TestFragment.newInstance(position);

            }

 

            @Override

            public int getCount() {

                //定义数量

                return 4;

            }

        });

        initTabHost();

 

    }

 

    private void initTabHost() {

        mTabHost = findViewById(R.id.tab_host);

        mTabHost.setup();

        //三个tab做出来

 

        //1.init data 设置标题的数据源,我这里定义在string里也可以直接写

        int[] titleIDs = {

                R.string.home,

                R.string.msg,

                R.string.me

        };

        //设置按钮图片的数据源(定义好的selector)

        int[] drawableIDs = {

                R.drawable.tab_main_icon_home,

                R.drawable.tab_main_icon_msg,

                R.drawable.tab_main_icon_me

        };

 

        //2、 data 显示到——>view上

        for (int index = 0; index < titleIDs.length; index++) {

            //这是每一个Tab的布局

            //解析成view

            View view = getLayoutInflater().inflate(R.layout.tab_layout, null, false);

            ImageView icon = view.findViewById(R.id.tab_img);

            TextView title = view.findViewById(R.id.tab_title);

            //设置图标资源

            icon.setImageResource(drawableIDs[index]);

            //设置标题资源

            title.setText(titleIDs[index]);

            //给每个Tag根部局设置背景色

            View tab = view.findViewById(R.id.tab_bg);

            tab.setBackgroundColor(getResources().getColor(R.color.white));

 

            //3。添加选项卡

            mTabHost.addTab(

                    mTabHost.newTabSpec(getString(titleIDs[index]))

                            .setContent(this)//要实现TabHost.TabContentFactory实现createTabContent方法

                            .setIndicator(view));

 

            //4.tab控制viewpager的显示

            //点击第几个tab就显示第几个viewpager

            mTabHost.setOnTabChangedListener(new TabHost.OnTabChangeListener() {

                @Override

                public void onTabChanged(String s) {

                    if (mTabHost != null) {

                        int position = mTabHost.getCurrentTab();

                        viewPager.setCurrentItem(position);

                    }

                }

            });

 

            //5.viewpager控制tab的显示

            viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {

                @Override

                public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

 

                }

 

                @Override

                public void onPageSelected(int position) {

                    //滑动到第几页就第几个tab就被选中

                    if (mTabHost != null) {

                        mTabHost.setCurrentTab(position);

                    }

                }

 

                @Override

                public void onPageScrollStateChanged(int state) {

 

                }

            });

 

        }

    }

 

    //返回的view就是addTab()里面的content,这里用不上这个view

    @Override

    public View createTabContent(String s) {

        View view = new View(this);

        return view;

    }

}

 完成.


TabHost用起来很麻烦,推荐BottomNavigationView



©小网格工作室 2013-2025