玩转ViewPager2以及在自如中的应用

一、简介

姓名:ViewPager2

生日:2019年11月20日

地址:androidx.viewpager2.widget

布景:

在2019年的11月20号,Google对外公开了一件大事!让许多Android开发者激动万分~ 那便是公布了我app下载们期待已久的 ViewPager2 正式版。他归于 androidx 组件包中的一员,ViewPager2 能够看做是 ViewPager前端开发是干什么的的升级版,所以许多场景是能够按照ViewPager的运用办法来用的。ViewPager2的进阶处理是内部选用了RecyclerView结束,解决了许多在运用ViewPGoager过程中的问题一同还增加了一些自身的特性~ 接下来就让咱们一同来认识一下他吧公积金~

二、根底

1.差异比照

谷歌源码中有这样介绍ViewPager2

ViewappearPager2 replaces ViewPager, addressing most of its predece前端开发需求学什么ssor’s pain-points, including right-to-left layout support, vertical orientation, modifiable Fragment collections, etc.

用如下表格明晰的展现比照:

ViewPager ViewP公积金ager2
PagerAdapter RecyclerView.Adapter
FragmentStatePagerAdapter FragmentStateAdapter
addPageChangeListener registerOnPageChangeCallback
不支撑 支撑RTL
不支撑 支撑笔直滑动
不支撑 支撑连续用户操源码是什么意思

个人感觉最爽的改动点在于内部的RecyclerView结束以及支撑笔直翻滚

2.底子运用

以ViewPager2来结束ViewPager最根底的功用【图片banner】为例:

前提是需求确保项目代码支撑androidx的呦~参看官网

2.1 增加依托(需求单独增加依托~),

depe宫颈癌n前端工程师dencies {
implementa源码是什么意思tion "androidx.viewpager2:viewpagerappreciate2:version"
}

2.3 布局文件运用

在xmGol中运用,没有什么特别的点,类似常见控件运用办法即可。approve设置宽高、ID、方位等等条件前端学什么

    <a源码网站ndroidx.viewGopager2.widget.ViewPager2
android:id="@+id/view_pager2"
android:layo前端和后端的差异ut_width="match_parent"
android:layout工商银行客服电话_height="0dp"
apapproachp:layout_constraintDimensionRatio="2:3"
app:layout_constraintStart_toStartOf="parentGo"
aapplepp:layout_constrappearaintTop_toTopOf="parent" />

2.4 设置Adapter

谷歌空间为内部Rec谷歌地球ycleRiew结束的,所以ViewPager2的Adapter就需求设置为Recy谷歌浏览器下载clerView的Ad前端和后端哪个薪酬高apter

class VpAdapter : RecyclerView.Adapter<VpAdapter.VpViewH谷歌翻译older>() {
// adapter的数据源
private var data: MutableList<HouseItem> = mutableListOf()
fun s源码编辑器etData(list: MutableL宫颈癌ist<HouseItem>) {
data.clear()
data.addAll(list)
notifyDataSetChanged()宫崎骏
}
override fun onCreateViewHolder(pa谷歌地图rent: ViewGroup, viewType: Int): VpViewHolder {
val view =
LayoutInflater.from谷歌地球(parent.cont源码年代训练怎么样ext).inflate(R.layou谷歌浏览器t.item_rv2_basic枸杞_view, parent, false)
return VpVi宫崎骏ewHolder(view)
}
override fun onBindViewHolder(holder: VpViewHolder, position: Int) {
holder.render(dappreciateata[position])
}
ov前端工程师erride fun getItemCount() = data.size
class VpViewHolder(_itemView: View) : RecyclerView.ViewHolder(_itemView) {
private var pvImage: SimpleDraweeV工商银行iew = itemView.fi源码年代训练怎么样ndViewB宫崎骏yId(R.id.pv_ima工商银行ge)
private var tvTitle: Text前端训练组织View = itemView.findViewById谷歌商铺(R.id.tv_title)
fun render(bean: HouseItem) {
tvTitle.text = bea源码精灵n.houseTypeName
pvImage.setImageURI(bean.houseTypePic)
}
}
}

布局文件也很简单,单纯的放置了一个SimpleDraapp下载weeView+一个TextView用来展现一张图片+一个标题;Go
能够看到,这跟咱们平常运用RecyclerView时写的Adapter没有任何差异。所以在运用的时分是不会有任何阻碍的~

(SimpleDrawe前端开发需求学什么eView的运用在此不赘述,感兴趣的小伙伴可参看官网学习SimpleDraweeView)

2.5 装备特征

类似于RecyclerVGoiew~
初始化ViewPager2、初始化Adapter、设置数据源、给Vie宫颈癌前期症状wPager2设置Adapter,就能结束类似ViewPager的Banner作用了~

        adapter =前端和后端的差异 VpAdapter()
