Android -> how to animate to the new position - android

Here is simple xml android animation:
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromXDelta="0" android:fromYDelta="0" android:toXDelta="-110"
android:toYDelta="-110" android:duration="1000" android:fillAfter="true" />
I want to move animated object from the center of the screen to 0, 0 positions. How cat I make it (it should work at all screen resolutions)
My Answer:
Thank you guys for your help. But I have fix my problem by other way, dynamically, without xml. Here's full code of this method:
public void replace(int xTo, int yTo, float xScale, float yScale) {
// create set of animations
replaceAnimation = new AnimationSet(false);
// animations should be applied on the finish line
replaceAnimation.setFillAfter(true);
// create scale animation
ScaleAnimation scale = new ScaleAnimation(1.0f, xScale, 1.0f, yScale);
scale.setDuration(1000);
// create translation animation
TranslateAnimation trans = new TranslateAnimation(0, 0,
TranslateAnimation.ABSOLUTE, xTo - getLeft(), 0, 0,
TranslateAnimation.ABSOLUTE, yTo - getTop());
trans.setDuration(1000);
// add new animations to the set
replaceAnimation.addAnimation(scale);
replaceAnimation.addAnimation(trans);
// start our animation
startAnimation(replaceAnimation);
}

My solution:
Thank you guys for your help. But I have fix my problem by other way, dynamically, without xml. Here's full code of this method:
public void replace(int xTo, int yTo, float xScale, float yScale) {
// create set of animations
replaceAnimation = new AnimationSet(false);
// animations should be applied on the finish line
replaceAnimation.setFillAfter(true);
// create scale animation
ScaleAnimation scale = new ScaleAnimation(1.0f, xScale, 1.0f, yScale);
scale.setDuration(1000);
// create translation animation
TranslateAnimation trans = new TranslateAnimation(0, 0,
TranslateAnimation.ABSOLUTE, xTo - getLeft(), 0, 0,
TranslateAnimation.ABSOLUTE, yTo - getTop());
trans.setDuration(1000);
// add new animations to the set
replaceAnimation.addAnimation(scale);
replaceAnimation.addAnimation(trans);
// start our animation
startAnimation(replaceAnimation);
}

First, insert object in container that occupies entire screen. Then modify you animation xml like this
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromXDelta="50%p" android:fromYDelta="50%p"
android:toXDelta="0%p" android:toYDelta="0%p"
android:duration="1000"
android:fillAfter="true" />
You can also check this android API reference http://developer.android.com/guide/topics/resources/animation-resource.html#translate-element
%p suffix translates element "in percentage relative to the parent size".

If you want it to work on all screens you aren't going to be able to hardcode x,y values. Animations allow you to use percents. This animation would move your view from 0% x and y(relative to itself. In other words where ever it is before the animation it will start from there) It will move to 0%p x and y (which means 0% relative to the parent) This should take you to the top left. Depending on how far into the corner you want it you may try 5%p or 10%p to get some extra margin.
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromXDelta="0%" android:fromYDelta="0%" android:toXDelta="0%p"
android:toYDelta="0%p" android:duration="1000" android:fillAfter="true" />

In my case I used an ImageView, randomly moved it using setY() and setX() and then animated it on the new position with a Scale animation in xml.
That didn't work. It always started from the initial position and scaled out to the new position.
The way I solved it was to wrap the animated View in a RelativeLayout and then move the RelativeLayout with the ImageView inside it.
PivotX and PivotY always uses the center of the parent view.

Related

How do i apply fade out animation from left to right in android

