简体   繁体   中英

Animate/translate view from position of other view

I have a fab and a framelayout which can host a fragment.

I'm trying to do a translation animation so that my framelayout starts at the position of the fab and ends up at its original position. (complex layout, the fab is in another xml file but <include> in same layout as the frame) So basically step 2 here: How to transform a FAB into a popup menu?

I have tried:

<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromXDelta="340"
    android:fromYDelta="431"
    android:toXDelta="0"
    android:toYDelta="0"
    android:duration="1000"
    android:fillAfter="true" />

and

val anim = TranslateAnimation(340f, 0f, 431f, 0f)

with

 myFab.setOnClickListener {
    val frame = my_frame_im_about_to_fill_with_a_fragment
    frame.startAnimation(anim)
 }

So I tried with the values I get from these methods

myFab.getLocationOnScreen()
myFab.getLocationInWindow()

Both methods give (891, 1130) . I've tried plugging those in or converting it to dp, that gets it closer(not very close still though).

Another strange thing is that I thought if I used absolute values in the animation I thought zero would be top left of the screen but it isn't. x: 0 y: 0 give me the same results as 0%,0% and 0%p,0%p . they all animate the view to the top left point of where the framelayout is in constrained to in the xml

How do I translate a view from another view to 'itself'?

Use ConstraintLayout for your layout, put your view constraints to starting position (here I will animate @+id/view after clicking @+id/fab . Animated view has to be VISIBLE or INVISIBLE - GONE will mess up animation.

    <androidx.constraintlayout.widget.ConstraintLayout
             /*constraint stuff*/>       
                <View
                    android:id="@+id/view"
                    android:layout_width="120dp"
                    android:layout_height="120dp"
                    android:visibility="invisible"
                    app:layout_constraintEnd_toEndOf="parent"
                    app:layout_constraintBottom_toBottomOf="parent" />

                <com.google.android.material.floatingactionbutton.FloatingActionButton
                    android:id="@+id/fab"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginEnd="8dp"
                    android:layout_marginBottom="120dp"
                    app:layout_constraintBottom_toTopOf="@+id/bottom_navigation"
                    app:layout_constraintEnd_toEndOf="@+id/symbolList" />

   </androidx.constraintlayout.widget.ConstraintLayout>

There are few options:

  1. Use ObjectAnimator

In your xml file put View that will be animated on fab position:

view = findViewById(R.id.view)
fab = findViewById(R.id.fab)

fab.setOnClickListener {

    view.visibility = View.VISIBLE
    val propertyX = PropertyValuesHolder.ofFloat(View.X, 0f)
    val propertyY = PropertyValuesHolder.ofFloat(View.Y, 0f)
    ObjectAnimator.ofPropertyValuesHolder(view, propertyX, propertyY).apply {
        duration = 2000L
        start()
    }
}
  1. Or use ViewPropertyAnimator (same XML as above)

      fab.setOnClickListener { view.animate() .x(0f) .y(0f) .setDuration(2000L) .start() } 
  2. Or use TransitionManager, MotionLayout, scene api or animate ConstraintSet manually.

     private fun startAnimation() { val animationEndConstraints = ConstraintSet().apply { clone(container) clear(button.id, ConstraintSet.START) clear(button.id, ConstraintSet.TOP) // instead of parent you can use fab.id connect(button.id, ConstraintSet.END, ConstraintSet.PARENT_ID, ConstraintSet.END, 0) connect(button.id, ConstraintSet.BOTTOM, ConstraintSet.PARENT_ID, ConstraintSet.BOTTOM, 0) } TransitionManager.beginDelayedTransition(container) animationEndConstraints.applyTo(container) } 

This approach will allow to specify start state as xml layout and end state as xml layout, but you will have less control.

With other view position:

        fab.setOnClickListener {
            view.animate()
                .x(fab.left.toFloat())
                .y(fab.top.toFloat())
                .setDuration(2000L)
                .start()
        }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM