From b327109ca8613a624412d35191d60db6649b40b1 Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 14 Oct 2021 22:11:44 +0300 Subject: [PATCH] Updated on 2026-08-14 --- .../tap/common/leapfrogWidget/Animations.kt | 86 ++++----- .../tap/common/leapfrogWidget/LeapView.kt | 173 +++++++----------- .../common/leapfrogWidget/LeapfrogWidget.kt | 117 +++++++----- 3 files changed, 175 insertions(+), 201 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/common/leapfrogWidget/Animations.kt b/app/src/main/java/com/tangem/tap/common/leapfrogWidget/Animations.kt index 77c9f1fcbb..a95488d44f 100644 --- a/app/src/main/java/com/tangem/tap/common/leapfrogWidget/Animations.kt +++ b/app/src/main/java/com/tangem/tap/common/leapfrogWidget/Animations.kt @@ -32,14 +32,14 @@ fun createProgressListener(duration: Long, listener: ProgressListener?): Animato return valueAnimator } -fun View.unfoldAnimation(animDuration: Long, properties: AnimationProperties): AnimatorSet { - val translate = ObjectAnimator.ofFloat(this, View.TRANSLATION_Y, properties.yTranslationStart, properties.yTranslationEnd) +fun View.unfoldAnimation(animDuration: Long, properties: LeapViewProperties): AnimatorSet { + val translate = ObjectAnimator.ofFloat(this, View.TRANSLATION_Y, properties.yTranslation) translate.duration = animDuration return AnimatorSet().apply { playTogether(translate) } } -fun View.foldAnimation(animDuration: Long, properties: AnimationProperties): AnimatorSet { - val translate = ObjectAnimator.ofFloat(this, View.TRANSLATION_Y, properties.yTranslationStart, properties.yTranslationEnd) +fun View.foldAnimation(animDuration: Long, properties: LeapViewProperties): AnimatorSet { + val translate = ObjectAnimator.ofFloat(this, View.TRANSLATION_Y, properties.yTranslation) translate.duration = animDuration return AnimatorSet().apply { @@ -47,17 +47,17 @@ fun View.foldAnimation(animDuration: Long, properties: AnimationProperties): Ani } } -fun View.leapAnimation(animDuration: Long, properties: AnimationProperties, overLift: Float): AnimatorSet { +fun View.leapAnimation(animDuration: Long, properties: LeapViewProperties, overLift: Float): AnimatorSet { val halfDuration = animDuration / 2 - val upTo = (height.toFloat() + properties.yTranslationStart + overLift) * -1 - val translateUp = ObjectAnimator.ofFloat(this, View.TRANSLATION_Y, properties.yTranslationStart, upTo) + val upTo = (height.toFloat() + overLift) * -1 + val translateUp = ObjectAnimator.ofFloat(this, View.TRANSLATION_Y, upTo) translateUp.duration = halfDuration translateUp.interpolator = LinearInterpolator() val scaleDuration = halfDuration - halfDuration / 5 - val scaleX = ObjectAnimator.ofFloat(this, View.SCALE_X, properties.scaleStart, properties.scaleEnd) - val scaleY = ObjectAnimator.ofFloat(this, View.SCALE_Y, properties.scaleStart, properties.scaleEnd) + val scaleX = ObjectAnimator.ofFloat(this, View.SCALE_X, properties.scale) + val scaleY = ObjectAnimator.ofFloat(this, View.SCALE_Y, properties.scale) val scale = AnimatorSet().apply { startDelay = scaleDuration duration = scaleDuration @@ -65,37 +65,28 @@ fun View.leapAnimation(animDuration: Long, properties: AnimationProperties, over playTogether(scaleX, scaleY) } - val elevation = ValueAnimator.ofFloat(properties.elevationStart, properties.elevationEnd) - elevation.addUpdateListener { this.elevation = (it.animatedValue as? Float) ?: properties.elevationStart } - elevation.startDelay = halfDuration - elevation.duration = 100 - - val translateDown = ObjectAnimator.ofFloat(this, View.TRANSLATION_Y, upTo, properties.yTranslationEnd) + val elevation = elevationAnimator(properties.elevationStart, properties.elevationEnd, halfDuration, 100) + val translateDown = ObjectAnimator.ofFloat(this, View.TRANSLATION_Y, properties.yTranslation) translateDown.startDelay = halfDuration translateDown.duration = halfDuration translateDown.interpolator = LinearInterpolator() return AnimatorSet().apply { - playTogether( - translateUp, - scale, - elevation, - translateDown - ) + playTogether(translateUp, scale, elevation, translateDown) } } -fun View.leapBackAnimation(animDuration: Long, properties: AnimationProperties, calculator: PropertyCalculator): AnimatorSet { +fun View.leapBackAnimation(animDuration: Long, properties: LeapViewProperties, calculator: PropertyCalculator): AnimatorSet { val halfDuration = animDuration / 2 val upTo = ((height).toFloat() - calculator.yTranslationFactor) * -1 - val translateUp = ObjectAnimator.ofFloat(this, View.TRANSLATION_Y, properties.yTranslationStart, upTo) + val translateUp = ObjectAnimator.ofFloat(this, View.TRANSLATION_Y, upTo) translateUp.duration = halfDuration translateUp.interpolator = LinearInterpolator() val scaleDuration = halfDuration - halfDuration / 5 - val scaleX = ObjectAnimator.ofFloat(this, View.SCALE_X, properties.scaleStart, properties.scaleEnd) - val scaleY = ObjectAnimator.ofFloat(this, View.SCALE_Y, properties.scaleStart, properties.scaleEnd) + val scaleX = ObjectAnimator.ofFloat(this, View.SCALE_X, properties.scale) + val scaleY = ObjectAnimator.ofFloat(this, View.SCALE_Y, properties.scale) val scale = AnimatorSet().apply { startDelay = scaleDuration duration = scaleDuration @@ -103,34 +94,24 @@ fun View.leapBackAnimation(animDuration: Long, properties: AnimationProperties, playTogether(scaleX, scaleY) } - val elevation = ValueAnimator.ofFloat(properties.elevationStart, properties.elevationEnd) - elevation.addUpdateListener { this.elevation = (it.animatedValue as? Float) ?: properties.elevationStart } - elevation.startDelay = halfDuration - elevation.duration = 100 - - val translateDown = ObjectAnimator.ofFloat(this, View.TRANSLATION_Y, upTo, properties.yTranslationEnd) + val elevation = elevationAnimator(properties.elevationStart, properties.elevationEnd, halfDuration, 100) + val translateDown = ObjectAnimator.ofFloat(this, View.TRANSLATION_Y, properties.yTranslation) translateDown.startDelay = halfDuration translateDown.duration = halfDuration return AnimatorSet().apply { - playTogether( - translateUp, - scale, - elevation, - translateDown, - ) + playTogether(translateUp, scale, elevation, translateDown) } } -fun View.pullUpAnimation(leapDuration: Long, properties: AnimationProperties): AnimatorSet { +fun View.pullUpAnimation(leapDuration: Long, properties: LeapViewProperties): AnimatorSet { val pullDuration = leapDuration / 2 val delayDuration = leapDuration / 2 - val translateUp = ObjectAnimator.ofFloat(this, View.TRANSLATION_Y, properties.yTranslationStart, properties.yTranslationEnd) - val scaleX = ObjectAnimator.ofFloat(this, View.SCALE_X, properties.scaleStart, properties.scaleEnd) - val scaleY = ObjectAnimator.ofFloat(this, View.SCALE_Y, properties.scaleStart, properties.scaleEnd) - val elevation = ValueAnimator.ofFloat(properties.elevationStart, properties.elevationEnd) - elevation.addUpdateListener { this.elevation = (it.animatedValue as? Float) ?: properties.elevationStart } + val translateUp = ObjectAnimator.ofFloat(this, View.TRANSLATION_Y, properties.yTranslation) + val scaleX = ObjectAnimator.ofFloat(this, View.SCALE_X, properties.scale) + val scaleY = ObjectAnimator.ofFloat(this, View.SCALE_Y, properties.scale) + val elevation = elevationAnimator(properties.elevationStart, properties.elevationEnd) return AnimatorSet().apply { startDelay = delayDuration @@ -140,15 +121,14 @@ fun View.pullUpAnimation(leapDuration: Long, properties: AnimationProperties): A } } -fun View.pullDownAnimation(leapDuration: Long, properties: AnimationProperties): AnimatorSet { +fun View.pullDownAnimation(leapDuration: Long, properties: LeapViewProperties): AnimatorSet { val pullDuration = leapDuration / 2 val delayDuration = leapDuration / 4 - val translate = ObjectAnimator.ofFloat(this, View.TRANSLATION_Y, properties.yTranslationStart, properties.yTranslationEnd) - val scaleX = ObjectAnimator.ofFloat(this, View.SCALE_X, properties.scaleStart, properties.scaleEnd) - val scaleY = ObjectAnimator.ofFloat(this, View.SCALE_Y, properties.scaleStart, properties.scaleEnd) - val elevation = ValueAnimator.ofFloat(properties.elevationStart, properties.elevationEnd) - elevation.addUpdateListener { this.elevation = (it.animatedValue as? Float) ?: properties.elevationStart } + val translate = ObjectAnimator.ofFloat(this, View.TRANSLATION_Y, properties.yTranslation) + val scaleX = ObjectAnimator.ofFloat(this, View.SCALE_X, properties.scale) + val scaleY = ObjectAnimator.ofFloat(this, View.SCALE_Y, properties.scale) + val elevation = elevationAnimator(properties.elevationStart, properties.elevationEnd) return AnimatorSet().apply { startDelay = delayDuration @@ -156,4 +136,12 @@ fun View.pullDownAnimation(leapDuration: Long, properties: AnimationProperties): interpolator = DecelerateInterpolator() playTogether(translate, scaleX, scaleY, elevation) } +} + +fun View.elevationAnimator(start: Float, end: Float, startDelay: Long? = null, duration: Long? = null): Animator { + val elevationAnimator = ValueAnimator.ofFloat(start, end) + elevationAnimator.addUpdateListener { this.elevation = (it.animatedValue as? Float) ?: start } + startDelay?.let { elevationAnimator.startDelay = it } + duration?.let { elevationAnimator.duration = it } + return elevationAnimator } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/common/leapfrogWidget/LeapView.kt b/app/src/main/java/com/tangem/tap/common/leapfrogWidget/LeapView.kt index 0c4d37a066..be2d63b664 100644 --- a/app/src/main/java/com/tangem/tap/common/leapfrogWidget/LeapView.kt +++ b/app/src/main/java/com/tangem/tap/common/leapfrogWidget/LeapView.kt @@ -12,35 +12,33 @@ class LeapView( private val maximalPosition: Int, private val calculator: PropertyCalculator, ) { - var currentProperties: AnimationProperties + var state: LeapViewState private set - var currentPosition: Int = position - private set - var previousPosition: Int = position - private set + val initialState: LeapViewState init { val initialProperties = createInitialProperty(position) - currentProperties = AnimationProperties.from(initialProperties, initialProperties) - initView(initialProperties) + state = LeapViewState(index, position, position, initialProperties) + initialState = state.copy() } - private fun initView(properties: Properties) { - view.elevation = properties.elevation - view.translationY = properties.yTranslation - view.scaleX = properties.scale - view.scaleY = properties.scale -// initialProperties.hasForeground + fun initView() { + applyState(initialState) } fun leap(): LeapFrogAnimation { - previousPosition = currentPosition - currentPosition = when (previousPosition) { + val previousPosition = state.currentPosition + val currentPosition = when (previousPosition) { 0 -> maximalPosition - else -> currentPosition - 1 + else -> state.currentPosition - 1 } - updateProperties(createLeapAnimationProperty(previousPosition, currentPosition)) + + state = state.copy( + currentPosition = currentPosition, + previousPosition = previousPosition, + properties = createLeapAnimationProperty(previousPosition, currentPosition) + ) return when { previousPosition == 0 && currentPosition == maximalPosition -> LeapFrogAnimation.LEAP @@ -49,12 +47,16 @@ class LeapView( } fun leapBack(): LeapFrogAnimation { - previousPosition = currentPosition - currentPosition = when (previousPosition) { + val previousPosition = state.currentPosition + val currentPosition = when (previousPosition) { maximalPosition -> 0 - else -> currentPosition + 1 + else -> state.currentPosition + 1 } - updateProperties(createLeapAnimationProperty(previousPosition, currentPosition)) + state = state.copy( + currentPosition = currentPosition, + previousPosition = previousPosition, + properties = createLeapAnimationProperty(previousPosition, currentPosition) + ) return when { previousPosition == maximalPosition && currentPosition == 0 -> LeapFrogAnimation.LEAP @@ -63,66 +65,60 @@ class LeapView( } fun fold() { - updateProperties(currentProperties.toFold()) + state = state.copy(properties = state.properties.toFold() + ) } fun unfold() { - updateProperties(currentProperties.toUnfold(calculator)) - } - - fun getState(): LeapViewState { - return LeapViewState(index, currentPosition, previousPosition, currentProperties) + state = state.copy(properties = state.properties.toUnfold(calculator)) } fun applyState(state: LeapViewState) { - previousPosition = state.previousPosition - currentPosition = state.currentPosition - updateProperties(state.properties) - initView(state.properties.endProperties()) + this.state = state + setProperties(this.state.properties) } - private fun updateProperties(properties: AnimationProperties) { - currentProperties = properties + private fun setProperties(properties: LeapViewProperties) { + view.elevation = properties.elevationEnd + view.translationY = properties.yTranslation + view.scaleX = properties.scale + view.scaleY = properties.scale +// initialProperties.hasForeground } - private fun createInitialProperty(endPosition: Int): Properties { - return Properties( - endPosition, - calculator.scale(endPosition), - calculator.elevation(endPosition, maximalPosition + 1), - calculator.yTranslation(0), - calculator.hasForeground(endPosition), + private fun createInitialProperty(endPosition: Int): LeapViewProperties { + return LeapViewProperties( + endPosition, + endPosition, + calculator.scale(endPosition), + calculator.elevation(endPosition, maximalPosition + 1), + calculator.elevation(endPosition, maximalPosition + 1), + calculator.yTranslation(0), + calculator.hasForeground(endPosition), ) } - private fun createLeapAnimationProperty(startPosition: Int, endPosition: Int): AnimationProperties { - return AnimationProperties( - startPosition, - endPosition, - calculator.scale(startPosition), - calculator.scale(endPosition), - calculator.elevation(startPosition, maximalPosition + 1), - calculator.elevation(endPosition, maximalPosition + 1), - calculator.yTranslation(startPosition), - calculator.yTranslation(endPosition), - calculator.hasForeground(startPosition), - calculator.hasForeground(endPosition), + private fun createLeapAnimationProperty(startPosition: Int, endPosition: Int): LeapViewProperties { + return LeapViewProperties( + startPosition, + endPosition, + calculator.scale(endPosition), + calculator.elevation(startPosition, maximalPosition + 1), + calculator.elevation(endPosition, maximalPosition + 1), + calculator.yTranslation(endPosition), + calculator.hasForeground(endPosition), ) } - private fun AnimationProperties.toUnfold(calculator: PropertyCalculator): AnimationProperties { - val start = this.yTranslationEnd - val end = calculator.yTranslation(this.positionEnd) - return this.copy(yTranslationStart = start, yTranslationEnd = end) + private fun LeapViewProperties.toUnfold(calculator: PropertyCalculator): LeapViewProperties { + return this.copy(yTranslation = calculator.yTranslation(this.positionEnd)) } - private fun AnimationProperties.toFold(): AnimationProperties { - val start = this.yTranslationEnd - val end = 0f - return this.copy(yTranslationStart = start, yTranslationEnd = end) + private fun LeapViewProperties.toFold(): LeapViewProperties { + return this.copy(yTranslation = 0f) } - override fun toString(): String = "index: $index, position: $currentPosition, code: ${view.hashCode()}" + override fun toString(): String = "index: $index, position: ${state.currentPosition}, code: ${view.hashCode()}" } @@ -130,62 +126,19 @@ data class LeapViewState( val index: Int, val currentPosition: Int, val previousPosition: Int, - val properties: AnimationProperties + val properties: LeapViewProperties ) enum class LeapFrogAnimation { LEAP, PULL } -data class Properties( - val position: Int, - val scale: Float, - val elevation: Float, - val yTranslation: Float, - val hasForeground: Boolean, -) - -data class AnimationProperties( +data class LeapViewProperties( val positionStart: Int, val positionEnd: Int, - val scaleStart: Float, - val scaleEnd: Float, + val scale: Float, val elevationStart: Float, val elevationEnd: Float, - val yTranslationStart: Float, - val yTranslationEnd: Float, - val hasForegroundStart: Boolean, - val hasForegroundEnd: Boolean, -) { - - fun endProperties(): Properties { - return Properties( - positionEnd, - scaleEnd, - elevationEnd, - yTranslationEnd, - hasForegroundEnd, - ) - } - - override fun toString(): String { - return """ - scaleStart: $scaleStart, scaleEnd: $scaleEnd, - elevationStart: $elevationStart, elevationEnd: $elevationEnd, - yTranslationStart: $yTranslationStart, yTranslationEnd: $yTranslationEnd, - hasForegroundStart : $hasForegroundStart, hasForegroundEnd: $hasForegroundEnd, - """.trimIndent() - } - - companion object { - fun from(start: Properties, end: Properties): AnimationProperties { - return AnimationProperties( - start.position, end.position, - start.scale, end.scale, - start.elevation, end.elevation, - start.yTranslation, end.yTranslation, - start.hasForeground, end.hasForeground - ) - } - } -} \ No newline at end of file + val yTranslation: Float, + val hasForeground: Boolean, +) \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/common/leapfrogWidget/LeapfrogWidget.kt b/app/src/main/java/com/tangem/tap/common/leapfrogWidget/LeapfrogWidget.kt index 37b04d4f2a..11c0b11e63 100644 --- a/app/src/main/java/com/tangem/tap/common/leapfrogWidget/LeapfrogWidget.kt +++ b/app/src/main/java/com/tangem/tap/common/leapfrogWidget/LeapfrogWidget.kt @@ -2,9 +2,9 @@ package com.tangem.tap.common.leapfrogWidget import android.animation.Animator import android.animation.AnimatorSet -import android.view.View import android.view.animation.AccelerateDecelerateInterpolator import android.widget.FrameLayout +import androidx.core.animation.doOnEnd import androidx.core.view.children import com.tangem.tangem_sdk_new.extensions.dpToPx @@ -25,60 +25,87 @@ class LeapfrogWidget( private var leapProgress: Int = 100 private var leapBackProgress: Int = 100 - private var isFolded: Boolean = true + var isFolded: Boolean = true + private set init { calculator.setTranslationConverter { parentContainer.dpToPx(it) } - init() - } - - private fun init() { - if (!viewIsFullFledged()) return - - val maxPosition = parentContainer.childCount - 1 - parentContainer.children.forEachIndexed { index, view -> - val initialPosition = maxPosition - index - leapViews.add(LeapView(view, index, initialPosition, maxPosition, calculator)) + if (viewIsFullFledged()) { + val maxPosition = parentContainer.childCount - 1 + parentContainer.children.forEachIndexed { index, view -> + val initialPosition = maxPosition - index + leapViews.add(LeapView(view, index, initialPosition, maxPosition, calculator)) + } } } - fun fold(listener: ProgressListener? = null) { - if (!canFoldUnfold() || isFolded) return - - createFoldUnfoldAnimation(true, foldAnimationDuration, listener) + /** + * Apply initial properties to the views + */ + fun initViews() { + isFolded = true + leapViews.forEach { it.initView() } } - fun unfold(listener: ProgressListener? = null) { - if (!canFoldUnfold() || !isFolded) return - - createFoldUnfoldAnimation(false, foldAnimationDuration, listener) + fun fold(onEnd: () -> Unit = {}) { + val animator = foldAnimator() + if (animator == null) { + onEnd() + } else { + animator.doOnEnd { onEnd() } + animator.start() + } } - private fun createFoldUnfoldAnimation(isFoldAnimation: Boolean, duration: Long, listener: ProgressListener?) { + fun unfold(onEnd: () -> Unit = {}) { + val animator = unfoldAnimator() + if (animator == null) { + onEnd() + } else { + animator.doOnEnd { onEnd() } + animator.start() + } + } + + fun foldAnimator(): Animator? { + if (!canFoldUnfold() || isFolded) return null + + return createFoldUnfoldAnimator(true, foldAnimationDuration) + } + + fun unfoldAnimator(): Animator? { + if (!canFoldUnfold() || !isFolded) return null + + return createFoldUnfoldAnimator(false, foldAnimationDuration) + } + + private fun createFoldUnfoldAnimator(isFoldAnimation: Boolean, duration: Long): Animator { val animatorsList = mutableListOf() leapViews.forEach { if (isFoldAnimation) { it.fold() - animatorsList.add(it.view.foldAnimation(duration, it.currentProperties)) + animatorsList.add(it.view.foldAnimation(duration, it.state.properties)) } else { it.unfold() - animatorsList.add(it.view.unfoldAnimation(duration, it.currentProperties)) + animatorsList.add(it.view.unfoldAnimation(duration, it.state.properties)) } } animatorsList.add(createProgressListener(duration) { foldUnfoldProgress = it if (it == 100) isFolded = isFoldAnimation }) - animatorsList.add(createProgressListener(duration, listener)) val animator = AnimatorSet() animator.interpolator = AccelerateDecelerateInterpolator() animator.playTogether(animatorsList.toList()) - animator.start() + return animator } - fun leap(listener: ProgressListener? = null) { - if (!canLeap()) return + fun leap(onEnd: () -> Unit = {}) { + if (!canLeap()) { + onEnd() + return + } val duration = leapAnimationDuration val animatorsList = mutableListOf() @@ -86,48 +113,54 @@ class LeapfrogWidget( when (it.leap()) { LeapFrogAnimation.LEAP -> { val overLift = calculator.overLift(leapViews.size) - animatorsList.add(it.view.leapAnimation(duration, it.currentProperties, overLift)) + animatorsList.add(it.view.leapAnimation(duration, it.state.properties, overLift)) } LeapFrogAnimation.PULL -> { - animatorsList.add(it.view.pullUpAnimation(duration, it.currentProperties)) + animatorsList.add(it.view.pullUpAnimation(duration, it.state.properties)) } } } animatorsList.add(createProgressListener(duration) { leapProgress = it }) - animatorsList.add(createProgressListener(duration, listener)) val animator = AnimatorSet() animator.playTogether(animatorsList.toList()) + animator.doOnEnd { onEnd() } animator.start() } - fun leapBack(listener: ProgressListener? = null) { - if (!canLeapBack()) return + fun leapBack(onEnd: () -> Unit = {}) { + if (!canLeapBack()) { + onEnd() + return + } val duration = leapBackAnimationDuration val animatorsList = mutableListOf() leapViews.forEach { when (it.leapBack()) { LeapFrogAnimation.LEAP -> { - animatorsList.add(it.view.leapBackAnimation(duration, it.currentProperties, calculator)) + animatorsList.add(it.view.leapBackAnimation(duration, it.state.properties, calculator)) } LeapFrogAnimation.PULL -> { - animatorsList.add(it.view.pullDownAnimation(duration, it.currentProperties)) + animatorsList.add(it.view.pullDownAnimation(duration, it.state.properties)) } } } animatorsList.add(createProgressListener(duration) { leapBackProgress = it }) - animatorsList.add(createProgressListener(duration, listener)) + val animator = AnimatorSet() animator.playTogether(animatorsList.toList()) + animator.doOnEnd { onEnd() } animator.start() } - fun getViewByPosition(position: Int): View? { - return leapViews.firstOrNull { it.currentPosition == position }?.view - } + fun getViewsCount(): Int = parentContainer.childCount - fun getState(): LeapfrogWidgetState = LeapfrogWidgetState(isFolded, leapViews.map { it.getState() }) + fun getViewPositionByIndex(index: Int): Int = leapViews.first { it.index == index }.state.currentPosition + + fun getViewByPosition(position: Int): LeapView = leapViews.first { it.state.currentPosition == position } + + fun getState(): LeapfrogWidgetState = LeapfrogWidgetState(isFolded, leapViews.map { it.state }) fun applyState(state: LeapfrogWidgetState) { isFolded = state.isFolded @@ -179,11 +212,11 @@ data class LeapfrogWidgetState( class PropertyCalculator( val elevationFactor: Float = 1f, - val decreaseScaleFactor: Float = 0.1f, - val yTranslationFactor: Float = 20f, + val decreaseScaleFactor: Float = 0.2f, + val yTranslationFactor: Float = -40f, val decreaseOverLiftingFactor: Float = 0.85f, ) { - // 1st view it is view on the top of stack, but it is last in parent.children + // 0 view it is view on the top of stack, but it is last in parent.children private var translationValueConverter: ((Float) -> Float)? = null fun setTranslationConverter(converter: (Float) -> Float) {