ViewPager和Fragment使用(附源码)

简介: 1 初级版ViewPager通过滑动来切换Fragment,无底部导航栏。用法:数据List<Fragment>+适配器FragmentPagerAdapter+ViewPager通过FragmentPagerAdapter连接两者的桥梁,里面需要重写两个方法getItem,getCount。第一个方法是获取一个Fragment,从数据源获取。第二个方法是获取数据源的大小,也就是有几页。

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);
    }
}


目录
相关文章
|
5月前
|
Android开发 容器
35. 【Android教程】视频页面:ViewPager
35. 【Android教程】视频页面:ViewPager
58 3
|
Android开发 UED 开发者
两种方法,教你解决 ViewPager 嵌套 ViewPager滑动冲突(二)
两种方法,教你解决 ViewPager 嵌套 ViewPager滑动冲突
|
存储 Android开发
android ViewPager + Fragment + Tablayout 实现嵌套页面导航(二)
android ViewPager + Fragment + Tablayout 实现嵌套页面导航
android ViewPager + Fragment + Tablayout 实现嵌套页面导航(二)
|
编译器 Android开发 容器
android ViewPager + Fragment + Tablayout 实现嵌套页面导航(一)
android ViewPager + Fragment + Tablayout 实现嵌套页面导航
android ViewPager + Fragment + Tablayout 实现嵌套页面导航(一)
|
安全
Fragment里面有ViewPager,ViewPager里面又嵌套Fragment,刚遇到的一个坑
Fragment里面有ViewPager,ViewPager里面又嵌套Fragment,刚遇到的一个坑
|
Android开发 iOS开发
Android底部导航——BottomNavigationView+ViewPager+Fragment
Android底部导航——BottomNavigationView+ViewPager+Fragment
466 0
Android底部导航——BottomNavigationView+ViewPager+Fragment
|
Android开发
Android笔记:viewPager+fragment实现循环滚动
Android笔记:viewPager+fragment实现循环滚动
197 0
|
Java Android开发
Android Studio 使用ViewPager + Fragment实现滑动菜单Tab效果 --简易版
描述:         之前有做过一个记账本APP,拿来练手的,做的很简单,是用Eclipse开发的;         最近想把这个APP重新完善一下,添加了一些新的功能,并选用Android Studio来开发;         APP已经完善了一部分,现在就想把已经做好的功能整理一下,记录下来。
2982 0
|
Android开发
Android ViewPager嵌套Fragment出现白页面
解决ViewPager嵌套Fragment页面白屏 viewPager.setOffscreenPageLimit(Fragment的数量);
1562 0