目录
2.3 重写FragmentPagerAdapter的两个方法
3.10 重写FragmentPagerAdapter的两个方法
1 初级版
ViewPager通过滑动来切换Fragment,无底部导航栏。
用法:数据List<Fragment>+适配器FragmentPagerAdapter+ViewPager
通过FragmentPagerAdapter连接两者的桥梁,里面需要重写两个方法getItem,getCount。
第一个方法是获取一个Fragment,从数据源获取。
第二个方法是获取数据源的大小,也就是有几页。
1.1 XML布局文件添加ViewPager
在Activity的XML布局文件中添加一个控件——ViewPager。
加入宽高和ID即可。
在Java代码中找控件ViewPager。
1.2 Java代码创建Adapter类
继承自FragmentPagerAdapter类,重写两个方法getItem,getCount。
public class MyFragmentVPAdapter extends FragmentPagerAdapter {
private List<Fragment> fragmentList;
public MyFragmentVPAdapter(@NonNull FragmentManager fm,List<Fragment> list) {
super(fm);
this.fragmentList=list;
}
@NonNull
@Override
public Fragment getItem(int position) {
return fragmentList==null?null:fragmentList.get(position);
}
@Override
public int getCount() {
return fragmentList==null?0:fragmentList.size();
}
}
1.2.1 重写方法getItem
获取数据源的位置
public Fragment getItem(int position){
return mFragmentList==null?null:mFragmentList.get(position);
}
1.2.2 重写方法getCount
获取数据源的个数
public int getCount(){
return mFragmentList==null?0:mFragmentList.size();
}
1.2.3 适配器构造器
需要传入一个FragmentManager对象和数据源。
1.3 创建Fragment
也是只有一个文本TextView,new的时候传入一个参数来更改文本。
1.4 Java主代码
声明数据源List<Fragment>,实例化适配器。
1.4.1 数据源添加数据
实例化Fragment,用newInstance()。并add到List中。
1.4.2实例化适配器
传入两个参数,getSupportFragmentManager()即可获取FragmentManager对象,数据源。
1.4.3给ViewPager添加适配器
setAdapter即可。
1.4.4 给ViewPager添加监听事件
addOnPageChangeListener(),其中可以设置比如让底部导航栏变色。
2 中级版
ViewPager通过滑动来切换Fragment,有普通的底部导航栏,故也可以通过底部导航栏切换fragment。
用法:ViewPager+FragmentPagerAdapter+普通ButtonView
ViewPager用法+FragmentPagerAdapter的用法+ViewPager和底部导航栏的联动
就是要写很多控件,还要找,比较麻烦。
2.1 XML布局文件添加ViewPager
在Activity的XML布局文件中添加一个控件——ViewPager。
加入宽高和ID即可。
在Java代码中找控件ViewPager。
2.2 Java代码创建Adapter类
继承自FragmentPagerAdapter类,重写两个方法getItem,getCount。
2.3 重写FragmentPagerAdapter的两个方法
同上1.2。
2.4 创建Fragment
也是只有一个文本TextView,new的时候传入一个参数来更改文本。
2.5 Java主代码
声明数据源List<Fragment>,实例化适配器。
2.5.1 数据源添加数据
实例化Fragment,用newInstance()。并add到List中。
2.5.2 实例化适配器
传入两个参数,getSupportFragmentManager()即可获取FragmentManager对象,数据源。
2.5.3 给ViewPager添加适配器
setAdapter即可。
2.6 ViewPager和底部导航栏的联动
当切换页面的时候,把底部导航相应的状态给改变一下。通过ViewPager的addOnPageChangeListener的三个回调。
当点击底部导航时,把Fragment的页面给切换一下。通过线性布局的按钮点击事件的回调。
3 高级版
ViewPager通过滑动来切换Fragment,底部导航栏换成了ButtonNavigationView,故也可以通过底部导航栏切换fragment。
就是在中级版的基础上,把普通按钮换成了另外一个控件ButtonNavigationView,这个控件更加方便。
用法:ViewPager+FragmentPagerAdapter+ButtonNavigationView实现底部导航页
ViewPager用法+FragmentPagerAdapter用法+ButtonNavigationView用法+ViewPager切换页面和ButtonNavigationView的联动+Badge用法(新消息提示)。
3.1 ViewPager用法
数据List<>+适配器FragmentPagerAdapter+ViewPager
3.2 FragmentPagerAdapter用法
继承自FragmentPagerAdapter类,重写两个方法getItem,getCount。
同上1.2。
3.3 ButtonNavigationView用法
有两个重要的属性app:menu(声明导航按钮)和app:labelVisibility(导航按钮的显示模式,有4个值可选)
labeled(一直显示文字),unlabeled(不显示文字),selected(选中显示文字),auto(自动:小于三个按钮取labeled;大于三个按钮取selected)。
3.4 ViewPager切换页面和ButtonNavigationView的联动
3.4.1 ViewPager联动ButtonNavigationView
当ViewPager发生变化时,底部按钮要发生变化
mViewPager.addOnPageChangeListener(...)
mBottomNavigationView.setSelectedItemId(R.id.menu_xxx)
3.4.2 ButtonNavigationView联动ViewPager
当点击按钮时,ViewPager要发生变化
mBottomNavigationView.setOnItemSelectedListener(...)
mViewPager.setCurrentItem(index)
3.4.3 Badge用法(新消息提示)
创建Badge
//新消息加到菜单中哪个icon中,注册
BadgeDrawable badge=mBottomNavigationView.getOrCreateBadge(R.id.menu_xxx);
设置消息数
//默认是4个字符,只能999+
badge.setNumber(949);
//代表只能容下3个字符,99+
//若是4,则是999+
badge.setMaxCharacterCount(3);
到达页面移除badge
mBottomNavigationView.removeBadge(R.id.menu_xxx);
开始写代码咯!
3.5
3.6 创建菜单menu
之前的博客有写,直接创建选项菜单即可。可以在icon选取一个selected选择器,有按下和不按的两种图标状态。我这里没有设置选择器,只有一个icon而已。
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/like"
android:icon="@drawable/like"
android:title="喜欢"/>
<item android:id="@+id/local"
android:icon="@drawable/local"
android:title="定位"/>
<item android:id="@+id/report"
android:icon="@drawable/report"
android:title="举报"/>
<item android:id="@+id/share"
android:icon="@drawable/share"
android:title="分享"/>
</menu>
3.7 XML布局文件添加ViewPager和ButtonNavigationView
最基础的是设置宽高和Id,如果没有ButtonNavigationView控件,可能是没有导入依赖"com.google.android.material:material:1.2.1"。
ViewPager额外设置权重weight属性。
ButtonNavigationView额外设置app:menu和app:labelVisibility。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<androidx.viewpager.widget.ViewPager
android:id="@+id/vp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1" />
<com.google.android.material.bottomnavigation.BottomNavigationView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/btm_nav"
app:menu="@menu/btm_menu"
app:labelVisibilityMode="labeled"/>
</LinearLayout>
3.8 Java主代码获取控件
找两个控件即可。
public class MainActivity extends AppCompatActivity {
private ViewPager viewPager;
private BottomNavigationView mBottomNavigationView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mBottomNavigationView = findViewById(R.id.btm_nav);
viewPager = findViewById(R.id.vp);
}
}
3.9 Java代码创建Adapter类
继承自FragmentStatePagerAdapter类,这个类会回收划掉的页面,而前面那个FragmentPagerAdapter不会回收,会在后台占据着内存,使用方面是一样的。
3.10 重写FragmentPagerAdapter的两个方法
重写getItem,getCount。同上1.2。
3.11 适配器构造器
设置一个传入FragmentManager对象和数据源的构造器。
3.12 创建Fragment
3.12.1 XML文件
也是只有一个文本TextView,new的时候传入一个参数来更改文本。
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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=".viewPagerFragment">
<TextView
android:id="@+id/tv_1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:textSize="25dp"
android:text="@string/hello_blank_fragment" />
</FrameLayout>
3.12.2 Java文件
通过传入参数来更改文本
public class viewPagerFragment extends Fragment {
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
private String mParam1;
private String mParam2;
private TextView textView;
public viewPagerFragment() {
}
public static viewPagerFragment newInstance(String param1, String param2) {
viewPagerFragment fragment = new viewPagerFragment();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_view_pager, container, false);
}
@Override
public void onViewCreated(@NonNull View view,
@Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
textView= view.findViewById(R.id.tv_1);
if(TextUtils.isEmpty(mParam1)){
textView.setText(mParam1);
}
}
}
3.13 Java主代码
声明数据源List<Fragment>,实例化适配器。
List<Fragment> list=new ArrayList<>();
3.13.1 数据源添加数据
实例化Fragment,用newInstance()。并add到List中。
private void initData() {
viewPagerFragment viewPagerFragmenthome=viewPagerFragment.newInstance("首页","");
viewPagerFragment viewPagerFragmentfind=viewPagerFragment.newInstance("发现","");
viewPagerFragment viewPagerFragmentmine=viewPagerFragment.newInstance("我的","");
list.add(viewPagerFragmenthome);
list.add(viewPagerFragmentfind);
list.add(viewPagerFragmentmine);
}
3.13.2 实例化适配器
传入两个参数,getSupportFragmentManager()即可获取FragmentManager对象,数据源。
myFragmentVPAdapter = new MyFragmentVPAdapter(getSupportFragmentManager(), list);
3.13.3 给ViewPager添加适配器
setAdapter即可。
viewPager.setAdapter(myFragmentVPAdapter);
3.13.4 给ViewPager添加监听事件
addOnPageChangeListener(),其中可以设置比如让底部导航栏变色。
mViewPager.addOnPageChangeListener(...)
mBottomNavigationView.setSelectedItemId(R.id.menu_xxx)
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
switch(position){
case 0:
mBottomNavigationView.setSelectedItemId(R.id.like);
break;
case 1:
mBottomNavigationView.setSelectedItemId(R.id.local);
break;
case 2:
mBottomNavigationView.setSelectedItemId(R.id.report);
break;
case 3:
mBottomNavigationView.setSelectedItemId(R.id.share);
break;
}
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
写在第二个回调onPageSelected(),然后设置某个icon被选中即可,不需要再取消其他icon的选中状态,这个控件选中其中一个,另外的icon就会被取消,这就是ButtonNavigationView的好处。
3.13.5 给ButtonNavigationView添加监听事件
mBottomNavigationView.setOnItemSelectedListener(),可以让ViewPager切换页面。
//旧方法,已经废弃
mBottomNavigationView.setOnItemSelectedListener(...)
//设置ViewPager
mViewPager.setCurrentItem(index)
//我们这里不用废弃的旧方法,用setOnItemSelectedListener
mBottomNavigationView.setOnItemSelectedListener(new NavigationBarView.OnItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
switch(item.getItemId()){
case R.id.like:
viewPager.setCurrentItem(0);
break;
case R.id.local:
viewPager.setCurrentItem(1);
break;
case R.id.report:
viewPager.setCurrentItem(2);
break;
case R.id.share:
viewPager.setCurrentItem(3);
break;
default:
break;
}
return true;
}
});
3.14 Badge的设置
3.14.1 Badge的添加
BadgeDrawable badgeDrawable=mBottomNavigationView.getOrCreateBadge(R.id.like);
badgeDrawable.setNumber(888);
badgeDrawable.setMaxCharacterCount(3);
3.14.2 Badge的移除
在ViewPager的页面监听事件中获取信息,如果到达这个页面的话就移除。
mBottomNavigationView.removeBadge(R.id.like);
最后,上Activity的主代码~
package com.example.fragmentviewpager;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.viewpager.widget.ViewPager;
import android.os.Bundle;
import android.view.MenuItem;
import android.view.View;
import com.google.android.material.badge.BadgeDrawable;
import com.google.android.material.bottomnavigation.BottomNavigationView;
import com.google.android.material.navigation.NavigationBarView;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private ViewPager viewPager;
private BottomNavigationView mBottomNavigationView;
private MyFragmentVPAdapter myFragmentVPAdapter;
List<Fragment> list=new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mBottomNavigationView = findViewById(R.id.btm_nav);
viewPager = findViewById(R.id.vp);
initData();
myFragmentVPAdapter = new MyFragmentVPAdapter(getSupportFragmentManager(), list);
viewPager.setAdapter(myFragmentVPAdapter);
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
switch(position){
case 0:
mBottomNavigationView.removeBadge(R.id.like);
mBottomNavigationView.setSelectedItemId(R.id.like);
break;
case 1:
mBottomNavigationView.setSelectedItemId(R.id.local);
break;
case 2:
mBottomNavigationView.setSelectedItemId(R.id.report);
break;
case 3:
mBottomNavigationView.setSelectedItemId(R.id.share);
break;
}
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
mBottomNavigationView.setOnItemSelectedListener(new NavigationBarView.OnItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
switch(item.getItemId()){
case R.id.like:
viewPager.setCurrentItem(0);
break;
case R.id.local:
viewPager.setCurrentItem(1);
break;
case R.id.report:
viewPager.setCurrentItem(2);
break;
case R.id.share:
viewPager.setCurrentItem(3);
break;
default:
break;
}
return true;
}
});
BadgeDrawable badgeDrawable=mBottomNavigationView.getOrCreateBadge(R.id.like);
badgeDrawable.setNumber(888);
badgeDrawable.setMaxCharacterCount(3);
}
private void initData() {
viewPagerFragment viewPagerFragmenthome=viewPagerFragment.newInstance("首页","");
viewPagerFragment viewPagerFragmentfind=viewPagerFragment.newInstance("发现","");
viewPagerFragment viewPagerFragmentmine=viewPagerFragment.newInstance("我的","");
list.add(viewPagerFragmenthome);
list.add(viewPagerFragmentfind);
list.add(viewPagerFragmentmine);
}
}