电影电视剧网红广告屏轮播介绍视频特效制作,Compose轻松实现

视频特效动画制作,广告中占据了大多数,对于程序员来讲,费时费力的事情。

用Compose写出动画,然后录屏成视频转化后的GIF效果,本身是带 音乐背景 的。

先来看效果图GIF一

效果图GIF二:

哪吒2魔童脑海已经冲到了全球票房 第5了

一、前言

广告视频作为现代营销的核心工具,其意义远超传统广告形式,通过视听结合的方式,能够更高效地传递信息、激发情感共鸣并推动商业目标实现。

本文来介绍最简单的自动横向滚动广告视频动画用Compose怎么制作出来。

  1. 制作数据模型,可扩展,可自定义,
  2. 每一个Item的compose 可扩展自定义。
  3. 涉及到compose 的 Column ,LazyRow ,rememberLazyListState(),snapshotFlow 的用法
  4. 涉及到compose 的 LaunchedEffect,DisposableEffect 的用法
  5. 涉及到compose 中ExoPlayer 怎么播放音乐
  6. 涉及到compose 中 Glide怎么去给视图加载背景图片

二、数据模型设计

ScrollViewModel:滚动模型数据, 其中:
title:广告标题
showCount:屏幕可见个数,设置为0没有开始那个动画
list:数据集
bgImg:背景图片
musicUrl:音乐文件地址
itemWidth:屏幕显示个数的单个UI宽度
isPlayComplete:是否滚动到头了,控制音乐播放结束
tweenTimeL:前几个单个动画执行动画时间
colorNo:排名序号颜色
noFontSize:排名序号字体大小
colorTitle:单个标题颜色
titleFontSize:单个标题字体大小
colorValue:单个值颜色 valueFontSize:单个值字体大小

kotlin 复制代码
data class ScrollViewModel(
    val title: String,  //标题
    val showCount: Int, //UI宽度下刚好显示个数
    val list: MutableList<out TopDataSource>,//数据
    val bgImg: String = "", //背景图片
    val musicUrl: String = "" //背景音乐
) {
    var itemWidth = 0  //屏幕显示个数的单个UI宽度
    var isPlayComplete = false //是否滚动到头了,控制音乐播放结束
    var tweenTimeL = 3000L //前几个单个动画执行动画时间

    @Stable
    var colorNo = Color.Yellow //排名序号颜色
    var noFontSize = 23 //排名序号字体大小

    @Stable
    var colorTitle = Color.White  //单个标题颜色
    var titleFontSize = 18  //单个标题字体大小

    @Stable
    var colorValue = Color.White //单个值颜色
    var valueFontSize = 22 //单个值字体大小

    val tweenTimeI: Int
        get() = tweenTimeL.toInt()

    var formatString: String = ""//数字格式化设置
    var multiplier: Float = 1f//数据显示格式所用的乘数

    fun getTextValueFormat(value: Float): String {
        return formatString.format(value * multiplier)
    }
}

数据集属性,open式,可以扩展:
title:单条数据标题
img: 单条数据图片地址
value:数据值

kotlin 复制代码
open class TopDataSource(
val title: String, //单条数据标题  
val img: String,  //单条数据图片地址  
val value: Float  //数据值
)

三、真正使用

1、repositories中添加如下maven

rust 复制代码
   repositories {
        maven { url 'https://repo1.maven.org/maven2/' }
        maven { url 'https://s01.oss.sonatype.org/content/repositories/releases/' }
    }
}

2、 dependencies中添加依赖

scss 复制代码
implementation("io.github.wgllss:Wgllss-Scroll-View:1.0.02")

3、ViewModel中使用 准备好数据,和所有数据模型配置,都在里面

less 复制代码
class DhListViewModel : ViewModel() {

    private val _datas = MutableLiveData<ScrollViewModel>()
    val datas: LiveData<ScrollViewModel> = _datas

