前言

在app开发中,许多场景需求在有限的规模内显示完整的内容。假如内容自身没有超出控件规模,那么没有任何问题。可是假如内容的长度超过了控件的规模,那么就需求酌情处理了。而跑马灯作用便是处理方式之一。

跑马灯并不是什么新东西,在xml的时代,textview就能够经过简略的特点设置完成作用。不知道用过的xdm有没有跟我相同的感受,便是往往很难一下子完美的完成作用,由于什么焦点啊,行数啊这些特点都会影响到终究的作用并且有些场景需求多个textview按需跑马灯等等这些问题,总之让这个简略的功用完成起来不是那么顺利~

当然啊,好歹xml的方式还是能够完成的。而强大的Compose居然在1.4.0-alpha04版别之前不支撑跑马灯作用!这几天看文档发现从1.4.0-alpha04已经支撑了跑马灯这个或许有点迟来的功用。下面就来一起探究一下Compose的跑马灯完成吧。

最快完成

完成十分简略,调用Modifier.basicMarquee()即可!不必像之前xml的时分,需求设置焦点行数等。

Text(
    modifier = Modifier.padding(padding).basicMarquee(),
    text = "套马杆的汉子你威武雄壮!套马杆的汉子你威武雄壮!套马杆的汉子你威武雄壮!套马杆的汉子你威武雄壮!套马杆的汉子你威武雄壮!套马杆的汉子你威武雄壮!套马杆的汉子你威武雄壮!",
)

主页作用是用到了大话Compose炼体(1)-先一餐吃3碗饭 – ()这篇的完成。感兴趣的能够去看看点个赞,这儿主要看Text的跑马灯作用就好

嘿嘿。又少了一个不用Compose的理由~官方支持跑马灯效果了!

别的咱们缩减Text的text内容,再来看看

Text(
    modifier = Modifier.padding(padding).basicMarquee(),
    text = "套马杆的汉子你威武雄壮!",
)

由于这儿的Text的宽没有约束啊,所以是屏幕宽度。那么这儿的控件宽度必定大于内容,发现这是是没有跑马灯作用的

嘿嘿。又少了一个不用Compose的理由~官方支持跑马灯效果了!

假如咱们再把Text的宽度指定到一个肖小于内容的值示例为50dp

Text(
    modifier = Modifier.padding(padding).width(50.dp).basicMarquee(),
    text = "套马杆的汉子你威武雄壮!",
)

发现跑马灯作用又呈现了。这儿就不再贴图演示了。

定论:只要内容超出了有限规模才会有跑马灯作用,反之没有!

配合焦点完成跑马灯

考虑到电量优化和性能优化,许多时分让跑马灯无条件并无限时长的运转并不是个好主意。上面提到要完成跑马灯咱们要调用Modifier.basicMarquee办法。这个办法都有默许参数,所以咱们上面没有传参就能完成了。稍微看了一下参数类型和默许值,发现animationMode这个字段能够操控跑马灯动画的触发条件

fun Modifier.basicMarquee(
    iterations: Int = DefaultMarqueeIterations,
    //要害参数
    animationMode: MarqueeAnimationMode = Immediately,
    delayMillis: Int = DefaultMarqueeDelayMillis,
    initialDelayMillis: Int = if (animationMode == Immediately) delayMillis else 0,
    spacing: MarqueeSpacing = DefaultMarqueeSpacing,
    velocity: Dp = DefaultMarqueeVelocity
): Modifier
//动画模式
value class MarqueeAnimationMode private constructor(private val value: Int) {
    override fun toString(): String = when (this) {
        Immediately -> "Immediately"
        WhileFocused -> "WhileFocused"
        else -> error("invalid value: $value")
    }
    companion object {
        /**
         *不论有没焦点状态,当即执行
         */
        @Suppress("OPT_IN_MARKER_ON_WRONG_TARGET")
        @ExperimentalFoundationApi
        @get:ExperimentalFoundationApi
        val Immediately = MarqueeAnimationMode(0)
        /**
         * 只要控件有焦点或者子控件有焦点时才执行
         */
        @Suppress("OPT_IN_MARKER_ON_WRONG_TARGET")
        @ExperimentalFoundationApi
        @get:ExperimentalFoundationApi
        val WhileFocused = MarqueeAnimationMode(1)
    }
}

看到这心里就有个完成主意了,经过点击来操控焦点,然后经过是否有焦点来操控跑马灯动画是否运转。对Compose焦点办理不了解的xdm能够花个几分钟看看这篇文章Jetpack Compose中的焦点办理 – ()。

改造代码如下:

 //获取并记住焦点请求器,后边用它来请求焦点
val focusRequester = remember { FocusRequester() }
//获取焦点办理器 后边用它来清理焦点
val focusManager = LocalFocusManager.current
//声明一个变量来记录当时是否有焦点
var isFocused = false
Text(
    text = "套马杆的汉子你威武雄壮!套马杆的汉子你威武雄壮!",
    Modifier
        .padding(padding)
        .width(200.dp)
        //传参 MarqueeAnimationMode.WhileFocused用焦点来操控跑马灯动画
        .basicMarquee(animationMode = MarqueeAnimationMode.WhileFocused)
        //设置焦点请求器
        .focusRequester(focusRequester)
        //设置焦点改变监听
        .onFocusChanged {
            isFocused = it.isFocused
        }
        //这句必须要有,调用后表明能够被聚集
        .focusable()
        //设置点击事情
        .clickable {
            if (isFocused) {
                //假如当时有焦点,也便是在跑动画时。清楚焦点,中止动画。
                focusManager.clearFocus()
            } else {
                //假如当时没有焦点,请求焦点,开端动画
                focusRequester.requestFocus()
            }
        },
)

能够看到作用是契合预期的

嘿嘿。又少了一个不用Compose的理由~官方支持跑马灯效果了!

定论:能够经过焦点来操控动画的起止。失去焦点中止动画,并回到初始的状态而不是动画中止时的状态。

都能跑 才是好的跑马灯

之前大多数场景用到跑马灯,都是Text这种控件。可是Compose的跑马灯是否只能用在Text上呢?答案是“并不是哟”。一切可组合项都能够用到跑马灯作用!这个便是发挥xdm脑洞的时分了,下面展示一个简略作用:

调快一点速度,默许是30dp,这儿改成了60;削减一点动画头尾的距离,默许是3/1屏幕宽,这儿改成10/1

Row(modifier = Modifier
    .padding(padding)
    .basicMarquee(velocity =60.dp, spacing = MarqueeSpacing.fractionOfContainer(1f / 10f))) {
    Image(painter = painterResource(id = R.drawable.avatar1) , contentDescription = null)
    Image(painter = painterResource(id = R.drawable.avatar2) , contentDescription = null)
    Image(painter = painterResource(id = R.drawable.avatar3) , contentDescription = null)
    Image(painter = painterResource(id = R.drawable.avatar4) , contentDescription = null)
    Image(painter = painterResource(id = R.drawable.avatar5) , contentDescription = null)
    Image(painter = painterResource(id = R.drawable.avatar6) , contentDescription = null)
}

小结

经过上面的内容,能够发现。在Compose中要完成跑马灯作用十分简略,中心办法便是basicMarquee(),并且一切可组合项都能够经过Modifier来完成。详细有哪些其他的当地能够用到,这就看我们的想象力了!欢迎留言说说你的主意!