ViewPager+Fragment

①导包

在项目的gradle文件中引入ViewPager2的依赖包

1
implementation 'androidx.viewpager2:viewpager2:1.0.0'

②创建布局

在activity_main.xml布局中添加ViewPager2控件

1
2
3
4
5
6
7
8
9
10
11
12
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:orientation="vertical"
android:gravity="center_horizontal">
<androidx.viewpager2.widget.ViewPager2
android:layout_width="match_parent"
android:id="@+id/viewPager2"
android:layout_height="0dp"
android:layout_weight="1"/>
</LinearLayout>

③创建Fragment

新建一个空白的Fragment,并在BlankFragment.java中对代码进行优化

BlankFragment.java优化

下面代码,调用BlankFragment类的newInstance创建Fragment对象时,必会用Bundle传输数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
import android.os.Bundle;
import androidx.fragment.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

public class BlankFragment extends Fragment {
private TextView blanFragment_text1;
private View viewRoot;
// 接收Bandle消息所用的key
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";

// 接收Bandle后储存值mParam1和mParam2
private String mParam1;
private int mParam2;

// 无参构造器
public BlankFragment() {
// Required empty public constructor
}

// 调用该方法newInstance时会创建一个新的BlankFragment并返回,传入的两个值既是Bundle要发送的数据
public static BlankFragment newInstance(String param1, int param2) {
// 创建BlankFragment对象
BlankFragment fragment = new BlankFragment();
// Bundle数据传输
Bundle args = new Bundle();
// 设置两个传输值和key
args.putString(ARG_PARAM1, param1);
args.putInt(ARG_PARAM2, param2);
// 附加给BlankFragment对象
fragment.setArguments(args);
return fragment;
}

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 如果传入了Bundle值,则取出
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getInt(ARG_PARAM2);
}
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
if (viewRoot == null){
viewRoot = inflater.inflate(R.layout.fragment_blank, container, false);
}
// 对页面上的TextView作出修改
blanFragment_text1 = viewRoot.findViewById(R.id.blanFragment_text1);
blanFragment_text1.setText(mParam1+";页码:" + mParam2);

return viewRoot;
}
}

fragment_blank.xml修改

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout android:layout_height="match_parent"
android:layout_width="match_parent"
android:orientation="vertical"
android:gravity="center"
xmlns:android="http://schemas.android.com/apk/res/android">
<TextView
android:text="文本"
android:textSize="20sp"
android:textStyle="bold"
android:textColor="@color/black"
android:id="@+id/blanFragment_text1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>

④创建适配器

ViewPager中的FragmentPagerAdapter和FragmentStatePagerAdapter的区别

Jetpack和它的Lifecycle组件

MyAdapter继承自FragmentStateAdapter(不是FragmentPagerAdapter或FragmentStatePagerAdapter)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.lifecycle.Lifecycle;
import androidx.viewpager2.adapter.FragmentStateAdapter;

import java.util.ArrayList;

public class MyAdapter extends FragmentStateAdapter {
// 接收Fragment集合
private ArrayList<Fragment> fragments;
// 需要三个参数:getSupportFragmentManager()管理、Lifecycle是Jetpack中提供的一个用于感知生命周期的组件、fragment集合
public MyAdapter(@NonNull FragmentManager fragmentManager, @NonNull Lifecycle lifecycle,ArrayList<Fragment> fragments) {
super(fragmentManager, lifecycle);
this.fragments = fragments;
}

@NonNull
@Override
// 创建Fragment
public Fragment createFragment(int position) {
return fragments.get(position);
}

@Override
// 获取页面总数
public int getItemCount() {
return fragments.size();
}
}

⑤调用适配器

在MainActivity中调用适配器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.viewpager2.widget.ViewPager2;
import android.os.Bundle;
import java.util.ArrayList;