I am trying to make a fade out animation to a View, but I don't want the standard one. I want the fade out to start from left to right (or right to left no matter). Any idea on how to do it? I didn't really found anything for android on SO. This is my code for the moment:
val fadeOut = AlphaAnimation(1f, 0f)
fadeOut.interpolator = AccelerateInterpolator()
fadeOut.duration = 3000L
fadeOut.setAnimationListener(object : Animation.AnimationListener {
override fun onAnimationStart(animation: Animation) {
}
override fun onAnimationEnd(animation: Animation) {
mTextView.visibility = View.VISIBLE
}
override fun onAnimationRepeat(animation: Animation) {}
})
mTextView.startAnimation(fadeOut)
From what I can understand, it sounds like you want a reveal animation rather than a fade in/out animation. Your best bet would be to write your own reveal Animation, but if you're ready to settle for a simpler hack, then you could use the circular reveal animation that's available in ViewAnimationUtils. Just start the circular far off to the left/right so that the circular reveal feels like a linear reveal.
final View myView = findViewById(R.id.animatedImageView);
int cx = myView.getMeasuredWidth() * 2;
int cy = myView.getMeasuredHeight() / 2;
int finalRadius = (int) Math.hypot(myView.getWidth()*2, myView.getHeight());
Animator anim;
// for reveal
anim = ViewAnimationUtils.createCircularReveal(myView, cx, cy, 0, finalRadius);
// for hiding
// anim = ViewAnimationUtils.createCircularReveal(myView, cx, cy, finalRadius, 0);
// Do note that you'll need to factor in the 'reveal' time taken in by the extra empty space.
// You could probably get around this by creating your own interpolator,
// but in which case, you might as well just create your own reveal animation.
anim.setDuration(3000);
// make the view visible and start the animation
myView.setVisibility(View.VISIBLE);
anim.start();
Try this:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:fillAfter="true">
<alpha
android:duration="1000"
android:fromAlpha="0.0"
android:interpolator="#android:anim/accelerate_interpolator"
android:toAlpha="1.0" />
<translate
android:fromXDelta="100%p" android:toXDelta="0"
android:duration="500" />
</set>

Animate image view current position to top - left corner