    fun add() {
        viewModelScope.launch {
            val list = mutableListOf<TopDataSource>()
            list.add(TopDataSource("阿凡达", "https://bkimg.cdn.bcebos.com/smart/6f061d950a7b02087bf48857e581e5d3572c11df6276-bkimg-process,v_1,rw_1,rh_1,maxl_216,pad_1,color_ffffff?x-bce-process=image/format,f_auto", 212.0f))
            list.add(TopDataSource("复仇者联盟4:终局之战", "https://bkimg.cdn.bcebos.com/smart/2cf5e0fe9925bc31a5ffa7e950df8db1cb137025-bkimg-process,v_1,rw_1,rh_1,maxl_216,pad_1,color_ffffff?x-bce-process=image/format,f_auto", 202.99f))
            list.add(TopDataSource("阿凡达:水之道", "https://bkimg.cdn.bcebos.com/smart/e7cd7b899e510fb30f24192fab6bdf95d143ad4ba649-bkimg-process,v_1,rw_1,rh_1,maxl_216,pad_1,color_ffffff?x-bce-process=image/format,f_auto", 168.25f))
            list.add(TopDataSource("泰坦尼克号", "https://bkimg.cdn.bcebos.com/smart/f3d3572c11dfa9ec8a132753ae86e003918fa0ec6b62-bkimg-process,v_1,rw_1,rh_1,maxl_216,pad_1,color_ffffff?x-bce-process=image/format,f_auto", 164.23f))
            list.add(TopDataSource("哪吒之魔童闹海", "https://bkimg.cdn.bcebos.com/smart/09fa513d269759ee3d6ddbeb3ea254166d224f4a71c3-bkimg-process,v_1,rw_1,rh_1,maxl_216,pad_1,color_ffffff?x-bce-process=image/format,f_auto", 155.05f))
            list.add(TopDataSource("星球大战:原力觉醒", "https://bkimg.cdn.bcebos.com/smart/6c224f4a20a4462389da25bc9e22720e0df3d7d8-bkimg-process,v_1,rw_1,rh_1,maxl_216,pad_1,color_ffffff?x-bce-process=image/format,f_auto", 150.19f))
            list.add(TopDataSource("复仇者联盟3:无限战争", "https://bkimg.cdn.bcebos.com/smart/d31b0ef41bd5ad6eddc41b61f2932edbb6fd536696ba-bkimg-process,v_1,rw_1,rh_1,maxl_216,pad_1,color_ffffff?x-bce-process=image/format,f_auto", 148.82f))
            list.add(TopDataSource("蜘蛛侠:英雄无归", "https://bkimg.cdn.bcebos.com/smart/f3d3572c11dfa9ec8a13ddc33088e003918fa1ec6b94-bkimg-process,v_1,rw_1,rh_1,maxl_216,pad_1,color_ffffff?x-bce-process=image/format,f_auto", 141.6f))
            list.add(TopDataSource("头脑特工队2", "https://bkimg.cdn.bcebos.com/smart/b3fb43166d224f4a20a4c53494af87529822720e7bd9-bkimg-process,v_1,rw_1,rh_1,maxl_216,pad_1,color_ffffff?x-bce-process=image/format,f_auto", 123.19f))
            list.add(TopDataSource("侏罗纪世界", "https://bkimg.cdn.bcebos.com/smart/d62a6059252dd42a2834f25c70634cb5c9ea14ce1289-bkimg-process,v_1,rw_1,rh_1,maxl_216,pad_1,color_ffffff?x-bce-process=image/format,f_auto", 121.2f))
            list.add(TopDataSource("狮子王", "https://bkimg.cdn.bcebos.com/smart/aa18972bd40735fae6cde368af0118b30f2443a7a298-bkimg-process,v_1,rw_1,rh_1,maxl_216,pad_1,color_ffffff?x-bce-process=image/format,f_auto", 120.51f))
            list.add(TopDataSource("复仇者联盟", "https://bkimg.cdn.bcebos.com/smart/caef76094b36acaf24a1fd5772d98d1000e99cd3-bkimg-process,v_1,rw_1,rh_1,maxl_216,pad_1,color_ffffff?x-bce-process=image/format,f_auto", 110.26f))
            list.add(TopDataSource("速度与激情7", "https://bkimg.cdn.bcebos.com/smart/5d6034a85edf8db1cb135ac97b7bca54564e9258de5c-bkimg-process,v_1,rw_1,rh_1,maxl_216,pad_1,color_ffffff?x-bce-process=image/format,f_auto", 109.88f))
            list.add(TopDataSource("壮志凌云2:独行侠", "https://bkimg.cdn.bcebos.com/smart/9213b07eca8065380cd78040a988b644ad3459822411-bkimg-process,v_1,rw_1,rh_1,maxl_216,pad_1,color_ffffff?x-bce-process=image/format,f_auto", 108.45f))
            list.add(TopDataSource("冰雪奇缘2", "https://bkimg.cdn.bcebos.com/smart/2e2eb9389b504fc2a7b68177eadde71191ef6dd2-bkimg-process,v_1,rw_1,rh_1,maxl_216,pad_1,color_ffffff?x-bce-process=image/format,f_auto", 105.41f))
            list.add(TopDataSource("芭比", "https://bkimg.cdn.bcebos.com/smart/0e2442a7d933c895d143dc1db14464f082025aafaa04-bkimg-process,v_1,rw_1,rh_1,maxl_216,pad_1,color_ffffff?x-bce-process=image/format,f_auto", 104.93f))
            list.add(TopDataSource("复仇者联盟2:奥创纪元", "https://bkimg.cdn.bcebos.com/smart/0df3d7ca7bcb0a469f9d6c986f63f6246a60afd0-bkimg-process,v_1,rw_1,rh_1,maxl_216,pad_1,color_ffffff?x-bce-process=image/format,f_auto", 101.88f))
            list.add(TopDataSource("超级马力欧兄弟大电影", "https://bkimg.cdn.bcebos.com/smart/500fd9f9d72a6059252d735bb862239b033b5bb50c61-bkimg-process,v_1,rw_1,rh_1,maxl_216,pad_1,color_ffffff?x-bce-process=image/format,f_auto", 98.68f))
            list.add(TopDataSource("黑豹", "https://bkimg.cdn.bcebos.com/smart/86d6277f9e2f0708283863716a7caf99a9014c085433-bkimg-process,v_1,rw_1,rh_1,maxl_216,pad_1,color_ffffff?x-bce-process=image/format,f_auto", 97.88f))
            list.add(TopDataSource("哈利·波特与死亡圣器(下)", "https://bkimg.cdn.bcebos.com/smart/d0c8a786c9177f3ed1aacd6372cf3bc79e3d56c5-bkimg-process,v_1,rw_1,rh_1,maxl_216,pad_1,color_ffffff?x-bce-process=image/format,f_auto", 97.35f))
            list.add(TopDataSource("死侍与金刚狼", "https://bkimg.cdn.bcebos.com/smart/0b46f21fbe096b63f624ec34aa6b9044ebf81a4c0604-bkimg-process,v_1,rw_1,rh_1,maxl_216,pad_1,color_ffffff?x-bce-process=image/format,f_auto", 97.02f))
            list.add(TopDataSource("星球大战:最后的绝地武士", "https://bkimg.cdn.bcebos.com/smart/14ce36d3d539b6003af39b474806222ac65c113819be-bkimg-process,v_1,rw_1,rh_1,maxl_216,pad_1,color_ffffff?x-bce-process=image/format,f_auto", 96.76f))
            list.add(TopDataSource("侏罗纪世界2", "https://bkimg.cdn.bcebos.com/smart/e824b899a9014c08ae6e4c53077b02087af4f4eb-bkimg-process,v_1,rw_1,rh_1,maxl_216,pad_1,color_ffffff?x-bce-process=image/format,f_auto", 95.02f))
            list.add(TopDataSource("冰雪奇缘", "https://bkimg.cdn.bcebos.com/smart/a6efce1b9d16fdfaaf51f747c6d79b5494eef01fcd58-bkimg-process,v_1,rw_1,rh_1,maxl_216,pad_1,color_ffffff?x-bce-process=image/format,f_auto", 94.73f))
            list.add(TopDataSource("钢铁侠3", "https://bkimg.cdn.bcebos.com/smart/b3fb43166d224f4a5bf0fa380bf790529822d1b4-bkimg-process,v_1,rw_1,rh_1,maxl_216,pad_1,color_ffffff?x-bce-process=image/format,f_auto", 91.81f))
            list.add(TopDataSource("美女与野兽", "https://bkimg.cdn.bcebos.com/smart/3ac79f3df8dcd10043450c6f7b8b4710b8122fa7-bkimg-process,v_1,rw_1,rh_1,maxl_216,pad_1,color_ffffff?x-bce-process=image/format,f_auto", 91.81f))
            list.add(TopDataSource("超人总动员2", "https://bkimg.cdn.bcebos.com/smart/e1fe9925bc315c6034a8bff32ce7dc1349540923d92a-bkimg-process,v_1,rw_1,rh_1,maxl_216,pad_1,color_ffffff?x-bce-process=image/format,f_auto", 90.15f))
            list.add(TopDataSource("速度与激情8", "https://bkimg.cdn.bcebos.com/smart/203fb80e7bec54e736d1daa6cb608c504fc2d5623c48-bkimg-process,v_1,rw_1,rh_1,maxl_216,pad_1,color_ffffff?x-bce-process=image/format,f_auto", 89.62f))
            list.add(TopDataSource("小黄人大眼萌", "https://bkimg.cdn.bcebos.com/smart/c2cec3fdfc03924562bbc7148194a4c27d1e259a-bkimg-process,v_1,rw_1,rh_1,maxl_216,pad_1,color_ffffff?x-bce-process=image/format,f_auto", 84.07f))
            list.add(TopDataSource("美国队长3:内战", "https://bkimg.cdn.bcebos.com/smart/cc11728b4710b912bb7f8d69c4fdfc03934522ee-bkimg-process,v_1,rw_1,rh_1,maxl_216,pad_1,color_ffffff?x-bce-process=image/format,f_auto", 83.75f))
            list.add(TopDataSource("海王", "https://bkimg.cdn.bcebos.com/smart/f7246b600c338744b135f9ce5c0fd9f9d62aa094-bkimg-process,v_1,rw_1,rh_1,maxl_216,pad_1,color_ffffff?x-bce-process=image/format,f_auto", 83.53f))
            list.add(TopDataSource("指环王:王者无敌", "https://bkimg.cdn.bcebos.com/smart/503d269759ee3d6d55fbfbd691477a224f4a20a470d6-bkimg-process,v_1,rw_1,rh_1,maxl_216,pad_1,color_ffffff?x-bce-process=image/format,f_auto", 82.54f))
            list.add(TopDataSource("蜘蛛侠:英雄远征", "https://bkimg.cdn.bcebos.com/smart/9922720e0cf3d7ca6fe915d9fc1fbe096b63a905-bkimg-process,v_1,rw_1,rh_1,maxl_216,pad_1,color_ffffff?x-bce-process=image/format,f_auto", 82.13f))
            list.add(TopDataSource("惊奇队长", "https://bkimg.cdn.bcebos.com/smart/71cf3bc79f3df8dc9670d47ac011728b4610288f-bkimg-process,v_1,rw_1,rh_1,maxl_216,pad_1,color_ffffff?x-bce-process=image/format,f_auto", 82.04f))
            list.add(TopDataSource("变形金刚3", "https://bkimg.cdn.bcebos.com/smart/dc54564e9258d109b3de7eaa7b11dbbf6c81800ae7db-bkimg-process,v_1,rw_1,rh_1,maxl_216,pad_1,color_ffffff?x-bce-process=image/format,f_auto", 81.49f))
            list.add(TopDataSource("蝙蝠侠:黑暗骑士崛起", "https://bkimg.cdn.bcebos.com/smart/d0c8a786c9177f3e4f3b5b0f72cf3bc79f3d56a0-bkimg-process,v_1,rw_1,rh_1,maxl_216,pad_1,color_ffffff?x-bce-process=image/format,f_auto", 80.38f))
            list.add(TopDataSource("007:大破天幕杀机", "https://bkimg.cdn.bcebos.com/smart/d6ca7bcb0a46f21fbe098d1eb3737c600c338744007c-bkimg-process,v_1,rw_1,rh_1,maxl_216,pad_1,color_ffffff?x-bce-process=image/format,f_auto", 80.38f))
            list.add(TopDataSource("变形金刚4:绝迹重生", "https://bkimg.cdn.bcebos.com/smart/2e2eb9389b504fc28c79a73fefdde71190ef6de1-bkimg-process,v_1,rw_1,rh_1,maxl_216,pad_1,color_ffffff?x-bce-process=image/format,f_auto", 80.14f))
            list.add(TopDataSource("侏罗纪公园", "https://bkimg.cdn.bcebos.com/smart/7acb0a46f21fbe098007a2fe6d600c338644adfb-bkimg-process,v_1,rw_1,rh_1,maxl_216,pad_1,color_ffffff?x-bce-process=image/format,f_auto", 80.08f))
            list.add(TopDataSource("小丑", "https://bkimg.cdn.bcebos.com/smart/9d82d158ccbf6c81800ad21d7a77a63533fa838beaa6-bkimg-process,v_1,rw_1,rh_1,maxl_216,pad_1,color_ffffff?x-bce-process=image/format,f_auto", 78.23f))
//            list.sortByDescending { it.value }
            list.sortBy { it.value }
            
            val showCount = 3
            val model = ScrollViewModel(
                "全球影史票房榜TOP40", showCount, list, "https://img1.baidu.com/it/u=452832960,881910017&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=281",//背景图片
                musicUrl = "asset:///vv.mp3" //背景音乐,可配置网络链接
            ).apply {
                itemWidth = DisplayUtil.getSreenWidth(MyApp.application) / showCount
                formatString = "%.2f亿" //数字格式化设置
                multiplier = 1f //数据显示格式所用的乘数
            }
            _datas.value = model
        }
    }
}

