在 Android 开发中,ViewPager 是常用的一种控件,常常用于实现轮播图、图片浏览等功能。在 Material Design 中,ViewPager 切换动效被要求具有更加流畅自然以及针对性强的效果。本文将探讨 Material Design 下 ViewPager 切换动效的实现方式。
Material Design 下 ViewPager 切换动效的设计理念
Material Design 规范中关于 ViewPager 切换动效的设计理念如下:
- 能够让用户感受到物体移动的连续性和逐渐变化的速度。
- 提供物体的路径、速度和位置的透明度,使得用户可以预测物体下一个可能的位置。
- 支持用户在旅程的各个阶段中能够进行正常控制。
基于以上设计原则,我们可以尝试实现以下动效特征:
- 切换过程中页面元素的视觉感受存在连续性,呈现出一种自然的流动感。
- 切换过程中,页面元素的路径、速度和位置的透明度应该是清晰的。可以让用户在这个过程中感到跟踪操作非常简单。
- 不会出现卡顿现象,造成用户的不适。
ViewPager 切换动效的实现方式
在 Android 中,ViewPager 切换动效的实现,有三种方案:
1. 通过设置系统默认动画实现 ViewPager 切换动效
在 Android 中,ViewPager 默认的切换动画是 PageTransformer。我们可以直接在代码中调用系统默认提供的 View 的 API 来进行页面切换的翻页效果:
viewPager!!.setPageTransformer(true, DepthPageTransformer())
2. 自定义切换动效的实现方式:使用 ViewPager.PageTransformer 接口
使用 ViewPager.PageTransformer 接口可以实现自定义的页面切换动效。这种方法的实现仅需要简单的使用 ViewPager.setPageTransformer(boolean, PageTransformer) 方法即可。
3. 自定义切换动效的实现方式:通过多个动画协同实现 ViewPager 切换动效
此方法是最复杂的方案,它是通过加入多个动画实例,结合使用的方式,实现 ViewPager 的切换效果。他不仅要理解多种不同的动画实例,还需要处理它们的交互和晨合,也需要处理 这些动画实例在相互上下文中的演绎关系。
viewPager!!.addOnPageChangeListener(object : ViewPager.OnPageChangeListener { override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) { var realCurrentPosition: Int var nextPosition: Int var realPositionOffset: Float var left: View? var right: View? val isLeftToRight = lastPosition < position if (isLeftToRight) { realCurrentPosition = position - 1 nextPosition = position realPositionOffset = positionOffset left = getViewByPosition(realCurrentPosition) right = getViewByPosition(nextPosition) } else { realCurrentPosition = position + 1 nextPosition = position realPositionOffset = 1 - positionOffset left = getViewByPosition(nextPosition) right = getViewByPosition(realCurrentPosition) } if (left != null) { val lp = left.layoutParams as FrameLayout.LayoutParams lp.width = (mContainerWidth - mTransformer!!.getOffsetWidth() - mTransformer!!.getMarginWidth()) / 2 + (mTransformer!!.getOffsetWidth() + mTransformer!!.getMarginWidth()) * realPositionOffset.toInt() left.layoutParams = lp } if (right != null) { val lp = right.layoutParams as FrameLayout.LayoutParams lp.width = (mContainerWidth - mTransformer!!.getOffsetWidth() - mTransformer!!.getMarginWidth()) / 2 + (mTransformer!!.getOffsetWidth() + mTransformer!!.getMarginWidth()) * (1 - realPositionOffset).toInt() right.layoutParams = lp } } override fun onPageScrollStateChanged(state: Int) { if (state == ViewPager.SCROLL_STATE_IDLE) { lastPosition = viewPager!!.currentItem } } override fun onPageSelected(position: Int) {} })
案例分析
接下来我们将通过一个实例来展示以上三种实现方式效果的区别。
在这个实例中,我们将使用三张图片实现轮播效果。预期轮播效果如下:
1. 使用系统默认动画实现切换动效
我们可以使用系统默认动画实现切换效果,效果如下:
viewPager!!.setPageTransformer(true, DepthPageTransformer())
可以看到,通过设置系统默认动画,效果显得简单生硬,没有华丽的效果,缺乏足够的设计感。
2. 使用 ViewPager.PageTransformer 接口实现切换动效
此方案可以实现自定义动画,更好地实现 Material Design 设计效果。我们可以通过创建具有高度自定义性的 PageTransformer 子类,满足 Material Design 设计要求的需要,实现更加华丽的效果。
val pageTransformer = ParallaxPageTransformer() viewPager!!.setPageTransformer(true, pageTransformer)
class ParallaxPageTransformer : ViewPager.PageTransformer { override fun transformPage(page: View, position: Float) { if (position >= -1 || position <= 1) { transformOutline(page, position) } if (position >= -1 && position <= 1) { transformPageView(page, position) } else { page.alpha = 0f } if (position >= -0.5f && position <= 0.5f) { transformBody(page, position) } } private fun transformBody(view: View, position: Float) { val width = (view.width / 2 * position).toInt() view.findViewById<ImageView>(R.id.img_body).scrollTo(-width, 0) } private fun transformPageView(page: View, position: Float) { val pageWidth = page.width val pageHeight = page.height when { position < -1 -> page.alpha = 0f position <= 1 -> { val depth = 1f - abs(position) page.scaleX = depth page.scaleY = depth page.translationX = if (position > 0) { width * -position } else { width * position } page.alpha = 1f } else -> page.alpha = 0f } } private fun transformOutline(view: View, position: Float) { val width = view.width when { position <= -1 -> view.alpha = 0f position <= 0 -> { view.alpha = 1f view.findViewById<View>(R.id.img_back).translationX = -width * position / 2 view.findViewById<View>(R.id.img_shadow).translationX = -width * position / 8 } else -> { view.alpha = 1f view.findViewById<View>(R.id.img_back).translationX = -width * position / 2 view.findViewById<View>(R.id.img_shadow).translationX = -width * position / 8 } } } }
3. 自定义切换动效的实现方式:通过多个动画协同实现 ViewPager 切换动效
这种方式最为复杂,需要理解多种不同的动画实例,还要处理它们的交互和晨合,也需要处理 这些动画实例在相互上下文中的演绎关系。
viewPager!!.addOnPageChangeListener(object : ViewPager.OnPageChangeListener { override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) { var realCurrentPosition: Int var nextPosition: Int var realPositionOffset: Float var left: View? var right: View? val isLeftToRight = lastPosition < position if (isLeftToRight) { realCurrentPosition = position - 1 nextPosition = position realPositionOffset = positionOffset left = getViewByPosition(realCurrentPosition) right = getViewByPosition(nextPosition) } else { realCurrentPosition = position + 1 nextPosition = position realPositionOffset = 1 - positionOffset left = getViewByPosition(nextPosition) right = getViewByPosition(realCurrentPosition) } if (left != null) { val lp = left.layoutParams as FrameLayout.LayoutParams lp.width = (mContainerWidth - mTransformer!!.getOffsetWidth() - mTransformer!!.getMarginWidth()) / 2 + (mTransformer!!.getOffsetWidth() + mTransformer!!.getMarginWidth()) * realPositionOffset.toInt() left.layoutParams = lp } if (right != null) { val lp = right.layoutParams as FrameLayout.LayoutParams lp.width = (mContainerWidth - mTransformer!!.getOffsetWidth() - mTransformer!!.getMarginWidth()) / 2 + (mTransformer!!.getOffsetWidth() + mTransformer!!.getMarginWidth()) * (1 - realPositionOffset).toInt() right.layoutParams = lp } } override fun onPageScrollStateChanged(state: Int) { if (state == ViewPager.SCROLL_STATE_IDLE) { lastPosition = viewPager!!.currentItem } } override fun onPageSelected(position: Int) {} })
总结
为了提高用户的体验,我们应当在 Material Design 下,高效应对 ViewPager 切换效果的实现。给用户带来更为豪华、自然、流畅的视觉体验。本文中讨论了在 Material Design 下 ViewPager 切换动效的设计理念、三种实现方式及其案例分析。希望本文内容能为读者在开发中提供一些有益的技术指导。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/6594e100eb4cecbf2d92bc59