类似Launcher壁纸的视差背景效果

2024-01-10 18:10

本文主要是介绍类似Launcher壁纸的视差背景效果,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!


转载地址http://mp.weixin.qq.com/s?__biz=MzAxMTI4MTkwNQ==&mid=2650820494&idx=1&sn=1af3e5bd98e347ce9bde72f69d3802eb&scene=0#wechat_redirect


相信大家在切换手机launcher图标的时候,都会注意到后面的壁纸,仿佛是一张很大的壁纸在后面,每次切换图标页,壁纸会有一定的视差滚动效果。


那么这样一个效果是如何制作的呢?


那么本文的主要目的就是介绍这样的一个效果的制作原理。


首先看下效果图:




恩,其实这个是我在为wanandroid.com收录文章的时候发现的开源项目,项目地址是:


  • https://github.com/zhe525069676/BgMoveViewPager


当然本文不是造轮子,而是我觉得这样的效果有一定的实用价值,特地写出来分享下。


类似的库还有:


  • https://github.com/andraskindler/parallaxviewpager


如果大家有兴趣,建议大家在阅读完本文后,可以去看看上述两个项目的源码。


最后,需要说明本文的代码与上述库代码有一定的出入。



2思路   

其实写起来还是蛮简单的,只是如果找不到切入点就会觉得毫无头绪。


值得开心的是,在阅读完本文后,遇到类似的效果,你可能会会心一笑。


首先我们考虑下思路:


对于控件的选择,肯定首选ViewPager了,对于这样一个效果,仅仅将图片设置为ViewPager的背景是肯定不行的。


通过效果图,可以看得出来,图片可以伴随控件的移动,能够进行同步的移动。


所谓同步的移动,就是随着控件的scorllX的改变,绘制图片的区域会发生变化,那么我们在ViewPager滑动的过程中,我们需要找到一个方法,这个方法可以全程监听滑动,并且能够提供一定的参数帮助我们去定位图片该显示的区域。


2.1 思路一


这样的话,我们好像有思路了,我们可以为ViewPager设置setOnPageChangeListener,然后在onPageScrolled方法中,根据position和positionOffset的值,就可以确定图片需要显示的位置了,然后调用invalidate,去绘制指定的区域即可。


这样的确是可以的,parallaxviewpager就是这么做的,有兴趣的可以去看下代码。


除此以外还有别的思路。


2.2 思路二


既然ViewPager在滑动的时候,会不断的改变scrollX,那么我们可以直接在onDraw或者dispatchDraw中,去读取scrollX,根据scrollX确定需要绘制图像的区域,直接使用canvas绘制出来即可。


该思路为今天的代码主要演示的,对于onDraw和dispatchDraw,由于我们是ViewGroup,我们可以选择dispatchDraw来实现;当然,onDraw也是可以的,注意如果有必要记得调用setWillNotDraw(false)。


这样的话思路就明确了,我们重写dispatchDraw,再其内部根据scrollX区计算需要显示的区域,然后就想绘制,那么下面看代码。


3实现    3.1 初步实现



是不是感觉代码很短~


的确不长,为了方便,我们直接在类中加载了作为背景的图。


可以看到我们首先拿到图片的宽高,然后除以item的个数,确定每个item可以显示的图片宽度widthForItem


然后根据scrollX,比如初始在第1页(currentItem=0),scrollX为0,那么绘制的图片宽度区域就为:(0,widthForItem).


随着scrollX的变化,那么绘制的区域随之变为


(scrollX * widthForPerPx,  scrollX * widthForPerPx + widthForItem)


widthForPerPx的意思是,当控件移动一个像素,图片需要移动的像素值。


确定了需要绘制的图片区域,那么绘制的目标宽度区域,相比就很简单了,肯定是:


(scrollX , scrollX + getWidth());


认真分析完代码,感觉没什么问题,赶紧跑起来,效果已经实现了。


但是,不要高兴的太早,代码里面有个潜在的问题,不知道大家发现没有。



3.2 处理存在的问题


