借鉴: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