I have Relative layout, in that layout I have image views which altogether looks like one image. I want animate the 6 image views. 3 are right_top,right_center,right_bottom and another 3 are left-top,left-center,left-bottom. and all these are within its parent layout only...
I want to implement exactly like this image.
Hope THIS may help you.
And if you want to add scaling to tour animation add this scale inside your each animation set
<scale
android:fromYScale="1.0"
android:toYScale="0.5"
android:startOffset="0"
android:duration="1200"
android:fromXScale="1.0"
android:toXScale="0.5"
android:fillAfter="true" />
siddhu,sorry for late.
#Override
public void onClick(View v) {
TranslateAnimation mAnimation1 = new TranslateAnimation(0, mImageViewX.getX(),
mImageView1.getY(), mImageViewX.getY());
mAnimation1.setDuration(500);
mAnimation1.setFillAfter(true);
mImageView1.startAnimation(mAnimation1);
TranslateAnimation mAnimation2 = new TranslateAnimation(0,
- mImageViewX.getX(), mImageView2.getY(), mImageViewX.getY());
mAnimation2.setDuration(500);
mAnimation2.setFillAfter(true);
mImageView2.startAnimation(mAnimation2);
TranslateAnimation mAnimation3 = new TranslateAnimation(0, mImageViewX.getX(),
mImageView3.getX(), -mImageViewX.getY());
mAnimation3.setDuration(500);
mAnimation3.setFillAfter(true);
mImageView3.startAnimation(mAnimation3);
}
The xml is this :
you should learn animation first..it's not hard.
android.view.animation.TranslateAnimation.TranslateAnimation(float fromXDelta, float toXDelta, float fromYDelta, float toYDelta)
```

Changing the position of an android view appears to change the animation pivot

I'm working in Xamarin (C#) but Java solutions are fine.
I have a custom parent view with a single child view. The parent has a fixed size and position, and the child is supposed to expand into view where the user taps the parent. The expand animation is a simple fade in and scale which should pivot around the centre of the child.
The result I'm currently seeing is that the child always begins the animation at the upper-left corner of the parent and appears to translate to the point the user tapped while scaling and fading properly. This leads me to think that somehow the animation pivot is being interfered with.
How can I move the child element and ensure the animation applied to it still pivots around the local centre point, and what exactly is causing this behaviour I'm currently seeing?
Edit: I've discovered that the root cause of this is that the animation scales the x and y coordinates of the child as well as its width and height, hence when the scale is 0 the child appears at the origin of the parent element, and when the scale is 1 it appears in the correct position. My new question now is: What method can I use to position the child absolutely in the parent without it being affected by scaling?
Thanks.
Parent View Class
public class Parent: RelativeLayout
{
private RelativeLayout _child;
private Animation _animation;
private LayoutParams _layoutParams;
public Parent(Context context, IAttributeSet attrs)
: base(context, attrs)
{
_layoutParams = new RelativeLayout.LayoutParams(64, 64);
_child = new RelativeLayout(context);
_child.LayoutParameters = _layoutParams;
_child.SetBackgroundColor(Color.Red);
_child.Visibility = ViewStates.Invisible;
this.AddView(_child);
_animation = AnimationUtils.LoadAnimation(context, Resource.Animation.Expand);
_animation.AnimationEnd += OnAnimationEnd;
this.Touch += OnTouch;
}
private void OnTouch(object sender, View.TouchEventArgs e)
{
// position the top left of the child view such that
// the center point lies over the touch point
var x = e.Event.GetX() - (_child.Width / 2);
var y = e.Event.GetY() - (_child.Height / 2);
_child.SetX(x);
_child.SetY(y);
_child.StartAnimation(_animation);
_child.Visibility = ViewStates.Visible;
}
}
Expand Animation Resource
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="#android:anim/decelerate_interpolator"
android:shareInterpolator="true"
android:duration="500" >
<scale
android:fromXScale="0"
android:fromYScale="0"
android:pivotX="50%"
android:pivotY="50%"
android:toXScale="1"
android:toYScale="1" >
</scale>
<alpha
android:fromAlpha="0"
android:toAlpha="1" />
</set>
I now have this animation working, although the new approach is more of a workaround than a solution.
By creating the animation programmatically and setting the pivot absolutely within the parent I was able to ensure that the child position and pivot aligned perfectly every time:
private void OnTouch(object sender, View.TouchEventArgs e)
{
// position the top left of the child view such that
// the center point lies over the touch point
var x = e.Event.GetX() - (_child.Width / 2);
var y = e.Event.GetY() - (_child.Height / 2);
_child.SetX(x);
_child.SetY(y);
// define the animation with the pivot absolutely positioned over the center of the child
var animation = new AnimationSet(true);
animation.Interpolator = new DecelerateInterpolator();
animation.Duration = 500;
animation.AddAnimation(new AlphaAnimation(0.4F, 0F));
animation.AddAnimation(new ScaleAnimation(0F, 4F, 0F, 4F,
Dimension.Absolute, x,
Dimension.Absolute, y));
_child.StartAnimation(animation);
_child.Visibility = ViewStates.Visible;
}
If there were a solution which allowed an animation resource to be used and didn't require absolute values that would be far more concise, however.

How to animate layout from top to 300dp of screen vice versa in android?

Requirement
I can translate layout base on toYDelta="100% or toYDelta="50% etc.
But I want to animate layout only in 300dp Height.
slide_down.xml
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="500"
android:fromYDelta="0"
android:toYDelta="100%" />
slide_up.xml
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="500"
android:fromYDelta="100%"
android:toYDelta="0" />
Java Code (Animation)
Animation animation = AnimationUtils.loadAnimation(getActivity().getApplicationContext(),R.anim.slide_down);
animation.setAnimationListener(new AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
// TODO Auto-generated method stub
}
#Override
public void onAnimationRepeat(Animation animation) {
// TODO Auto-generated method stub
}
#Override
public void onAnimationEnd(Animation animation) {
// TODO Auto-generated method stub
// I can hide layout after animation completion
}
});
Mockup
Problem
How to do base on 300dp height?
Please help me for this problem.
Thank you.
View Animation
Surprisingly enough, there does not seem to be a way to specify a 300dp translate animation in XML. The translate animation XML syntax accepts three different distance specifications:
Absolute pixels relative to normal position (e.g. android:toYDelta="10")
Percentage relative to element width/height (e.g. android:toYDelta="10%")
Percentage relative to parent width/height (e.g. android:toYDelta="10%p")
You are also restrained to the same specifications when you create a TranslateAnimation via Java. However, in Java you can calculate the equivalent absolute pixel value (for a given device) and supply that as your pixel translate distance.
To get 300dp, you can either define a dimen value of 300dp in XML, or simply perform the calculation in code.
Inside dimens.xml:
<dimen name="distance">300dp</dimen>
Inside your Activity/Fragment/etc:
float distance = getResources().getDimensionPixelSize(R.dimen.distance);
OR
Inside your Activity/Fragment/etc:
float distance = TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, 300,
getResources().getDisplayMetrics()
);
Then all you need to do is use that distance when creating your TranslateAnimation:
TranslateAnimation animation = new TranslateAnimation(
Animation.ABSOLUTE, 0,
Animation.ABSOLUTE, 0,
Animation.ABSOLUTE, 0,
Animation.ABSOLUTE, distance
);
Property Animation
If you are targeting Android 3.0 and above, you can use the new Property Animation framework to express the same animation more elegantly:
view.animate().translationY(distance).setDuration(...).start();
If you are still targeting Android 2.x, you can use NineOldAndroids to get backwards compatible animation syntax. It will automatically use the new property animations for devices that support it.
ViewPropertyAnimator.animate(view).translationY(distance).setDuration(...).start();

Android: Updating a LinearLayout position after animation is complete

Any help with the following problem would be greatly appreciated. I know what I need to do and I have checked the Developer docs, but the exact syntax I need to use eludes me (I'm a noob).
Here's what I'm doing. I have a translate.xml file in res/anim that works fine. It looks like this:
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromXDelta="0%"
android:toXDelta="0%"
android:fromYDelta="0%"
android:toYDelta="10%"
android:repeatCount="0"
android:duration="1000"
android:fillEnabled="true"
android:fillAfter="true"/>
I'm executing my code like this:
l = (LinearLayout) findViewById(R.id.linearLayout1);
a = AnimationUtils.loadAnimation(this, R.anim.translate);
a.setAnimationListener(new AnimationListener() {
public void onAnimationStart(Animation anim){};
public void onAnimationRepeat(Animation anim){};
public void onAnimationEnd(Animation anim){
//l.setLayoutParams(params);
};
});
l.startAnimation(a);
When the animation is done I would like the LinearLayout it animated to move to it's new position (where the animation moved it to). The reason for this is the LinearLayout contains several form elements the user can interact with.
This is a real simple animation for a fairly simple project. It simply moves the element about 30 pixels down the screen. I wouldn't ask for help except I've been struggling with this for several hours now. I know I need to update the LinearLayout's parameters on the end of the animation, but how exactly? I've read of several different ways and they're all a bit confusing.
Thanks in advance.
Instead of creating a new AnimationListener, try implementing the AnimationListener interface to your current (or a new) class. Then just override the onAnimationEnd() method.
Example:
public class ThisClass implements AnimationListener {
private otherMethod() {
l.getAnimation().setAnimationListener(this);
}
public void onAnimationStart(Animation anim){};
public void onAnimationRepeat(Animation anim){};
public void onAnimationEnd(Animation anim){
l.setLayoutParams(params);
};
}
Finally got a way to work around,the right way to do this is setFillAfter(true),
if you want to define your animation in xml then you should do some thing like this
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="#android:anim/decelerate_interpolator"
android:fillAfter="true">
<translate
android:fromXDelta="0%"
android:toXDelta="-100%"
android:duration="1000"/>
</set>
you can see that i have defined filterAfter="true" in the set tag,if you try to define it in translate tag it won't work,might be a bug in the framework!!
and then in the Code
Animation anim = AnimationUtils.loadAnimation(this, R.anim.slide_out);
someView.startAnimation(anim);
OR
TranslateAnimation animation = new TranslateAnimation(-90, 150, 0, 0);
animation.setFillAfter(true);
animation.setDuration(1800);
someView.startAnimation(animation);
then it will surely work!!
Now this is a bit tricky it seems like the view is actually move to the new position but actually the pixels of the view are moved,i.e your view is actually at its initial position but not visible,you can test it if have you some button or clickable view in your view(in my case in layout),to fix that you have to manually move your view/layout to the new position
public TranslateAnimation (float fromXDelta, float toXDelta, float fromYDelta, float toYDelta)
new TranslateAnimation(-90, 150, 0, 0);
now as we can see that our animation will starts from -90 x-axis to 150 x-axis
so what we do is set
someView.setAnimationListener(this);
and in
public void onAnimationEnd(Animation animation)
{
someView.layout(150, 0, someView.getWidth() + 150, someView.getHeight());
}
now let me explain public void layout (int left, int top, int right, int botton)
it moves your layout to new position first argument define the left,which we is 150,because translate animation has animated our view to 150 x-axis, top is 0 because we haven't animated y-axis,now in right we have done someView.getWidth() + 150 basically we get the width of our view and added 150 because we our left is now move to 150 x-axis to make the view width to its originall one, and bottom is equals to the height of our view.
I hope you people now understood the concept of translating, and still you have any questions you can ask right away in comment section,i feel pleasure to help :)
EDIT Don't use layout() method as it can be called by the framework when ever view is invalidated and your changes won't presist, use LayoutParams to set your layout parameters according to your requirement

Categories

Resources