adapter.setData(lis谷歌浏览器下载t)
viewPager2.adapter = adapter

作用如图:
Video

前边叙说差异的时分,有提到过ViewPage谷歌商铺r2默许支撑笔直滑动,那么我要结束笔直翻滚的Banner,该怎样处理呢?

其实很简前端工程师单,只需求设置ViewPager2的翻滚方向特征就行了~

        // 设置笔直翻滚方向
viewPager2.orientation = ViewPager2.ORIENTATIO前端工程师N_VERTICAL谷歌地图

至此,关于ViewPage前端面试题r2底子的运用都介绍完了~

三、进阶

1.页面切换监听前端开发是干什么的

ViewPager2的页面切换监听,供给了 registerOnPageChangeCallback 的办法,传递一个 笼统方针 OnPageChaapplengeCallback,长处是三个办法不需求一次性列出来了,用到哪个写哪个。

    public前端工程师 abstract static class OnPageChangeCallbac谷歌浏览器下载k {
public voi前端训练组织d onPageScrolled(int position, float positionOffset,
@Px int positionOffsetPixels) {
}
public void onPageSelected(int po谷歌商铺sition) {
}
public void onPageScrollSt前端学什么ateChanged(@ScroapplicationllState int state) {
}
}

通过以上源码解释,常用的应该谷歌翻译便是 onPageSelected(int position)办法了,监听到滑动到对应索引值的页面。工商银行客服电话

        // 页面切换监听
viewPager2.registerOnPageCh宫颈癌前期症状angeCal公积金lback(ob前端面试题ject : ViewPa工商银行客服电话ger2.OnPageChangeCallback() {
// 选中 回调,中心用于 处理选中索引值相关逻辑
override fun onPage源码网站Selected(position: Int) {
super.onPage源码资源站Selected(position)
Log.e(TAG, "onPageSelected: position = $前端结构position")
}
})

2.一屏多页

ViewPager2假如要结束一屏多页的作用,需求借助于 offscreenPageLimit 以及 setPadding狗狗币

        viewPager2.apply {
offscreenPageLimit = 1
val recyclerVi源码ew = this.getChildAt(0) as RecyclerView /前端开发是干什么的/ 获取ViewPager2中的 RecyclerView
recyclerView.apply {
val padding = 40.dp
setPadding(padding,谷歌地球 0, padd前端开发是干什么的inappleg, 0)
clipToPadding = false
}
}
va宫崎骏l recyclerView = this.getChildAt(0) as RecyclerView

针对这个地方,参看源码254行,能够看到,Vi源码交易网站源码ewPager2内部是默许将 mRecyclerView增加到ViewGroup中的,索引值固定是0!

attachViewToParent(mRecyclerView, 0, mRecyclerView.getLayoutParams());

3.offscreenPageLimit 预加载

在ViewPager中,会前端默许加载approachapplication后各一个页面,所以处理懒加载就比较费事,那么在ViewPager2中,默许去掉了这约束,也便是默许只会加载一个页面,
先来看下 参数

    public void setOffscreen谷歌装置器PageLimit(@OffscreenPageLimit int limit) {
if (limit < 1 && limit != OFFSCREEN_源码年代PAGE_LIappointmentMIT_DEFAULT) {
throw new IllegalArgumentException(
"Offscreen page limit must be OFFSCREEN_APPPAGE_LIMIT_DEFAULT or a numb谷歌卫星地图er > 0");
}
mOffscreenPageLimit = limit;
// Trigger layout so prefetch happens through getExtraLayoutSize()
mRecyclerView.requ前端训练组织es公积金tLayout();
}

源码中的setOffscreenPageLimit设置需求处理一个参数,能够看到有个注解OffscreenPageLimit标明默许值是需求从1初步的。

接下来我用ViewPager2加载Fragment来证明,默许以Fragment的生命周期日志为参照

3.1 offscreenPageLimit 不设置

E/debug_VpFragment: onCreate:  mCurrentPosition = 0
E/debug_谷歌翻译VpFragment: onPause:  onCreateViegooglew = 0
E/debug_VpFragment: o谷歌翻译nResume:  mCurrentPosition = 0

能够看到,默许google对此办法不做处理的话,只对第一个Fragment进行了初始化工商银行的相关操作。

3.2 offscreenPageLim龚俊it = 1

E/debug_VpFragment: onCreate:  mCurrentP前端开发需求学什么osition = 0
E/debug_VpFragment: onPause:  onCreateView = 0
E/debug_VpFragment: onResume:  mCurrentPo前端和后端哪个薪酬高sit前端工程师ion = 0
E谷歌地图/debug_VpFragment: onCreate:  mCurrentPosiappletion = 1
E/debug_VpFragment: onPause:  onCreateView = 1

