mira
mira

Reputation: 1056

Android translate animation - permanently move View to new position using AnimationListener

I have android translate Animation. I have an ImageView with random generated position (next1, next2). I am calling void every 3 seconds. It generates new position of the View and then make animation and move View to destination position. Translate animation has AnimationListener implemented. When the animation finish, I move View permanently to the new position (in OnAnimationEnd). My problem is that animation position does not correspond with setting layoutParams positions. When animation end, it makes jump to a new position, which is about 50-100 pixels far. I think the positions should be the same because I use same values (next1, next2) in both situations. Please can you show me the way to find sollution ? Drawing of situation here here

 FrameLayout.LayoutParams pozice_motyl = (FrameLayout.LayoutParams)  pozadi_motyl.getLayoutParams();    
            TranslateAnimation anim = new TranslateAnimation(Animation.ABSOLUTE,pozice_motyl.leftMargin, Animation.ABSOLUTE, next1, Animation.ABSOLUTE, pozice_motyl.topMargin, Animation.ABSOLUTE, next2);
            anim.setDuration(1000);
            anim.setFillAfter(true);
            anim.setFillEnabled(true);

            anim.setAnimationListener(new Animation.AnimationListener() {
                @Override
                public void onAnimationStart(Animation animation) {
                }

                @Override
                public void onAnimationEnd(Animation animation) {




                    FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(100, 100);

                    layoutParams.leftMargin = (int)(next1);
                    layoutParams.topMargin = (int)(next2);
                    pozadi_motyl.setLayoutParams(layoutParams);

                }

                @Override
                public void onAnimationRepeat(Animation animation) {

                }
            });

            pozadi_motyl.startAnimation(anim);

Here is XML layout:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:ads="http://schemas.android.com/apk/lib/com.google.ads"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" 
    android:id="@+id/pozadi0"
    android:gravity="center_vertical"
    android:layout_gravity="center_vertical"          
    android:background="@drawable/pozadi2"
    >



<LinearLayout
android:id="@+id/pozadi_motyl"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        >

  <ImageView android:id="@+id/obrazek_motyl"
             android:src="@drawable/motyl"
             android:layout_width="100dip"
             android:layout_height="100dip"
                         />

   </LinearLayout>


<LinearLayout 
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>

<RelativeLayout
android:id="@+id/obrazek_pozadi0"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>



 <ImageView android:id="@+id/zaba_obrazek0"
android:src="@drawable/zaba_obrazek"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerInParent="true"
/>

</RelativeLayout>   
</LinearLayout> 

<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent" 
>

<cz.zaba.Spojnice  
android:layout_width="fill_parent"          
android:layout_height="fill_parent" 
/>

</LinearLayout>
</FrameLayout>

Upvotes: 44

Views: 118320

Answers (7)

Sanjay S Gangwar
Sanjay S Gangwar

Reputation: 1

Just add this function. And we are good to goo.. 🫶🏻


fun moveView(viewToMove: View, targetView: View, repeatCount: Int? = 10) {
    val viewToMovePos = IntArray(2)
    viewToMove.getLocationOnScreen(viewToMovePos)

    val targetViewPos = IntArray(2)
    targetView.getLocationOnScreen(targetViewPos)

    // Calculate the distance to move
    val moveX = targetViewPos[0] - viewToMovePos[0]
    val moveY = targetViewPos[1] - viewToMovePos[1]

    // Create a TranslateAnimation for the movement
    val animation = TranslateAnimation(0f, moveX.toFloat(), 0f, moveY.toFloat())
    animation.duration = 300 // Set the duration of the animation (in milliseconds)

    // Set animation properties (optional)
    animation.fillAfter = true
    animation.repeatCount = repeatCount ?: 10


    // Start the animation on the source view
    viewToMove.startAnimation(animation)
}

Upvotes: -1

Hitesh Sahu
Hitesh Sahu

Reputation: 45052

Listing down 3 ways to achieve this for future reference

fun translateView(viewToAnimate: View, positionX: Int) {
        

Animate View directly

        viewToAnimate.animate()
            .x(positionX)
            .setDuration(600L)
            .setInterpolator(defaultAnimationInterpolator)
            .start()

Object Animator

         ObjectAnimator.ofFloat(
            viewToAnimate,
            View.X,
            positionX
        ).apply {
            duration = 600
            interpolator = defaultAnimationInterpolator
        }.start()

Value Animator

        ValueAnimator.ofFloat(viewToAnimate.x, positionX).apply {
            duration = 2000
            interpolator = defaultAnimationInterpolator
            addUpdateListener {
                viewToAnimate.x = it.animatedValue as Float
            }
            start()
        }
    }

Upvotes: 1

Rushi Ayyappa
Rushi Ayyappa

Reputation: 2848

Just Do like this

view.animate()
            .translationY(-((root.height - (view.height)) / 2).toFloat())
            .setInterpolator(AccelerateInterpolator()).duration = 1500

Here, view is your View which is animating from its origin position. root is root View of your XML file.

Calculation inside translationY is made for moving your view to the top but keeping it inside the screen, otherwise, it will go partially outside of the screen if you keep its value 0.

Upvotes: 12

Bajrang Hudda
Bajrang Hudda

Reputation: 3268

You can try this way -

ObjectAnimator.ofFloat(view, "translationX", 100f).apply {
    duration = 2000
    start()
}

Note - view is your view where you want animation.

Upvotes: 2

Debasish Ghosh
Debasish Ghosh

Reputation: 1887

This is what worked for me perfectly:-

// slide the view from its current position to below itself
public void slideUp(final View view, final View llDomestic){

    ObjectAnimator animation = ObjectAnimator.ofFloat(view, "translationY",0f);
    animation.setDuration(100);
    llDomestic.setVisibility(View.GONE);
    animation.start();

}

// slide the view from below itself to the current position
public void slideDown(View view,View llDomestic){
    llDomestic.setVisibility(View.VISIBLE);
    ObjectAnimator animation = ObjectAnimator.ofFloat(view, "translationY",   0f);
    animation.setDuration(100);
    animation.start();
}

llDomestic : The view which you want to hide. view: The view which you want to move down or up.

Upvotes: 2

Gil Moshayof
Gil Moshayof

Reputation: 16761

I usually prefer to work with deltas in translate animation, since it avoids a lot of confusion.

Try this out, see if it works for you:

TranslateAnimation anim = new TranslateAnimation(0, amountToMoveRight, 0, amountToMoveDown);
anim.setDuration(1000);

anim.setAnimationListener(new TranslateAnimation.AnimationListener() {

    @Override
    public void onAnimationStart(Animation animation) { }

    @Override
    public void onAnimationRepeat(Animation animation) { }

    @Override
    public void onAnimationEnd(Animation animation) 
    {
        FrameLayout.LayoutParams params = (FrameLayout.LayoutParams)view.getLayoutParams();
        params.topMargin += amountToMoveDown;
        params.leftMargin += amountToMoveRight;
        view.setLayoutParams(params);
    }
});

view.startAnimation(anim);

Make sure to make amountToMoveRight / amountToMoveDown final

Hope this helps :)

Upvotes: 57

bpr10
bpr10

Reputation: 1096

You should rather use ViewPropertyAnimator. This animates the view to its future position and you don't need to force any layout params on the view after the animation ends. And it's rather simple.

myView.animate().x(50f).y(100f);

myView.animate().translateX(pixelInScreen) 

Note: This pixel is not relative to the view. This pixel is the pixel position in the screen.

Upvotes: 50

Related Questions