public class MainActivity extends AppCompatActivity {
private ViewPager2 viewPager2;
private ArrayList<Fragment> fragments;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

viewPager2 = findViewById(R.id.viewPager2);
fragments = new ArrayList<>();

// 添加Fragment
fragments.add(BlankFragment.newInstance("微信",0));
fragments.add(BlankFragment.newInstance("通讯录",1));
fragments.add(BlankFragment.newInstance("发现",2));
fragments.add(BlankFragment.newInstance("我",3));

// 传入三个参数:getSupportFragmentManager()管理、Lifecycle是Jetpack中提供的一个用于感知生命周期的组件、fragment集合
MyAdapter myAdapter = new MyAdapter(getSupportFragmentManager(),getLifecycle(),fragments);
viewPager2.setAdapter(myAdapter);
}
}

⑥当前效果

⑦创建首页的顶部导航和底部按钮

创建selected布局

1
2
3
4
5
6
7
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 未被选中时-->
<item android:drawable="@drawable/main_weixin" android:state_selected="false"/>
<!-- 被选中时-->
<item android:drawable="@drawable/main_weixin_true" android:state_selected="true"/>
</selector>

main_top.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout android:layout_height="60dp"
android:layout_width="match_parent"
android:background="#FFEDEDED"
xmlns:android="http://schemas.android.com/apk/res/android">
<LinearLayout
android:layout_width="match_parent"
android:orientation="vertical"
android:gravity="center"
android:layout_height="match_parent">
<TextView
android:text="page name"
android:id="@+id/main_top_text1"
android:textStyle="bold"
android:textColor="@color/black"
android:textSize="20sp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignParentRight="true"
android:gravity="center"
android:orientation="horizontal">
<ImageView
android:layout_width="30dp"
android:layout_height="30dp"
android:src="@mipmap/ic_launcher"/>
<ImageView
android:layout_marginRight="10dp"
android:layout_marginLeft="10dp"
android:layout_width="30dp"
android:layout_height="30dp"
android:src="@mipmap/ic_launcher"/>
</LinearLayout>
</RelativeLayout>

main_bottom.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout android:layout_height="60dp"
android:layout_width="match_parent"
android:orientation="horizontal"
android:background="#FFEDEDED"
xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 微信-->
<LinearLayout
android:layout_width="0dp"
android:layout_weight="1"
android:orientation="vertical"
android:gravity="center"
android:id="@+id/main_bottom_button0"
android:layout_height="match_parent">
<ImageView
android:id="@+id/main_bottom_img0"
android:layout_width="30dp"
android:layout_height="30dp"
android:src="@drawable/main_weixin_selected"/>
<TextView
android:text="name"
android:textColor="@color/black"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
<!-- 联系人-->
<LinearLayout
android:layout_width="0dp"
android:layout_weight="1"
android:orientation="vertical"
android:gravity="center"
android:id="@+id/main_bottom_button1"
android:layout_height="match_parent">
<ImageView
android:layout_width="30dp"
android:layout_height="30dp"
android:id="@+id/main_bottom_img1"
android:src="@drawable/main_lianxiren_selected"/>
<TextView
android:text="name"
android:textColor="@color/black"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
<!-- 发现-->
<LinearLayout
android:layout_width="0dp"
android:layout_weight="1"
android:orientation="vertical"
android:gravity="center"
android:id="@+id/main_bottom_button2"
android:layout_height="match_parent">
<ImageView
android:layout_width="30dp"
android:layout_height="30dp"
android:id="@+id/main_bottom_img2"
android:src="@drawable/main_faxian_selected"/>
<TextView
android:text="name"
android:textColor="@color/black"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
<!-- 我-->
<LinearLayout
android:layout_width="0dp"
android:layout_weight="1"
android:orientation="vertical"
android:gravity="center"
android:id="@+id/main_bottom_button3"
android:layout_height="match_parent">
<ImageView
android:layout_width="30dp"
android:layout_height="30dp"
android:id="@+id/main_bottom_img3"
android:src="@drawable/main_wo_selected"/>
<TextView
android:text="name"
android:textColor="@color/black"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
</LinearLayout>

