ViewPager2最显著的特点是基于RecyclerView实现,RecyclerView是目前Android端最成熟的AdapterView解决方案,这带来诸多好处:
1、抛弃传统的PagerAdapter,统一了Adapter的API/
2、通过LinearLayoutManager可以实现类似抖音的纵向滑动
3、支持DiffUitl,可以通过diff实现局部刷新
4、支持RTL(right-to-left)布局,对于一些有出海需求的APP非常有用
5、支持ItemDecorator
一、ViewPager2和ViewPager的对比:
1、ViewPager2内部实现是RecyclerView,所以ViewPager2的性能更高。
2、ViewPager2可以实现竖向滑动,ViewPager只能横向滑动。
3、ViewPager2只有一个adapter,FragmentStateAdapter继承自RecyclerView.Adapter。
而ViewPager有两个adapter,FragmentStatePagerAdapter和FragmentPagerAdapter,均是继承PagerAdapter。FragmentStatePagerAdapter和FragmentPagerAdapter两者的区别是FragmentStatePagerAdapter不可以缓存,FragmentPagerAdapter可以缓存。
4、ViewPager2模式实现了懒加载,默认不进行预加载。内部是通过Lifecycle 对 Fragment 的生命周期进行管理。ViewPager会进行预加载,懒加载需要我们自己去实现。

效果图:

