【问题标题】:How do I keep animated components from "bouncing back" to their original positions after animation?如何让动画组件在动画后“弹回”到它们的原始位置?
【发布时间】:2021-02-28 19:03:46
【问题描述】:

我想让位于窗口底部的CardView 在您切换模式时向下滑动,并在您返回正常模式时向上滑动。问题是虽然动画效果很好,但卡片会在动画结束后立即重新出现在它所在的位置。如何让它保持/冻结,直到我想让它回来?

这是我隐藏卡片的动画代码(card_hide_ani.xml):

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:shareInterpolator="@android:anim/decelerate_interpolator">
    <translate
        android:fromYDelta="0%"
        android:toYDelta="100%"
        android:duration="500" />
</set>

...以及在MainActivity.java 中隐藏卡片的方法(通过点击按钮调用)

    void HideCard(Context context) {
        CardView cardView = findViewById(R.id.cardView);
        Animation cardAni = AnimationUtils.loadAnimation(context, R.anim.card_hide_ani);
        cardView.startAnimation(cardAni);
    }

(我还想为卡片的透明度/alpha 设置动画,虽然我不完全确定这是否适用于卡片及其嵌入式组件。我稍后会处理,但是现在我只想让它工作。)

就像我说的,动画部分工作正常,但卡片“弹回”到原来的位置。我找不到任何可以说明原因的东西,到目前为止,这一直令人沮丧。我假设我应该以其他方式完成它,但我无法弄清楚该做什么或如何去做。我在这里错过了什么吗?任何帮助将不胜感激。谢谢!

问题的可视化演示

【问题讨论】:

  • 所以你想在动画完成后隐藏包含 TextView 和 FAB child 的整个 CardView?
  • 是的,整个 CardView。如果有意义的话,我希望它留在动画结束的任何地方。
  • 在你的函数 hideCard() 中,一旦你的动画完成,只需使用可见性修饰符隐藏 CardView。并且每当您想再次显示卡片时,请将动画和可见性设置为 VISIBLE。
  • 其他的呢?当点击它并且下一个窗口正在加载时,该 FAB 应该缩小以显示其后面的进度条。它不会一直缩小。如何防止它调整大小?
  • 恐怕我没有完全理解你。但我找到了解决您问题的类似解决方案。检查这个答案:stackoverflow.com/a/12329682/7725103

标签: java android android-studio android-animation


【解决方案1】:

如果您想尝试自定义动画(这将使您对动画有更多的控制权),您可以试试这个。我已经同时尝试了 YAxis 动画和 Alpha 动画。这将为您提供有关我们如何控制项目的背景信息。

import android.animation.AnimatorSet
import android.animation.ValueAnimator
import android.os.Bundle
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.cardview.widget.CardView

class MainActivityF : AppCompatActivity() {

    lateinit var downTextView: TextView
    lateinit var upTextView: TextView
    lateinit var cardview: CardView
    private val cardViewOriginalY: Float by lazy { cardview.y }
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main_f)
        downTextView = findViewById(R.id.down)
        upTextView = findViewById(R.id.up)
        cardview = findViewById(R.id.cardview)

        downTextView.setOnClickListener { animateCardDown() }
        upTextView.setOnClickListener { animateCardUp() }
    }

    private fun animateCardDown() {
        val yAxisAnimator: ValueAnimator = ValueAnimator.ofFloat(cardViewOriginalY, cardViewOriginalY + cardview.height)
        val alphaAnimator: ValueAnimator = ValueAnimator.ofFloat(1.0f, 0.5f)
        with(yAxisAnimator) {
            duration = 300L
            addUpdateListener {
                val currentY = it.animatedValue as Float
                cardview.y = currentY
            }
        }

        with(alphaAnimator) {
            duration = 300L
            addUpdateListener {
                val currentAlpha = it.animatedValue as Float
                cardview.alpha = currentAlpha
            }
        }

        val animatorSet = AnimatorSet()
        with(animatorSet) {
            playTogether(yAxisAnimator, alphaAnimator)
            start()
        }
    }

    private fun animateCardUp() {
        val yAxisAnimator: ValueAnimator = ValueAnimator.ofFloat(cardViewOriginalY + cardview.height, cardViewOriginalY)
        val alphaAnimator: ValueAnimator = ValueAnimator.ofFloat(0.5f, 1.0f)
        with(yAxisAnimator) {
            duration = 300L
            addUpdateListener {
                val currentY = it.animatedValue as Float
                cardview.y = currentY
            }
        }

        with(alphaAnimator) {
            duration = 300L
            addUpdateListener {
                val currentAlpha = it.animatedValue as Float
                cardview.alpha = currentAlpha
            }
        }

        val animatorSet = AnimatorSet()
        with(animatorSet) {
            playTogether(yAxisAnimator, alphaAnimator)
            start()
        }
    }
}

xml文件

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/down"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="20dp"
        android:layout_marginTop="20dp"
        android:text="DOWN ANIMATION"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/up"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:layout_marginEnd="20dp"
        android:text="UP ANIMATION"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <androidx.cardview.widget.CardView
        android:id="@+id/cardview"
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:backgroundTint="@color/black"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent" />


</androidx.constraintlayout.widget.ConstraintLayout>

【讨论】:

    【解决方案2】:

    添加这一行就足够了

    android:fillAfter="true"
    

    到您的 xml TranslateAnimation 代码。由于 TranslateAnimation 不会真正为视图本身设置动画,更像是在屏幕上表示视图的位图,没有那条线,动画不会停留在想要的位置。

    对于一般更好和更动态的动画,请查看ViewPropertyAnimator

    这允许您在一行代码中将多个动画链接在一起,并且它确实在屏幕上为 View 的属性本身设置动画,而不是像上面提到的 xml TranslateAnimation,它只移动屏幕上的像素,不是视图本身。 这也应该可以帮助您开始其他(alpha)动画计划。

    【讨论】:

      猜你喜欢
      • 2011-04-20
      • 1970-01-01
      • 1970-01-01
      • 2015-12-24
      • 1970-01-01
      • 2015-12-16
      • 1970-01-01
      • 2013-03-22
      • 1970-01-01
      相关资源
      最近更新 更多