以组件的方式将main_top.xml和main_bottom.xml添加至activity_main.xml中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:orientation="vertical"
android:gravity="center_horizontal">
<!-- 顶部-->
<include layout="@layout/main_top"/>
<androidx.viewpager2.widget.ViewPager2
android:layout_width="match_parent"
android:id="@+id/viewPager2"
android:layout_height="0dp"
android:layout_weight="1"/>
<!-- 底部-->
<include layout="@layout/main_bottom"/>
</LinearLayout>

页面切换监听

给ViewPager2添加registerOnPageChangeCallback页面切换监听事件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
//        页面切换监听
viewPager2.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
@Override
// 翻新页和ViewPager首次加载时调用
// 当position=当前页码-1时,说明向前翻页,当前偏移的像素位置(屏幕大小决定)positionOffsetPixels从max-0,当前页面偏移比例positionOffset从100%-0%
// 当position等于当前页码时,说明向后翻页,当前偏移的像素位置(屏幕大小决定)positionOffsetPixels从0-max,当前页面偏移比例positionOffset从0%-100%
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
super.onPageScrolled(position, positionOffset, positionOffsetPixels);
// Log.d("xin", "onPageScrolled: 页码," + position + ";偏移像素," + positionOffsetPixels + ";偏移比例," + positionOffset);
}

@Override
// 翻新页和ViewPager首次加载时调用
// position=当前页码
public void onPageSelected(int position) {
super.onPageSelected(position);
// Log.d("xin", "onPageSelected: " + position);
main_top_text1.setText(pageName[position]);//设置首页page name
pageSlide(position);//设置不同页面时底部按钮的展示状态
}

@Override
// 手指触碰屏幕时调用
// state=1时手指触碰屏幕,state=2时手指离开屏幕,state=0时滑动结束
public void onPageScrollStateChanged(int state) {
super.onPageScrollStateChanged(state);
// Log.d("xin", "onPageScrollStateChanged: " + state);
}
});

该方法响应页面切换监听事件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
private void pageSlide(int position){
if (main_bottom_temp == null){
main_bottom_img0.setSelected(true);
main_bottom_temp = main_bottom_img0;
}
else{
main_bottom_temp.setSelected(false);
switch (position){
case 0:
main_bottom_img0.setSelected(true);
main_bottom_temp = main_bottom_img0;
break;
case 1:
main_bottom_img1.setSelected(true);
main_bottom_temp = main_bottom_img1;
break;
case 2:
main_bottom_img2.setSelected(true);
main_bottom_temp = main_bottom_img2;
break;
case 3:
main_bottom_img3.setSelected(true);
main_bottom_temp = main_bottom_img3;
break;
}
}
}

单击底部按钮时切换页面

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
    @Override
// ViewPager2切换页面
public void onClick(View v) {
switch (v.getId()){
case R.id.main_bottom_button0:
viewPager2.setCurrentItem(0);
break;
case R.id.main_bottom_button1:
viewPager2.setCurrentItem(1);
break;
case R.id.main_bottom_button2:
viewPager2.setCurrentItem(2);
break;
case R.id.main_bottom_button3:
viewPager2.setCurrentItem(3);
break;
}
}

MainActivity.java全部代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.viewpager2.widget.ViewPager2;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import java.util.ArrayList;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private String[] pageName = new String[]{"微信","通讯录","发现","我"};
private ViewPager2 viewPager2;//ViewPager2
private TextView main_top_text1;//首页顶部的page name
// 底部所有按钮的图片
private ImageView main_bottom_img0,main_bottom_img1,main_bottom_img2,main_bottom_img3,main_bottom_temp;
// 底部按钮
private LinearLayout main_bottom_button0,main_bottom_button1,main_bottom_button2,main_bottom_button3;
private ArrayList<Fragment> fragments;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

viewPager2 = findViewById(R.id.viewPager2);
fragments = new ArrayList<>();

