You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

实现单个FrameLayout滑出、两个FrameLayout滑入的动画切换咨询

Bottom Menu Slide Transition Solution

Hey, I’ve worked on similar bottom menu animation scenarios before, and here are two reliable approaches to get the slide-out/slide-in effect you need for your three FrameLayouts. Let’s break them down:

Option 1: Property Animators (ValueAnimator)

This gives you precise control over each view’s movement, perfect for customizing the animation flow.

Step 1: Initialize Menu States

First, set up the initial visibility and position in your onCreate (or onViewCreated for fragments). We’ll hide the secondary and tertiary menus off-screen below the bottom edge:

// Kotlin example; Java works the same way
val primaryMenu = findViewById<FrameLayout>(R.id.primaryMenu)
val secondaryMenu = findViewById<FrameLayout>(R.id.secondaryMenu)
val tertiaryMenu = findViewById<FrameLayout>(R.id.tertiaryMenu)

// Wait for views to finish measuring before setting positions
primaryMenu.viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
    override fun onGlobalLayout() {
        primaryMenu.viewTreeObserver.removeOnGlobalLayoutListener(this)
        // Push secondary/tertiary below the screen initially
        secondaryMenu.translationY = secondaryMenu.height.toFloat()
        tertiaryMenu.translationY = tertiaryMenu.height.toFloat()
        secondaryMenu.visibility = View.INVISIBLE
        tertiaryMenu.visibility = View.INVISIBLE
    }
})

Step 2: Implement the Switch Animation

Create a function to handle the transition when a menu item is clicked. This will slide the current menu down off-screen, then slide the other two up into view:

fun switchToSecondaryAndTertiary() {
    val primaryMenu = findViewById<FrameLayout>(R.id.primaryMenu)
    val secondaryMenu = findViewById<FrameLayout>(R.id.secondaryMenu)
    val tertiaryMenu = findViewById<FrameLayout>(R.id.tertiaryMenu)
    val animDuration = 300L // Adjust speed as needed

    // Slide primary menu down out of view
    ValueAnimator.ofFloat(0f, primaryMenu.height.toFloat()).apply {
        addUpdateListener { anim ->
            primaryMenu.translationY = anim.animatedValue as Float
        }
        addListener(object : Animator.AnimatorListener {
            override fun onAnimationStart(anim: Animator?) {}
            override fun onAnimationEnd(anim: Animator?) {
                primaryMenu.visibility = View.INVISIBLE
            }
            override fun onAnimationCancel(anim: Animator?) {}
            override fun onAnimationRepeat(anim: Animator?) {}
        })
        duration = animDuration
        interpolator = AccelerateDecelerateInterpolator() // Smooth start/end
        start()
    }

    // Slide secondary menu up into view
    secondaryMenu.visibility = View.VISIBLE
    ValueAnimator.ofFloat(secondaryMenu.height.toFloat(), 0f).apply {
        addUpdateListener { anim ->
            secondaryMenu.translationY = anim.animatedValue as Float
        }
        duration = animDuration
        interpolator = AccelerateDecelerateInterpolator()
        start()
    }

    // Slide tertiary menu up into view
    tertiaryMenu.visibility = View.VISIBLE
    ValueAnimator.ofFloat(tertiaryMenu.height.toFloat(), 0f).apply {
        addUpdateListener { anim ->
            tertiaryMenu.translationY = anim.animatedValue as Float
        }
        duration = animDuration
        interpolator = AccelerateDecelerateInterpolator()
        start()
    }
}

To switch back, just reverse the animations: slide secondary/tertiary down, and primary back up into view.

Option 2: Android Transition API (Cleaner & More Declarative)

The Transition API handles view visibility changes with built-in animations, making your code more concise.

Step 1: Define Transitions

Create slide-out and slide-in transitions targeted at your menus:

// Slide current menu down out of the screen
val slideOutDown = Slide(Gravity.BOTTOM).apply {
    duration = 300L
    addTarget(R.id.primaryMenu)
    interpolator = AccelerateDecelerateInterpolator()
}

// Slide secondary/tertiary menus up from below the screen
val slideInUp = Slide(Gravity.BOTTOM).apply {
    duration = 300L
    mode = Slide.MODE_IN // Specify this is an "in" animation
    addTarget(R.id.secondaryMenu, R.id.tertiaryMenu)
    interpolator = AccelerateDecelerateInterpolator()
}

Step 2: Trigger the Transition

Use TransitionManager to animate the visibility change:

fun switchMenus() {
    val primaryMenu = findViewById<FrameLayout>(R.id.primaryMenu)
    val secondaryMenu = findViewById<FrameLayout>(R.id.secondaryMenu)
    val tertiaryMenu = findViewById<FrameLayout>(R.id.tertiaryMenu)

    // Begin transition on the parent layout (control_area)
    TransitionManager.beginDelayedTransition(findViewById(R.id.control_area), TransitionSet().apply {
        addTransition(slideOutDown)
        addTransition(slideInUp)
    })

    // Toggle visibility - the transition will handle the animation
    primaryMenu.visibility = View.INVISIBLE
    secondaryMenu.visibility = View.VISIBLE
    tertiaryMenu.visibility = View.VISIBLE
}

Key Notes

  • View Measurement: Always wait for views to finish measuring before getting their height (using ViewTreeObserver), otherwise you’ll get a height of 0 initially.
  • Interpolators: Using AccelerateDecelerateInterpolator makes the animation feel more natural instead of a linear movement.
  • State Tracking: Keep a variable to track which menus are currently visible so you don’t trigger incorrect animations when switching back and forth.

Either of these approaches will give you the smooth slide transition you’re looking for. Pick the one that fits your coding style best!

内容的提问来源于stack exchange,提问作者milan kumar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 08:56:54