类似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

相关文章

Kotlin Compose Button 实现长按监听并实现动画效果(完整代码)

《KotlinComposeButton实现长按监听并实现动画效果(完整代码)》想要实现长按按钮开始录音,松开发送的功能,因此为了实现这些功能就需要自己写一个Button来解决问题,下面小编给大... 目录Button 实现原理1. Surface 的作用(关键)2. InteractionSource3.

使用WPF实现窗口抖动动画效果

《使用WPF实现窗口抖动动画效果》在用户界面设计中,适当的动画反馈可以提升用户体验,尤其是在错误提示、操作失败等场景下,窗口抖动作为一种常见且直观的视觉反馈方式,常用于提醒用户注意当前状态,本文将详细... 目录前言实现思路概述核心代码实现1、 获取目标窗口2、初始化基础位置值3、创建抖动动画4、动画完成后

uniapp小程序中实现无缝衔接滚动效果代码示例

《uniapp小程序中实现无缝衔接滚动效果代码示例》:本文主要介绍uniapp小程序中实现无缝衔接滚动效果的相关资料,该方法可以实现滚动内容中字的不同的颜色更改,并且可以根据需要进行艺术化更改和自... 组件滚动通知只能实现简单的滚动效果,不能实现滚动内容中的字进行不同颜色的更改,下面实现一个无缝衔接的滚动

Java实现图片淡入淡出效果

《Java实现图片淡入淡出效果》在现代图形用户界面和游戏开发中,**图片淡入淡出(FadeIn/Out)**是一种常见且实用的视觉过渡效果,它可以用于启动画面、场景切换、轮播图、提示框弹出等场景,通过... 目录1. 项目背景详细介绍2. 项目需求详细介绍2.1 功能需求2.2 非功能需求3. 相关技术详细

使用animation.css库快速实现CSS3旋转动画效果

《使用animation.css库快速实现CSS3旋转动画效果》随着Web技术的不断发展,动画效果已经成为了网页设计中不可或缺的一部分,本文将深入探讨animation.css的工作原理,如何使用以及... 目录1. css3动画技术简介2. animation.css库介绍2.1 animation.cs

Flutter实现文字镂空效果的详细步骤

《Flutter实现文字镂空效果的详细步骤》:本文主要介绍如何使用Flutter实现文字镂空效果,包括创建基础应用结构、实现自定义绘制器、构建UI界面以及实现颜色选择按钮等步骤,并详细解析了混合模... 目录引言实现原理开始实现步骤1:创建基础应用结构步骤2:创建主屏幕步骤3:实现自定义绘制器步骤4:构建U

Vue项目的甘特图组件之dhtmlx-gantt使用教程和实现效果展示(推荐)

《Vue项目的甘特图组件之dhtmlx-gantt使用教程和实现效果展示(推荐)》文章介绍了如何使用dhtmlx-gantt组件来实现公司的甘特图需求,并提供了一个简单的Vue组件示例,文章还分享了一... 目录一、首先 npm 安装插件二、创建一个vue组件三、业务页面内 引用自定义组件:四、dhtmlx

前端原生js实现拖拽排课效果实例

《前端原生js实现拖拽排课效果实例》:本文主要介绍如何实现一个简单的课程表拖拽功能,通过HTML、CSS和JavaScript的配合,我们实现了课程项的拖拽、放置和显示功能,文中通过实例代码介绍的... 目录1. 效果展示2. 效果分析2.1 关键点2.2 实现方法3. 代码实现3.1 html部分3.2

css渐变色背景|<gradient示例详解

《css渐变色背景|<gradient示例详解》CSS渐变是一种从一种颜色平滑过渡到另一种颜色的效果,可以作为元素的背景,它包括线性渐变、径向渐变和锥形渐变,本文介绍css渐变色背景|<gradien... 使用渐变色作为背景可以直接将渐China编程变色用作元素的背景,可以看做是一种特殊的背景图片。(是作为背

基于Python实现PDF动画翻页效果的阅读器

《基于Python实现PDF动画翻页效果的阅读器》在这篇博客中,我们将深入分析一个基于wxPython实现的PDF阅读器程序,该程序支持加载PDF文件并显示页面内容,同时支持页面切换动画效果,文中有详... 目录全部代码代码结构初始化 UI 界面加载 PDF 文件显示 PDF 页面页面切换动画运行效果总结主