// 添加Fragment
fragments.add(BlankFragment.newInstance(pageName[0],0));
fragments.add(BlankFragment.newInstance(pageName[1],1));
fragments.add(BlankFragment.newInstance(pageName[2],2));
fragments.add(BlankFragment.newInstance(pageName[3],3));
// 获取底部所有按钮图
main_bottom_img0 = findViewById(R.id.main_bottom_img0);
main_bottom_img1 = findViewById(R.id.main_bottom_img1);
main_bottom_img2 = findViewById(R.id.main_bottom_img2);
main_bottom_img3 = findViewById(R.id.main_bottom_img3);
// 获取底部四个子LinearLayout作为按钮
main_bottom_button0 = findViewById(R.id.main_bottom_button0);
main_bottom_button1 = findViewById(R.id.main_bottom_button1);
main_bottom_button2 = findViewById(R.id.main_bottom_button2);
main_bottom_button3 = findViewById(R.id.main_bottom_button3);

// 设置click事件,点击时ViewPager2切换页面
main_bottom_button0.setOnClickListener(this);
main_bottom_button1.setOnClickListener(this);
main_bottom_button2.setOnClickListener(this);
main_bottom_button3.setOnClickListener(this);

main_top_text1 = findViewById(R.id.main_top_text1);//首页顶部的page name

// 传入三个参数:getSupportFragmentManager()管理、Lifecycle是Jetpack中提供的一个用于感知生命周期的组件、fragment集合
MyAdapter myAdapter = new MyAdapter(getSupportFragmentManager(),getLifecycle(),fragments);
viewPager2.setAdapter(myAdapter);

// 页面切换监听
viewPager2.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
@Override
// 翻新页和ViewPager首次加载时调用
// 当position=当前页码-1时,说明向前翻页,当前偏移的像素位置(屏幕大小决定)positionOffsetPixels从max-0,当前页面偏移比例positionOffset从100%-0%
// 当position等于当前页码时,说明向后翻页,当前偏移的像素位置(屏幕大小决定)positionOffsetPixels从0-max,当前页面偏移比例positionOffset从0%-100%
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
super.onPageScrolled(position, positionOffset, positionOffsetPixels);
// Log.d("xin", "onPageScrolled: 页码," + position + ";偏移像素," + positionOffsetPixels + ";偏移比例," + positionOffset);
}

@Override
// 翻新页和ViewPager首次加载时调用
// position=当前页码
public void onPageSelected(int position) {
super.onPageSelected(position);
// Log.d("xin", "onPageSelected: " + position);
main_top_text1.setText(pageName[position]);//设置首页page name
pageSlide(position);//设置不同页面时底部按钮的展示状态
}

@Override
// 手指触碰屏幕时调用
// state=1时手指触碰屏幕,state=2时手指离开屏幕,state=0时滑动结束
public void onPageScrollStateChanged(int state) {
super.onPageScrollStateChanged(state);
// Log.d("xin", "onPageScrollStateChanged: " + state);
}
});
}

private void pageSlide(int position){
if (main_bottom_temp == null){
main_bottom_img0.setSelected(true);
main_bottom_temp = main_bottom_img0;
}
else{
main_bottom_temp.setSelected(false);
switch (position){
case 0:
main_bottom_img0.setSelected(true);
main_bottom_temp = main_bottom_img0;
break;
case 1:
main_bottom_img1.setSelected(true);
main_bottom_temp = main_bottom_img1;
break;
case 2:
main_bottom_img2.setSelected(true);
main_bottom_temp = main_bottom_img2;
break;
case 3:
main_bottom_img3.setSelected(true);
main_bottom_temp = main_bottom_img3;
break;
}
}
}

@Override
// ViewPager2切换页面
public void onClick(View v) {
switch (v.getId()){
case R.id.main_bottom_button0:
viewPager2.setCurrentItem(0);
break;
case R.id.main_bottom_button1:
viewPager2.setCurrentItem(1);
break;
case R.id.main_bottom_button2:
viewPager2.setCurrentItem(2);
break;
case R.id.main_bottom_button3:
viewPager2.setCurrentItem(3);
break;
}
}
}

当前效果

累死了,就到这儿吧,源代码下载(不包含.gradle和.idea文件夹)