注意:showCount设置为0没有开始几个往下的动画,但是itemWidth必须要设置宽度,那儿单独设置屏幕显示个数

4、Compose页面调用方

  1. 使用我默认实现的Item 布局HorizontalScroll(it, it.list),这样调用就行
  2. 自定义Item布局,可监听滚动到最右边,可自定义item的compose
kotlin 复制代码
HorizontalScroll(it, it.list, onPlayComplete = {
           //滚动到右边,背景音乐播放结束
       }) { data: TopDataSource, index: Int, size: Int ->
           //真正itemView 布局compose,可自定义
           RealItemView(data, it.itemWidth, index, size, it)
       }
  1. 顶部gif效果图示例调用如下:
kotlin 复制代码
@Composable
fun horizontalScrollView(viewModel: DhListViewModel) {
    val datas by viewModel.datas.observeAsState()
    datas?.let {
        HorizontalScroll(it, it.list)

//        HorizontalScroll(it, it.list, onPlayComplete = {
//            //滚动到右边,背景音乐播放结束
//        }) { data: TopDataSource, index: Int, size: Int ->
//            //真正itemView 布局compose,可自定义
//            RealItemView(data, it.itemWidth, index, size, it)
//        }
    }
}

四、动画真正实现逻辑

Compose实现整体逻辑比较简单

  1. 整个屏幕是一个Column,竖向的,里面包含一个标题Text和一个横向LazyRow
  2. LazyRow通过 listState = rememberLazyListState(),listState.scrollBy(3.6f)向右滚动:如下
