使用方法:

mBinding.bnBanner.setOnPageChangeListener(object : OnPageChangeListener {val viewScrollGradientHelper = BannerScrollGradientHelper(mBinding.bannerCurrentBg, mBinding.bannerWillShowBg)override fun onPageScrollStateChanged(p0: Int) {}override fun onPageScrolled(position: Int, offsetPercent: Float, offsetPx: Int) {// offsetPercent 代表当前滑动的比例,往后滑动【从0到1区间渐渐变大】,往前滑动【从1到0区间渐渐变小】// 开始渐变滑动viewScrollGradientHelper.startGradientByOffsetPercent(requireContext(), position, offsetPercent, offsetPx, bean.bannerBgUrlList) {// banner滑动到某个位置的埋点dataTrackOnBanner(bean.list, position)}}override fun onPageSelected(position: Int) {}})

思路:

根据banner滑动监听,滑动的比例offsetPercent (【offsetPercent】0~1,往下一张滑动从0到1变大,往上一张滑动从1到0变小) 逐渐改变透明度;两张背景图交替变化为当前图控件和将要显示的控件(为了处理图片闪烁问题,透明度瞬间改变有闪烁);

资源准备:

1.banner控件:来自三方控件

// gradle中引入
api 'com.youth.banner:banner:1.4.10'

2. 布局(嵌套到你的父布局中,显示banner的位置):

<!-- banner底部背景 -->
<FrameLayoutandroid:id="@+id/frame_banner"android:layout_width="match_parent"android:layout_height="225dp"android:visibility="gone"app:layout_constraintTop_toTopOf="parent"tools:visibility="visible"><!-- 背景图A 当前背景图 --><ImageViewandroid:id="@+id/banner_current_bg"android:layout_width="match_parent"android:layout_height="match_parent"android:alpha="1"android:scaleType="centerCrop" /><!-- 背景图B 将要展示的背景图 --><ImageViewandroid:id="@+id/banner_will_show_bg"android:layout_width="match_parent"android:layout_height="match_parent"android:alpha="0"android:scaleType="centerCrop" /><!-- 前景图banner --><com.youth.banner.Bannerandroid:id="@+id/bn_banner"android:layout_width="match_parent"android:layout_height="225dp"android:layout_gravity="center"app:indicator_height="3dp"app:indicator_margin="3dp"app:indicator_width="9dp"app:scroll_time="1600"tools:background="@drawable/banner_placeholder"tools:visibility="gone" />
</FrameLayout>

3. 滑动渐变帮助类:

package com.xxx.helperimport android.content.Context
import android.widget.ImageView
import com.czb.chezhubang.base.utils.GlideUtils
import kotlin.math.roundToInt/*** @author: lwp* @date: 6/22/21* @description: banner 滑动渐变帮助类*/
class BannerScrollGradientHelper constructor(private val mBannerCurrentBg: ImageView, private val mBannerWillShowBg: ImageView) {/*** 上次记录的偏移量百分比(0f~1f)取值*/private var preOffsetPercent: Float = 0f/*** 上次加载最终位置图的index,用来去重同样值的回调*/private var preLoadFinalImagePosition = -1/*** 真正的当前显示的图的ImageView控件(根据当前透明度计算,透明度为1的为当前图的ImageView)*/private var currentImageView: ImageView? = null/*** 真正的将要显示的下张图的ImageView控件((根据最终停止滑动的最后一次回调的透明度计算,透明度为1的为下张显示图的ImageView)*/private var willShowImageView: ImageView? = null/*** banner滚动方向 true是下一张,false是上一张*/private var bannerWillScrollToNext = true/*** 判断banner的onScroll回调里是否设置了方向的值,用来去除重复赋值*/private var isJudgeScrollAndSetScrollNextValue = false/*** 上次滚动中加载图的位置index*/private var preLoadImagePositionOnScrolling = -1/*** @param context 上下文* @param position 位置* @param offsetPercent 滑动的偏移百分比(0~1之间)* @param offsetPx 滑动偏移的像素* @param imageUrlList 渐变的list URL* @param onScrollFinishListener 滚动完毕回调*/fun startGradientByOffsetPercent(context: Context, position: Int,offsetPercent: Float,offsetPx: Int,imageUrlList: MutableList<String>,onScrollFinishListener: () -> Unit) {// 滑动的图的数组长度val imageUrlListSize = imageUrlList.sizeif (currentImageView == null) {currentImageView = getCurrentImageView()}if (willShowImageView == null) {willShowImageView = getWillShowImageView()}if (offsetPercent > 0f && preOffsetPercent > 0) {// 获取将要滑动的方向if (!isJudgeScrollAndSetScrollNextValue) {isJudgeScrollAndSetScrollNextValue = truebannerWillScrollToNext = offsetPercent - preOffsetPercent > 0}// 判断滑动方向if (bannerWillScrollToNext) {if (preLoadImagePositionOnScrolling != position) {preLoadImagePositionOnScrolling = position/*** 当往后一张滑动时候,position的值是当前张的值*/GlideUtils.loadImage(context, currentImageView, imageUrlList[position % imageUrlListSize])// 下一个GlideUtils.loadImage(context, willShowImageView, imageUrlList[(position + 1) % imageUrlListSize])}// 逐渐改变透明度,根据滑动偏移量比例// 当前page渐渐透明currentImageView?.alpha = 1 - offsetPercent// 下一张page渐渐显示willShowImageView?.alpha = offsetPercent} else {// preLoadImagePositionOnScrolling:去重,避免重复执行if (preLoadImagePositionOnScrolling != position) {preLoadImagePositionOnScrolling = position/*** 当往前一张滑动时候,position的值是上一张的值*/// 当前图GlideUtils.loadImage(context, currentImageView, imageUrlList[(position + 1) % imageUrlListSize])// 上一张GlideUtils.loadImage(context, willShowImageView, imageUrlList[position % imageUrlListSize])}// 逐渐改变透明度,根据滑动偏移量比例currentImageView?.alpha = offsetPercentwillShowImageView?.alpha = 1 - offsetPercent}}// 记录上次的滑动百分比,大于0表示开始滑动了preOffsetPercent = offsetPercent// offsetPercent和offsetPx 等于0代表最后一次滑动回调;preLoadFinalImagePosition去重,避免重复执行if (offsetPercent == 0f && offsetPx == 0 && position != preLoadFinalImagePosition) {preLoadFinalImagePosition = position// 最后一次滑动onTheLastScrollCallback(context, imageUrlList, position)// 滑动完成回调onScrollFinishListener?.invoke()}}/*** 最后的滑动回调*/private fun onTheLastScrollCallback(context: Context, imageUrlList: MutableList<String>, position: Int) {// 展示最终的图片showFinalImage(context, imageUrlList, position)}/*** 展示最终的图片*/private fun showFinalImage(context: Context, imageUrlList: MutableList<String>, position: Int) {// 设置最终的透明度,四舍五入,接近0的透明度为0,接近1的透明度为1,两个控件分别对应其中的一种情况,不会同时为0或1mBannerWillShowBg.alpha = mBannerWillShowBg.alpha.roundToInt() * 1fmBannerCurrentBg.alpha = mBannerCurrentBg.alpha.roundToInt() * 1fval willShowAlpha = mBannerWillShowBg.alpha// 展示alpha为1的控件,避免自动滑动的时候闪烁GlideUtils.loadImage(context, if (willShowAlpha == 1f) {mBannerWillShowBg} else {mBannerCurrentBg}, imageUrlList[position.let {if (it >= imageUrlList.size) {0} else {it}}])// 透明度为0的设置为空图资源if (willShowAlpha == 0f) {mBannerWillShowBg} else {mBannerCurrentBg}.setImageResource(0)// 重置一些记录变量resetRecordData()}/*** 重置记录的数据*/private fun resetRecordData() {isJudgeScrollAndSetScrollNextValue = falsepreLoadImagePositionOnScrolling = -1currentImageView = nullwillShowImageView = null}/*** @return 将返回透明度alpha为1的控件*/private fun getCurrentImageView(): ImageView {return if (mBannerCurrentBg.alpha == 1f) {mBannerCurrentBg} else {mBannerWillShowBg}}/*** @return 将返回透明度alpha为0的控件*/private fun getWillShowImageView(): ImageView {return if (mBannerCurrentBg.alpha == 0f) {mBannerCurrentBg} else {mBannerWillShowBg}}}

banner前后两张图实现滑动前景图背景图渐变效果(类似自如app的banner效果)相关推荐

  1. H5页面设置背景图,微信可浏览背景图

    最近做项目需要在微信播放视频,设置播放的背景图,折腾了好久 <div class="video-back" :style="{backgroundImage: 'u ...

  2. div自适应背景图的尺寸:设置背景图的方式;img作为div元素的方式

    目录 零.问题描述和基本情况介绍 案例: 问题及疑问: 一.background-size:cover;和background-size:100%;的区别: 1.background-size:100 ...

  3. php怎么添加背景图html,html怎么导入背景图

    html导入背景图的方法:1.用html标签插入图片,这里直接在img标签中使用src属性:2.用css插入,在div中设置class属性为img2,在script标签中使用background标签插 ...

  4. css 通过background将两张图合成一张图显示

    需求背景: 后台返回两张图,一张是默认背景图bgimg,另一张是显示在背景上的图案img. 在列表中,bgimg一般不变,但img会根据不同的花的类型返回不同的图片. 需求是将两张图片叠在一起,让人以 ...

  5. word表格分开快捷键_Word利用快捷键在两张以上无缝表格之间或表格前插入文字...

    在制作 Word 文档过程中,偶尔会遇到这样一种情况,就是要在两张或多张无缝表格之间插入文字,由于输入文字前必须插入光标,恰恰在无缝表格之间不容易插入光标,应该怎么办呢?毫无疑问把表格分离,至于如何分 ...

  6. ArcGIS中做一张新闻1+1演播厅背景图(附世界矢量地图.shp下载)

    ArcGIS中做一张新闻1+1演播厅背景图(附世界矢量地图.shp下载) 前段时间ceibake大佬的博客终于更新了,介绍了关于ArcMap中如何一张新闻1+1演播厅的背景图. 就是那张由点组成的世界 ...

  7. Android素描算法及实现手指在图片上左右滑动调节图片透明度,最终实现类似调节素描浓度的效果

    一.前期基础知识储备 UI掌握PS这一逆天的软件,可以实现将图片转化为素描或者水彩的效果,以素描为例: 在Photoshop中打开一张人物照片,按下快捷键"Ctrl+Shift+U" ...

  8. creator图片循环显示_CocosCreator背景图循环播放

    以前在玩小游戏的时候发现有的小游戏背景图一直再动,视觉效果挺好,给人一种炫炫的感觉,让我这写后台的码农很是羡慕和膜拜.没想到天意弄人,我也开始写游戏前端了刚接触CocosCreator,好多东西都不懂 ...

  9. Tableau学习笔记(进阶)——(7)多边形地图和背景图地图:设置地理信息(自定义地图码导入、设置地图源)

    上一小节链接. 目录 1.多边形地图 1.1 多边形地图的相关概念 1.2 英国国家公园多边形地图 2.设置地理信息 2.1 自定义地理码导入 (1)扩展现有角色: (2)新加角色 (3)添加新分层结 ...

最新文章

  1. 用ZipInputStream和ZipOutputStream实现文件及文件夹的压缩解压
  2. ecmall数据库表详解 二次开发必备
  3. 【实验吧】CTF_Web_简单的SQL注入之1
  4. deepin深度启动盘制作工具下载地址
  5. 输入法注入源码_将注入进行到底:利用Mono注入C#游戏脚本
  6. 太难得了!大厂数据分析实战项目资料首次公开!免费,速领!
  7. 实验5_JPEG解码
  8. java读取TXT文件的方法
  9. 问题 B: 数塔问题
  10. Django 第八课 3.【MySQL问题】
  11. H.264标准(三)F4V封装格式详解
  12. java代码性能优化
  13. php 中英文互换,php做项目进行中英文的切换,如何快速实现
  14. 图灵奖得主都写过哪些书?
  15. win10关机后cpu风扇还在转_win10系统关机后风扇还转的解决方法
  16. CVTE校招嵌入式经历
  17. 练习2-6 编写一个函数setbits(x, p ,n, y),该函数返回对x执行下列操作后的结果值: 将x中从第p位开始的n个(二进制)位设置为y中最右边n位的值,x的其余各位保持不变。
  18. 11届蓝桥杯青少年组C++全国赛高级组
  19. ‘xxxx’ does not name a type报错处理方法
  20. struct stat结构体中st_mode参数的含义

热门文章

  1. 大家都用得起的Revit工具,BIM建模助手正式上线
  2. 美团项目 --- 搜索栏及推荐 6
  3. 在word文档中如何输入复杂的公式,和特殊符号
  4. 困惑度perplexity
  5. C语言数据结构之二叉排序树
  6. 科东软件与工信部电子五所达成战略合作,共同推动国产工业基础软件高质量发展
  7. 蓝牙inquiry流程之Advertising Report
  8. php咖啡管理系统论文,数据库课程设计--“茶咖啡”销售管理系统总结
  9. Splash界面使用动画
  10. ARCHICAD 21—三维建筑设计工具