public class MainActivity extends AppCompatActivity {
private TabLayout tabLayout;
private ViewPager2 viewPager2;
private int activeColor = Color.parseColor("#ff678f");
private int normalColor = Color.parseColor("#666666");
private int activeSize = 20;
private int normalSize = 14;
private ArrayList<Fragment> fragments;
private TabLayoutMediator mediator;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tabLayout = findViewById(R.id.tab_layout);
viewPager2 = findViewById(R.id.view_pager);
final String[] tabs = new String[]{"关注", "推荐", "最新0", "最新1", "最新2", "最新3", "最新4", "最新5", "最新6"};
//禁用预加载
viewPager2.setOffscreenPageLimit(ViewPager2.OFFSCREEN_PAGE_LIMIT_DEFAULT);
//Adapter
viewPager2.setAdapter(new FragmentStateAdapter(getSupportFragmentManager(), getLifecycle()) {
@NonNull
@Override
public Fragment createFragment(int position) {
//FragmentStateAdapter内部自己会管理已实例化的fragment对象。
// 所以不需要考虑复用的问题
return TestFragment.newInstance(tabs[position]);
}
@Override
public int getItemCount() {
return tabs.length;
}
});
//viewPager 页面切换监听监听
viewPager2.registerOnPageChangeCallback(changeCallback);
mediator = new TabLayoutMediator(tabLayout, viewPager2, new TabLayoutMediator.TabConfigurationStrategy() {
@Override
public void onConfigureTab(@NonNull TabLayout.Tab tab, int position) {
//这里可以自定义TabView
TextView tabView = new TextView(MainActivity.this);
int[][] states = new int[2][];
states[0] = new int[]{android.R.attr.state_selected};
states[1] = new int[]{};
int[] colors = new int[]{activeColor, normalColor};
ColorStateList colorStateList = new ColorStateList(states, colors);
tabView.setText(tabs[position]);
tabView.setTextSize(normalSize);
tabView.setTextColor(colorStateList);
tab.setCustomView(tabView);
}
});
//要执行这一句才是真正将两者绑定起来
mediator.attach();
}
private ViewPager2.OnPageChangeCallback changeCallback = new ViewPager2.OnPageChangeCallback() {
@Override
public void onPageSelected(int position) {
//可以来设置选中时tab的大小
int tabCount = tabLayout.getTabCount();
for (int i = 0; i < tabCount; i++) {
TabLayout.Tab tab = tabLayout.getTabAt(i);
TextView tabView = (TextView) tab.getCustomView();
if (tab.getPosition() == position) {
tabView.setTextSize(activeSize);
tabView.setTypeface(Typeface.DEFAULT_BOLD);
} else {
tabView.setTextSize(normalSize);
tabView.setTypeface(Typeface.DEFAULT);
}
}
}
};
@Override
protected void onDestroy() {
mediator.detach();
viewPager2.unregisterOnPageChangeCallback(changeCallback);
super.onDestroy();
}
}
<com.google.android.material.tabs.TabLayout
android:id="@+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="40dp"
app:tabGravity="center"
app:tabIndicatorColor="#ff678f"
app:tabIndicatorFullWidth="false"
app:tabIndicatorHeight="2dp"
app:tabMode="scrollable"
app:tabSelectedTextColor="#ff678f"
app:tabTextColor="#333333"
app:tabUnboundedRipple="true" />
<!-- ViewPager2内置了RecyclerView
所以需要通过orientation来设置页面切换方向-->
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/view_pager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:orientation="horizontal" />
viewPager2可以通过设置android:orientation属性来设置切换方向,支持上下、左右切换。
对应tab页面的实现效果在Fragment中进行实现。
public class TestFragment extends Fragment {
private View rootView;
public static TestFragment newInstance(String text) {
Bundle args = new Bundle();
args.putString("text", text);
TestFragment fragment = new TestFragment();
fragment.setArguments(args);
return fragment;
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.fragment_test, container, false);
return rootView;
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
TextView textView = rootView.findViewById(R.id.text_view);
String text = getArguments() != null ? getArguments().getString("text") : null;
textView.setText(text);
}
}
几个注意的点!!
看下源码tag怎么设置的,调用链如下:
FragmentStateAdapter-》onBindViewHolder-》placeFragmentInViewHolder方法
mFragmentManager.beginTransaction()
.add(fragment, "f" + holder.getItemId())
.setMaxLifecycle(fragment, STARTED)
.commitNow();
setOffscreenPageLimit()设置预加载与缓存(1)ViewPager 会预加载几页
(2)ViewPager 会缓存 2*n+1 页(n为设置的值)
如设置为n=1,预加载页数1页,缓存页数3页。如果当前在第一页,会预加载第二页,滑倒第二页,会预加载第三页,当滑倒第三页,第一页会销毁,第四页会加载。
我正在使用查看寻呼机来滑动图像。我可以在日志中获取url,但是当我尝试在ImageView中设置时,出现错误。E/AndroidRuntime(1895):FATALEXCEPTION:mainE/AndroidRuntime(1895):Process:com.project.center,PID:1895E/AndroidRuntime(1895):java.lang.NullPointerException:Attempttoreadfromfieldcom.project.center.views.TouchImageViewcom.project.center.FullScr
我正在为我的Viewpager使用选项卡,这是现在的XML:它们看起来很棒,但我希望能够有更多选项卡,而不是让所有内容都挤在屏幕上。但是我不喜欢切换到可滚动的tabMode,因为那样的话一切都会变平并且看起来很乱。如何设置各个选项卡的宽度? 最佳答案 TabLayout不提供特定选项卡固定宽度的属性。但是您可以设置最小和最大宽度。tabMinWidthandtabMaxWidthhttps://developer.android.com/reference/android/support/design/widget/TabLayou
我正在尝试开发一个时间线,就像下面的facebook一样。你看,我有一个ViewPager可以在“fragment”(如提要、个人资料、关于等)之间导航用户。我有“main.xml”,它上面只有viewpager;我还有fragmenta.xml、fragmentb.xml、fragmentc.xml。让我们检查一下fragmenta.xml,我把它放在里面;并制作了singlerow.xml来将这些框创建成这样的时间线;我让它只使用一个静态框。但是当我尝试运行这个结构时,我在Debug模式下遇到错误“找不到来源编辑源查找路径”在我尝试像这样将我的适配器和其他关于listview的东西
我正在ViewPager内的TabLayout上设置高度,但它根本没有显示。我在stackoverflow上尝试了很多答案,但无法解决问题。在CoordinatorLayout中设置android:clipToPadding="false"也不能解决问题。任何帮助,将不胜感激。这是我正在使用但现在提升的布局的xml: 最佳答案 要使阴影可见,您必须在TabLayout上设置背景。它可以与您的窗口背景颜色相同(只要它是没有alpha的纯色)。此外,您还必须为其提供Tablayout边距以查看高度。最小margin应该是您提供的elev
以下是我的XML,我的PagerTitleStrip嵌入到ViewPager中:这是我自定义的PagerAdapter类。publicclassCustomPagerAdapterextendsPagerAdapter{privateint[]image_resources={R.drawable.1,R.drawable.2,R.drawable.3};privateContextctx;privateLayoutInflaterlayoutInflater;publicCustomPagerAdapter(Contextctx){this.ctx=ctx;}@Overridepub
我想将setOnClickListener设置到我的ImageView,它位于ViewPagerItemXML中。在我的activityXML中,我有ViewPager和其他几个按钮。在我的ViewPagerItemXML中,我有可点击的ImageView。我想在Activity中单击ImageView后执行一些操作。不幸的是,OnClickListener根本不会触发。LayoutInflaterinflater=(LayoutInflater)this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);itemView=inflat
我是安卓开发的新手。我正在使用photoview库在我的imageviewer应用程序中启用图像缩放。但是viewpager和缩放功能不能同时工作。当我在FullImageActivity.java中包含photoView.setVisibility(View.GONE);时,viewpager开始工作,当我删除它,缩放功能开始工作。但是zooming和viewpager不能同时工作。我该如何解决?谢谢完整代码可在https://github.com/redviper00/game获得FullImageActivity.java:publicclassFullImageActivity
我的代码有一些问题。我在下面的代码中有一个NullPointerException。我正在尝试在3个不同的fragment之间创建滑动。我不明白我的错误在哪里所以请帮助我:p虚拟fragment.java:packagecom.example.testslide;importandroid.os.Bundle;importandroid.support.v4.app.Fragment;importandroid.view.LayoutInflater;importandroid.view.View;importandroid.view.ViewGroup;importandroid.w
现在我在iOS应用程序开发过程中遇到了一个问题。我使一个viewpagercontrollerview包含几个viewcontroller。每个Viewcontroller都包含tableview。我在这个TableView中使用了UISearchController。但是,每当我单击searchcontroller并滚动标签时,就会发生错误。2016-08-0822:07:11.211ToolManager[3913:121312]***Assertionfailurein-[_UIQueuingScrollView_setWrappedViewAtIndex:withView:],
我目前正在使用Ionic3开发一个应用程序,主屏幕包含3个选项卡(ion-tabs)我创建了一个根据用户滑动更改选项卡的功能,但是我的客户要求一个等于WhatsApp的过渡,我不知道要实现这个。我考虑过使用ion-slides但我必须将代码从3个选项卡迁移到单个View,有没有一种方法可以在不更改组件的情况下附加动画? 最佳答案 您可以使用ionic2-super-tabs.这个库可以轻松制作可滑动的选项卡。您必须检查github页面的兼容性以及您应该使用哪个版本。有了这个库,一个基本的例子如下。它与Ionic本身的选项卡几乎相同。