上述代码非常依赖scrollX,我们预期scrollX是从:


0 -> 控件width -> 控件width*2 这样变化。


但是,假设我们默认ViewPager设置为第2页(currentItem=1),你会发现效果图极其奇怪。



造成这样的原因是什么呢?


其实是因为,当currentItem=1时,scrollX的变化为:


-控件width -> 0 -> 控件width


当currentItem=2时,scrollX的变化为:


-控件width * 2 -> -控件width -> 0


而我们上述代码一直是以scrollX从0到最大来计算的。


所以,我们这里需要对scrollX进行处理:


  • 怎么处理呢?


if分类判断么,那太夸张了,页面一多得写多少if呀。


如果你对数字比较敏感,应该可以看出,上述虽然currentItem不同,但是变化的规律还是很明显的,我们可以总结规律,将其统一转化为:


0->控件width->控件width*2


那么就简单了,首先我们得到currentItem的值,然后让其乘以控件宽度,再加上scrollX,即:


int x = getScrollX() + mFirstPos * getWidth();


相关于给原本的变化统一加上了mFirstPos * getWidth(),看看上面的变化,恰好完成我们的转化需求。


那么最后完善下代码:



这样就基本完成所有的代码,当然很多细节的地方需要你自己去完善。


不过从该例,可以发现针对一个问题,找到切入点,先从最简单的情况出发,编写完成后,在针对各种情况做调整即可。


4扩展   

最后,我们根据上例效果,可以做的事情还很多,假设我们有一张宽度大概为1.6倍屏幕宽度的图片,ViewPager包含3个Item。


均分为3等分拉伸效果肯定不好,其实你可以不拉伸,让当前屏幕显示同等宽度的图片,每切换一页,你图片移动总宽度为屏幕宽度的0.3即可,相信根据上文的代码你应该可以做出来。


5写在最后   

昨天的推送文章被指出太简单,有人发出类似疑问:


你是没有东西写了么?能不能发点干货?


这里我简单解释下,首先我感谢提出的意见,相比大家关注我的公众号肯定都是为了能够学到一些东西的,当然不排除那些为了和我搞基的。


为了这样一个目标,我也保持着每周3-5篇,尽可能推送`看起来不太费劲`又能`学到知识`的文章。


需要抱歉的是,我目前没有任何办法做到每天的文章都能符合所有人的口味,所以我希望如果文章对你来说太简单,你可以选择不看或者简单的看一下,权当巩固下记忆也好。


过分的抱怨会伤害到我以及原创作者,毕竟一篇文章,能够从作者写出来到推送到大家的手机上消耗了大量的时间与精力。并且个人长期的坚持分享与大家的支持是分不开的。


你可以试想下,你有个花了了大量时间与精力做的东西,给别人分享时,被别人泼冷水的时感受。


所以有可能的话,尽量可以:不要吐槽,随手点赞,给作者一点支持和鼓励。


当然,合理的意见是没问题的,比如你可以换个语气:


最近的文章好像有点偏简单,我最近在研究长得太帅的人如何与他人相处,可否推送相关文章?


我会根据大家的留言,对文章的选择有个大致的方向,并且我可以承诺,所有的文章我都有细心的编辑,在我所能做到的情况下,保证大家有个良好的阅读体验。


最后衷心的感谢投稿的作者、长期支持我的你们、默默关注我的你们以及给我提建议的朋友。


源码地址:

https://github.com/hongyangAndroid/Android_Blog_Demos


这篇关于类似Launcher壁纸的视差背景效果的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/591635

相关文章

Android实现任意版本设置默认的锁屏壁纸和桌面壁纸(两张壁纸可不一致)

客户有些需求需要设置默认壁纸和锁屏壁纸  在默认情况下 这两个壁纸是相同的  如果需要默认的锁屏壁纸和桌面壁纸不一样 需要额外修改 Android13实现 替换默认桌面壁纸: 将图片文件替换frameworks/base/core/res/res/drawable-nodpi/default_wallpaper.*  (注意不能是bmp格式) 替换默认锁屏壁纸: 将图片资源放入vendo

