布局管理器允许左右翻转带数据的页面,你想要显示的视图可以通过实现PagerAdapter来显示。这个类其实是在早期设计和开发的,它的API在后面的更新之中可能会被改变,当它们在新版本之中编译的时候可能还会改变源码。
ViewPager经常用来连接Fragment,它很方便管理每个页面的生命周期,使用ViewPager管理Fragment是标准的适配器实现。最常用的实现一般有FragmentPagerAdapter和FragmentStatePagerAdapter。
ViewPager是android扩展包v4包中的类,这个类可以让我们左右切换当前的view。我们先来聊聊ViewPager的几个相关知识点:
1、ViewPager类直接继承了ViewGroup类,因此它一个容器类,可以添加其他的view类2、ViewPager类需要一个PagerAdapter适配器类给它提供数据(这点跟ListView一样需要数据适配器Adater)3、ViewPager经常和Fragment一起使用,并且官方还提供了专门的FragmentPagerAdapterFragmentStatePagerAdapter类供Fragment中的ViewPager使用二、什么是ViewPager2原理: viewpager2 内部实现原理是使用recycleview加LinearLayoutManager实现竖直滚动,其实可以理解为对recyclerview的二次封装
private void initialize(Context context, AttributeSet attrs) { mAccessibilityProvider = sFeatureEnhancedA11yEnabled ? new PageAwareAccessibilityProvider() : new BasicAccessibilityProvider(); // 实例化recycleview对象 mRecyclerView = new RecyclerViewImpl(context); mRecyclerView.setId(ViewCompat.generateViewId()); mRecyclerView.setDescendantFocusability(FOCUS_BEFORE_DESCENDANTS); // 实例化LinearLayoutManager对象 mLayoutManager = new LinearLayoutManagerImpl(context); mRecyclerView.setLayoutManager(mLayoutManager); mRecyclerView.setScrollingTouchSlop(RecyclerView.TOUCH_SLOP_PAGING); setOrientation(context, attrs); mRecyclerView.setLayoutParams( new ViewGroup.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); mRecyclerView.addOnChildAttachStateChangeListener(enforceChildFillListener()); // Create ScrollEventAdapter before attaching PagerSnapHelper to RecyclerView, because the // attach process calls PagerSnapHelperImpl.findSnapView, which uses the mScrollEventAdapter mScrollEventAdapter = new ScrollEventAdapter(this); // Create FakeDrag before attaching PagerSnapHelper, same reason as above mFakeDragger = new FakeDrag(this, mScrollEventAdapter, mRecyclerView); mPagerSnapHelper = new PagerSnapHelperImpl(); mPagerSnapHelper.attachToRecyclerView(mRecyclerView); // Add mScrollEventAdapter after attaching mPagerSnapHelper to mRecyclerView, because we // don't want to respond on the events sent out during the attach process mRecyclerView.addOnScrollListener(mScrollEventAdapter); mPageChangeEventDispatcher = new CompositeOnPageChangeCallback(3); mScrollEventAdapter.setOnPageChangeCallback(mPageChangeEventDispatcher); // Callback that updates mCurrentItem after swipes. Also triggered in other cases, but in // all those cases mCurrentItem will only be overwritten with the same value. final OnPageChangeCallback currentItemUpdater = new OnPageChangeCallback() { @Override public void onPageSelected(int position) { if (mCurrentItem != position) { mCurrentItem = position; mAccessibilityProvider.onSetNewCurrentItem(); } } @Override public void onPageScrollStateChanged(int newState) { if (newState == SCROLL_STATE_IDLE) { updateCurrentItem(); } } }; // Prevents focus from remaining on a no-longer visible page final OnPageChangeCallback focusClearer = new OnPageChangeCallback() { @Override public void onPageSelected(int position) { clearFocus(); if (hasFocus()) { // if clear focus did not succeed mRecyclerView.requestFocus(View.FOCUS_FORWARD); } } }; // Add currentItemUpdater before mExternalPageChangeCallbacks, because we need to update // internal state first mPageChangeEventDispatcher.addOnPageChangeCallback(currentItemUpdater); mPageChangeEventDispatcher.addOnPageChangeCallback(focusClearer); // Allow a11y to register its listeners after currentItemUpdater (so it has the // right data). TODO: replace ordering comments with a test. mAccessibilityProvider.onInitialize(mPageChangeEventDispatcher, mRecyclerView); mPageChangeEventDispatcher.addOnPageChangeCallback(mExternalPageChangeCallbacks); // Add mPageTransformerAdapter after mExternalPageChangeCallbacks, because page transform // events must be fired after scroll events mPageTransformerAdapter = new PageTransformerAdapter(mLayoutManager); mPageChangeEventDispatcher.addOnPageChangeCallback(mPageTransformerAdapter); attachViewToParent(mRecyclerView, 0, mRecyclerView.getLayoutParams()); }ViewPager2的出现是为了替代ViewPager,它有以下几个优势:
支持RTL布局,支持竖向滚动支持notifyDataSetChangedRTL布局是Right To Left布局也就是从右往左的布局,大家知道我们平常写的布局都是从左往右,但是如果你适配阿拉伯语等环境的UI布局,他们的写法是从右往左的,具体这里不做研究。
API的变动:
FragmentStateAdapter替换了原来的 FragmentStatePagerAdapter
RecyclerView.Adapter替换了原来的 PagerAdapter
registerOnPageChangeCallback替换了原来的 addPageChangeListener
FragmentStateAdapter和FragmentStatePagerAdapter作用相同, 可以用viewpager来管理fragment, 区别在于viewpager2的FragmentStateAdapter与recycleview的生命周期绑定
另外viewpager2的Adapter是继承自recyclerview的adapter, 支持除了notifyDataSetChanged()以外的notifyItemChanged(int position)等方式, 使用上更加的便捷
三、ViewPager2 结合 Fragment实际demo在app模块的build.gradle里要加上这两个依赖
implementation"androidx.viewpager2:viewpager2:1.1.0-beta02"implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'myfragment.xml
一个显示在屏幕正中央的文字mode1
myfragment2.xml
一个显示在屏幕正中央的文字mode2
activity_main.xml
一个TabLayout和一个ViewPager2组件
MyAdapter.java
重写MyAdapter、createFragment、getItemCount三个方法
package com.example.viewpager2; import androidx.annotation.NonNull; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentManager; import androidx.viewpager2.adapter.FragmentStateAdapter; import androidx.lifecycle.Lifecycle; import java.util.List; public class MyAdapter extends FragmentStateAdapter { ListMyFragment.java
实现第一个fragment页面
package com.example.viewpager2; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; public class MyFragment extends Fragment { @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { return inflater.inflate(R.layout.myfragment, null); } }MySecondFragment.java
实现第二个fragment页面
package com.example.viewpager2; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; public class MySecondFragment extends Fragment { @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { return inflater.inflate(R.layout.myfragment2, null); } }MainActivity.java
进来的activity
package com.example.viewpager2; import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; import androidx.fragment.app.Fragment; import androidx.viewpager2.widget.ViewPager2; import android.os.Bundle; import com.google.android.material.tabs.TabLayout; import com.google.android.material.tabs.TabLayoutMediator; import java.util.ArrayList; import java.util.List; public class MainActivity extends AppCompatActivity { private TabLayout myTab; private ViewPager2 myPager2; ListViewPager + Fragment 实现tab页切换不同页面内容的效果
参考:【精选】Android:ViewPager \ViewPager2 简单介绍 & 使用方法解析_viewpager2与viewpager-CSDN博客