scss 复制代码
while (!isScrolledToLast) { // 无限循环,直到你决定停止它
    delay(30) // 延迟时间,例如30毫秒滚动一次
    scope.launch {
        listState.scrollBy(3.6f)
    }
}
  1. 通过listState.layoutInfo监听滚动到最右边:判断监听滚到右边逻辑:
    firstVisibleIndex:滚动时左边刚好显示的第一个
    layoutInfo.visibleItemsInfo.size:屏幕显示的个数,大多数情况下会比设置的多一个
    layoutInfo.totalItemsCount:视图里面数据集总共个数

这里滚动到最右边倒数第2个时后,再给到8s时间,让其滚动到最右边,这个时候认为滚动结束,停止背景音乐播放

ini 复制代码
LaunchedEffect(remember { derivedStateOf { listState.layoutInfo } }) {
        snapshotFlow { listState.firstVisibleItemIndex }.collect { firstVisibleIndex ->
            val layoutInfo = listState.layoutInfo
            val scrolledToLast = (firstVisibleIndex + layoutInfo.visibleItemsInfo.size >= layoutInfo.totalItemsCount)
            if (scrolledToLast) {
                delay(8000L)
                isScrolledToLast = true
                it.isPlayComplete = true
                player.stop()
                player.release()
                onPlayComplete?.invoke()
            }
        }
    }
  1. 整体实现代码如下: 这里list内数据是TopDataSource的扩展泛型,可增加字段,真正item的compose可自定义布局,可自定义多家属性展示。