防近视护眼台灯什么牌子好?五款防近视效果好的护眼台灯推荐

在家里,灯具是属于离不开的家具,每个大大小小的地方都需要的照亮,所以一盏好灯是必不可少的,每个发挥着作用。而护眼台灯就起了一个保护眼睛,预防近视的作用。可以保护我们在学习,阅读的时候提供一个合适的光线环境,保护我们的眼睛。防近视护眼台灯什么牌子好?那我们怎么选择一个优秀的护眼台灯也是很重要,才能起到最大的护眼效果。下面五款防近视效果好的护眼台灯推荐: 一:六个推荐防近视效果好的护眼台灯的

第49课 Scratch入门篇:骇客任务背景特效

骇客任务背景特效 故事背景:   骇客帝国特色背景在黑色中慢慢滚动着! 程序原理:  1 、 角色的设计技巧  2 、克隆体的应用及特效的使用 开始编程   1、使用 黑色的背景: ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/7d74c872f06b4d9fbc88aecee634b074.png#pic_center)   2

数据中台出现的背景

数据中台产生背景 数据建设中出现的问题 在企业数据建设过程中,都离不开大数据平台建设,大数据平台建设涉及数据采集、数据存储、数据仓库构建、数据处理分析、数据挖掘、数据可视化等一系列流程。 随着企业体量不断增大,一个企业可能有总公司及很多子公司,随着企业各类业务多元化和垂直业务发展,从全企业角度来看,每个子公司或者某些独立的业务部都在构建大数据分析平台,在企业内部形成了很多分散、烟囱式、独立的

PNG透明背景按钮的实现(MFC)

问题描述: 当前要在对话框上添加一个以两个PNG图片作为背景的按钮,PNG图的背景是透明的,按钮也要做出相同的透明效果。并且鼠标不在按钮上时,按钮显示"bg1.png";鼠标移动到按钮上时,按钮显示"bg2.png" 开发环境为VS2010。 解决办法: 使用GDI+库装载PNG图片,并使用MFC Button Control和CMFCButton类结合,调用CMFCButton

【Godot4.3】多边形的斜线填充效果基础实现

概述 图案(Pattern)填充是一个非常常见的效果。其中又以斜线填充最为简单。本篇就探讨在Godot4.3中如何使用Geometry2D和CanvasItem的绘图函数实现斜线填充效果。 基础思路 Geometry2D类提供了多边形和多边形以及多边形与折线的布尔运算。按照自然的思路,多边形的斜线填充应该属于“多边形与折线的布尔运算”范畴。 第一个问题是如何获得斜线,这条斜线应该满足什么样

UniApp实现漂亮的音乐歌词滚动播放效果

在现代的音乐播放应用中,歌词的展示和滚动播放已经成为了一个非常常见的功能。今天,我们将通过UniApp来实现一个漂亮的歌词滚动播放功能。我们将使用UniApp提供的组件和API来完成这个任务。 页面结构 在页面的模板部分,我们需要创建一个音频播放器和歌词展示区域。使用<scroll-view>组件来实现歌词的滚动效果。 <template><view class="audio-co

Nuxt3入门:过渡效果(第5节)

你好同学,我是沐爸,欢迎点赞、收藏、评论和关注。 Nuxt 利用 Vue 的 <Transition> 组件在页面和布局之间应用过渡效果。 一、页面过渡效果 你可以启用页面过渡效果,以便对所有页面应用自动过渡效果。 nuxt.config.js export default defineNuxtConfig({app: {pageTransition: {name: 'fade',mode

Differential Diffusion,赋予每个像素它应有的力量,以及在comfyui中的测试效果

🥽原论文要点 首先是原论文地址:https://differential-diffusion.github.io/paper.pdf 其次是git介绍地址:GitHub - exx8/differential-diffusion 感兴趣的朋友们可以自行阅读。 首先,论文开篇就给了一个例子: 我们的方法根据给定的图片和文本提示,以不同的程度改变图像的不同区域。这种可控性允许我们再现