设置offscreenPageLimit = 1的时分,对前两个Fragment进行了初始化相关操作。

3.3 offscreenPageLimit = 2

E/debug_VpFragment: onCreate:  mCurrentP宫崎骏osition = 0
E/debug_VpFragment: onPause:  onCreateView = 0
E/debug_VpFragment: onResume:  mCurrentPosi谷歌空间tion = 0
E/debug_VpFragment: onCre宫崎骏ate:  mCurrentPosition = 1
E/debug_VpFragment: onPause:  onCreateView = 1
E/debu源码年代g_VpFragment: onCreate:  mCurrentPosition = 2
E/debug_VpFragment: onPause:  onCreateView = 2

google置offscreenPageLimit = 2的时分,对前三个Fragment进行了初始化相关操作。

4.结合TabLayout

TabLayo工商银行ut结合ViewPager也是比较常用的,可是ViewPager2结合运用的时分,需求多一个TabLayou前端开发需求学什么tMediator

TabLayoutMediator接受三个参数:

参数1:TabLayout

参数2:源码之家ViewPager2

参数3:TabConfigurat源码年代训练怎么样ionStrategy (interface)

重点是第三个参数,需求重写onConfigureTab(@NonNull TabLayout.Tab tab, int position),所以假如咱们想要结束一些自定义的Tab样式,能够直接在此办法中处理,一同能够拿到索引值进行特别处理。

        new TabLayoutMediator(mTabLayout, mViewPager2, new TabLayoutMediator.TabConfigurationStrategy() {
@Override
public voappearanceid onConfigureTab(@NonNull TabLayout.Tab tab, int position) {
TextView text前端开发需求学什么View = new TextView(mFragmentActivity);
textView.setText(mVpBea工商银行ns.get(position).getTitle());
tab.setCustomView(textView);
}
}).attach();

项目实战

自若寓,隶归于自若咱们庭的重要一员,是一种更加年青的、外交化的集中式公寓,具有多种外交活动等功用,所以自若寓的管家们会将日常安排的活动中的一前端和后端的差异些精彩视频、图片记录下来,并上传到“好玩”tab的数据里边,并以瀑布流的方法展现。
基于用户体会以及交互方法,咱们考虑针对这些视频、图片做一种上下滑动播映视频、横向滑动展现图片的一种效前端训练组织果,考虑到了上述谷歌装置器ViewPager2的特性,查验运用结束

大致思路

页面容器中,前端和后端的差异选用ViewPager2来承载每一个切换的Page;Page以Fragment结束;Fragment中差异视频类型/图片类型,分别以视频播映器/图片banner来承载

页面结构

考虑到了ViewPager2的笔直翻滚功用,坚决决断的进行查验一会儿;页面结构结束简单化,在对应的页面中,全体结构便是ViewPager2+TopV前端训练组织iew(一些自定义的样式展现,此处忽略),然后VpFragmeng作为每一个Page的承载,内含播映器控件或许轮播控件(展现横滑图片)
大致如图:

Activity中的内容比较简单,首要便是对ViewPager2、Fragment绑定的处理。

  privappleate fun initView()宫颈癌 {
mAdapter = Pag前端和后端哪个薪酬高eAdapter(this, mModelList)
mAdapter?.setOnAdapterDataChangeListener(obappreciateject : PageAdap源码ter.OnAdapterDataChangeListener {
override fun onPageChangeListener(selectedPosi谷歌商铺tion: Int) {
mTvCurrentPage?.text = Stapplicationring.format("%d", selectedPosition + 1)
}
override fun onSupportClick(bean: PlayEvaluationListModel.RowsBean?, posit枸杞ion: Int, status: Boolean) {
}
override fun onImageClick() {
finish()
}
})
// 设置笔直翻滚作用
mViewPageappstorer2?.orientation = ViewPager2.ORIENTATION_VERTICAL
mViewPager2?.adapter = mAdapter
mViewPager2?.registerOn前端面试题PageCh工商银行客服电话angeCallback(object : V谷歌装置器iewPager2.OnPageChangeCall工商银行客服电话back() {appear
override fuappointmentn onPageSelected(position: Int) {
super.onPageSelected(pos源码网站ition)
// 处理顶部的指示器数据
//这只当时item的数据
val model = mModelList[position]
// 准备加载更多的数据
i源码之家f (position == mModelList.size - 2) { // -2 ,是为了在倒数第二个的时分就让他进行分页approach,提早一个加载
if (!mCanLoadMore) {
return
}
mPresenter?.fill谷歌浏览器下载Data()
}
}
})
initTitlePosition()
}

Adapter的代码就不贴了,跟demo中类似,绑定Fragment就行了~

PageFragment,作为每一个Page的承载,运用办法跟普通Fragment没什么本质差异;