scss 复制代码
@SuppressLint("UseKtx")
@Composable
fun <T : TopDataSource> HorizontalScroll(
    it: ScrollViewModel, list: MutableList<T>, onPlayComplete: (() -> Unit)? = null, content: @Composable (data: T, index: Int, size: Int) -> Unit = { data: T, index: Int, size: Int ->
        RealItemView(data, it.itemWidth, index, size, it)
    }
) {
    val context = LocalContext.current
    val listState = rememberLazyListState()
    val scope = rememberCoroutineScope()
    val size = remember(it) { list.size }
    var isScrolledToLast by remember { mutableStateOf(false) }
    var bitmapBg by remember { mutableStateOf(DefaultBitmapUtils.createImageBitmap()) }
    var width by remember { mutableIntStateOf(0) }
    var height by remember { mutableIntStateOf(0) }
    val player = remember { ExoPlayer.Builder(context).build() }
    val lifecycleOwner = LocalLifecycleOwner.current

    LaunchedEffect(remember { derivedStateOf { listState.layoutInfo } }) {
        snapshotFlow { listState.firstVisibleItemIndex }.collect { firstVisibleIndex ->
            val layoutInfo = listState.layoutInfo
            val scrolledToLast = (firstVisibleIndex + layoutInfo.visibleItemsInfo.size >= layoutInfo.totalItemsCount)
            if (scrolledToLast) {
                delay(8000L)
                isScrolledToLast = true
                it.isPlayComplete = true
                player.stop()
                player.release()
                onPlayComplete?.invoke()
            }
        }
    }

    LaunchedEffect(Unit) {
        Glide.with(context).asBitmap().load(it.bgImg).skipMemoryCache(false).diskCacheStrategy(DiskCacheStrategy.RESOURCE).into(object : SimpleTarget<Bitmap>() {
            override fun onResourceReady(resource: Bitmap, transition: Transition<in Bitmap>?) {
                bitmapBg = resource.asImageBitmap()
            }
        })
        player.run {
            setMediaItem(MediaItem.fromUri(it.musicUrl.toUri()))
            prepare()
            play()
        }
        delay(1000L + (it.showCount * 3000L)) // 延迟时间,例如2秒滚动一次
        while (!isScrolledToLast) { // 无限循环,直到你决定停止它
            delay(30) // 延迟时间,例如30毫秒滚动一次
            scope.launch {
                listState.scrollBy(3.6f)
            }
        }
    }
    DisposableEffect(lifecycleOwner) {
        val observer = LifecycleEventObserver { _, event ->
            if (event == Lifecycle.Event.ON_STOP) {
                if (player.isPlaying) {
                    player.stop()
                    player.release()
                }
                if (!it.isPlayComplete) {
                    it.isPlayComplete = true
                    onPlayComplete?.invoke()
                }
            }
        }
        lifecycleOwner.lifecycle.addObserver(observer)
        onDispose {
            lifecycleOwner.lifecycle.removeObserver(observer)
        }
    }

    Column(
        Modifier
            .fillMaxWidth()
            .fillMaxHeight()
            .onSizeChanged {
                width = it.width
                height = it.height
            }
            .drawBehind {
                drawImage(
                    bitmapBg, srcOffset = IntOffset.Zero, srcSize = IntSize(bitmapBg.width, bitmapBg.height),   //绘制的图片大小
                    dstOffset = IntOffset.Zero, dstSize = IntSize(
                        width, height
                    )
                )
            }, horizontalAlignment = Alignment.CenterHorizontally
    ) {
        Text(
            modifier = Modifier
                .fillMaxWidth()
                .height(50.dp)
                .padding(0.dp, 5.dp, 0.dp, 0.dp), text = it.title, textAlign = TextAlign.Center, color = Color.White, fontSize = 22.sp
        )
        LazyRow(
            state = listState, modifier = Modifier
                .fillMaxWidth()
                .wrapContentHeight()
        ) {
            itemsIndexed(list) { index, data ->
                ItemView(index, it.showCount, data, size, it, content)
            }
        }
    }
}
  1. Item里面,屏幕显示个数的第一屏,设置成动画,
    这里使用到ComposeAnimatedVisibility 动画,
    配置好动画进入,进出时间slideInVertically(tween(it.tweenTimeI))