常规数据初始化
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
mFragmentActivity = activity
if (arguments != null) {
mRowsBean = arguments?.getSerializable("rowsBean") as PlayEval源码年代训练怎么样uationListModel源码是什么意思.RowsBean
mCurrentPappstoreosition = arguments?.getInt("position") ?: 0
}龚俊
}
绑定View
override fun onCreateView(inflater: LayoutInflat源码之家er, container: ViewGroup?, savedInstaapprovenceState: Bundle?): View? {
val view = inflater.inflate(R.layout.Goitem_play_evaluation_list, container, false)
initView(view)
return view
}

// 这个是具体的展现逻辑,依据是视频类型还是图片类型,分别展现 视频播映器 或许 图片banner控件;

    private fun render() {
val model = mRowsBean ?: return
if (model.isVideo) {
mZvvVideo?.visible = true
mCpPicList?.visible = false
val pic = if (null != model.picList && model.picList.size >= 1) model.picList[0].picUrl else前端开发是干什么的 ""
mZvvVideo?.setPlaceImg(pic)
mZvvVideo?.setVideoPath(model.videoUrl)
mZvvVideo?.setOnClickListener { _: View? ->
if (mZvvVideo?.videoView != null &ampapproach;& mZvvVideo?.videoView?.isPlayingGo == true) {
mZvvVideo?.pause()
} else {
mZvvVi谷歌浏览器deo?.startVideo()
}
}
var imgWidth = 720.0
var imgHeapproachight = 1280.0
// 视频和图片的宽高
if (model.picList != null && model.picList.isNotEmpty()) {
val picListBean = model.picList[0]
if (picListBean != null) {
imgWidth = picLis源码年代tBeaapplen.width
imgHeighGot = picListBean.heig谷歌地图ht
}
}
// 手动赋值宽高
val lp:工商银行 ViewGroup.LayouAPPtPar谷歌地球ams = mZvvVideo?.layoutParams
?: Vie源码wGroup.LayoutPar源码之家ams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)
lp.width = mScreenWid谷歌装置器t前端和后端哪个薪酬高h
var newH = imgHeight
// 竖屏视频
if (imgWidth > 0) {
newH = mScreenWidth * imgHeight / imgWidth
}
lp.height = newH.toInt()
mZvvVideo?.video谷歌空间View?.setOnVideoSapplicationizeChangedListene源码交易网站源码r { _: Int, _: Int ->
mZvvVideo?.videoView?前端开发.displayAspectRatio = PLVideoView.工商银行客服电话ASPECT_RATIO_FIT_PAR前端工程师ENT
}
} else {
mapproveZvvVid前端面试题eo?.visible = f源码年代alse
mCpPicList?.visible = true
mCpPicList?.isCa谷歌nLoop = f枸杞alse
mCpPicList?谷歌地图.setPages({
val detailPlay宫崎骏PicHolder = Detail宫颈癌前期症状PlayPicHolder()
detailPlayPicHolder.setOnAdapterDataChan源码g源码是什么意思eListener(object : OnAdapterDataChangeListener {
override fun onPageChangeL谷歌地图istener(selectedPosition: Int) {}
override fun onSupportClick(bean: PlayEvaluationListModel.RowsBean?, position: Int, status: Boolean) {}
override fun onImageClick() {
mOnAdapterDataChangeListener?.onImageClick()
}
})
detailPlayPicHolder
}, model.picList)
mCpPicList?.onPageChangeListener = objec公积金t : ViewPager.OnPageChangeListener {
override fun onPage工商银行客服电话Scrolledappointment(position: Int, positionOffset: Float, positionOffsetPixels: Int) {}
override fun onPageSelected(page: Int) {
mOnAd前端和后端的差异apterDataChangeListener?.onPageChangeListener前端开发是干什么的(page)
}
override fu源码交易网站源码n onPageScrollStateChanged(state: Int) {}
}
}
// ....省谷歌空间掉....
}

考虑到视频appearance播映状况要与用户操作页面状况结合,所以需求在页面切换出去的时分,将对应的视频播映器进行暂停或许连续操龚俊作(具体采用何种操作视情况而定),在此处咱们谷歌选用的是暂停计划,当用户手动切换回一个刚切换出去的Page,能够结束持续播映前次未播映完毕的视频。

    override fun onResume() {
super.onResume()
mZvvVideo?.start()
}
override fun onPause() {
super.onPause()
mZvvVideo?.pause()
}

至此,结束了支撑上下滑动切换视频/图片、左右切换图集的功用。
以上,仅为自己实战体会,如有更优姿势,欢迎不吝赐教~

本文作者:自若大前端研制中心-邱宴峰

发表评论

提供最优质的资源集合

立即查看 了解详情