scss 复制代码
@Composable
fun <T> ItemView(index: Int, showCount: Int, data: T, size: Int, it: ScrollViewModel, content: @Composable (data: T, index: Int, size: Int) -> Unit) {
    var visible by remember { mutableStateOf(false) }
    LaunchedEffect(Unit) {
        if (showCount > index) {
            delay(1000L + index * it.tweenTimeL)
            visible = true
        }
    }
    Box(
        modifier = Modifier
            .width(it.itemWidth.dp)
            .wrapContentHeight()
    ) {
        if (showCount > index) {
            AnimatedVisibility(
                visible = visible, enter = slideInVertically(tween(it.tweenTimeI)), exit = slideOutVertically(tween(it.tweenTimeI))
            ) {
                content(data, index, size)
            }
        } else {
            content(data, index, size)
        }
    }
}

五、总结

本文简单介绍了电影电视剧网红广告屏轮播介绍视频特效制作

  1. 制作数据模型,可扩展,
  2. 每一个Item的compose 可扩展。
  3. 涉及到compose 的 Column ,LazyRow ,rememberLazyListState(),snapshotFlow 的使用
  4. 涉及到compose 的 LaunchedEffect,DisposableEffect 的使用
  5. 涉及到compose 中ExoPlayer 怎么播放音乐
  6. 涉及到compose 中 Glide怎么去给视图加载背景图片。

感谢阅读:

欢迎用你发财的小手 关注,点赞、收藏

这里你会学到不一样的东西

相关推荐
_祝你今天愉快5 分钟前
深入剖析Java中ThreadLocal原理
android
张力尹1 小时前
谈谈 kotlin 和 java 中的锁!你是不是在协程中使用 synchronized?
android
会讲英语的码农1 小时前
什么叫“架构”
考研·架构·硬件架构
AI糊涂是福1 小时前
数字政府与智慧城市区别报告分析
大数据·人工智能·机器学习·架构·智慧城市
AronTing1 小时前
06- 服务网格实战:从 Istio 核心原理到微服务治理升级
java·后端·架构
流浪汉kylin1 小时前
Android 斜切图片
android
腾讯云开发者2 小时前
AI 时代,程序员只剩架构师?腾讯云架构师技术沙龙邀你共探破局之道
架构
PuddingSama2 小时前
Android 视图转换工具 Matrix
android·前端·面试
RichardLai882 小时前
[Flutter学习之Dart基础] - 控制语句
android·flutter
AronTing2 小时前
05-微服务可观测性体系建设:从日志、监控到链路追踪实战指南
java·后端·架构