View.getX/Y and View.setX/Y below Android 3.0 - android

I am working on a project that must work on Android 2.2 onwards, and I just realized I was using a 3.0+ method from View.
I have a menu that animates vertically sliding in/out when a button is pressed. When the animation finishes I update the View position with setY() method.
I tried to change it to getTop/setTop but it's not working properly, I suspect because getY is actually taking into account transformations and getTop is not (I guess animations are handled as transformations).
Any easy alternative for Froyo without modifying too much code?
This is the animation part:
animationSlideInDown = AnimationUtils.loadAnimation(this, R.anim.slide_out_down);
animationSlideOutUp = AnimationUtils.loadAnimation(this, R.anim.slide_in_up);
animationSlideInDown.setDuration(200);
animationSlideOutUp.setDuration(200);
animationSlideInDown.setAnimationListener(new AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
if (menuInitialPosition == -1) {
menuInitialPosition = menu.getY();
menuHeight = menu.getHeight();
} else {
menu.setY(menuInitialPosition);
}
}
#Override
public void onAnimationRepeat(Animation animation) {}
#Override
public void onAnimationEnd(Animation animation) {
menu.setY(menuInitialPosition);
}
});
animationSlideOutUp.setAnimationListener(new AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {}
#Override
public void onAnimationRepeat(Animation animation) {}
#Override
public void onAnimationEnd(Animation animation) {
menu.setY(-menuHeight);
}
});
This is the slide_out transition:
<translate
xmlns:android="http://schemas.android.com/apk/res/android"
android:fromYDelta="-100%"
android:toYDelta="0"
android:fillAfter="true"
android:fillEnabled="true"
android:duration="#android:integer/config_longAnimTime" />
Thanks!

If you want to get position of particular view on the screen than you can use :
int[] locationOnScreen = new int[2];
menu.getLocationOnScreen(locationOnScreen);
And for setting view to particular position you can use LayoutParams and set left and top margin for the view.

Related

How to add delay between animations

I'm having a trouble with animations in android. I have my animation_char.xml:
<set xmlns:android="http://schemas.android.com/apk/res/android">
<alpha
android:duration="300"
android:fromAlpha="0.0"
android:interpolator="#android:anim/accelerate_interpolator"
android:toAlpha="1.0"/>
</set>
That is ok, but in my MainActivity I want to start an animation one after one. So I created a method to make it more easy and just change the ImageView
public void animation(ImageView imageView){
animation = AnimationUtils.loadAnimation(getApplicationContext(),R.anim.animation_char);
imageView.startAnimation(animation);
}
And for make consecutives animations, I'm trying to use AnimatorSet. But as I read AnimatorSet works with Animator, not with Animation. So my question is:
is there a way to load an animation in a animator?? Or should I use another way in order to achieve what I want to do? Thanks in advance!
EDIT
I changed my method and now Im trying with this but the problem is that all the images appear at the same time, how can I add some delay between animations?
public void animation() {
animation= AnimationUtils.loadAnimation(getApplicationContext(),R.anim.animation_char);
w.startAnimation(animation);
a.startAnimation(animation);
r.startAnimation(animation);
}
Actually I've answered on this question here. You should start your second animation in onAnimationEnd of AnimationListener of first animations. The same for second one.
You should use AnimationSet class instead of AnimatorSet.
For instance
AnimationSet as = new AnimationSet(true);
as.setFillEnabled(true);
as.setInterpolator(new BounceInterpolator());
as.addAnimation(firstAnim);
as.addAnimation(secondAnim);
as.setDuration(1000);
imageView.startAnimation(as);
I put this here maybe it helps someone...
I did something like this. I have 3 images that I want to fall one after the other.
note1 = findViewById(R.id.note1);
note1.setVisibility(View.INVISIBLE);
note2 = findViewById(R.id.note2);
note2.setVisibility(View.INVISIBLE);
note3 = findViewById(R.id.note3);
note3.setVisibility(View.INVISIBLE);
Setting visibility so that they are not shown initially
And then create 3 animations
Animation slideDown = AnimationUtils.loadAnimation(this, R.anim.slide_down);
note1.startAnimation(slideDown);
final Animation slideDown2 = AnimationUtils.loadAnimation(SplashScreen.this, R.anim.slide_down);
final Animation slideDown3 = AnimationUtils.loadAnimation(SplashScreen.this, R.anim.slide_down);
Next step is to add the event listeners that #Divers added:
slideDown.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
note1.setVisibility(View.VISIBLE);
note2.startAnimation(slideDown2);
slideDown2.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
note3.startAnimation(slideDown3);
note2.setVisibility(View.VISIBLE);
slideDown3.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
note3.setVisibility(View.VISIBLE);
}
#Override
public void onAnimationRepeat(Animation animation) {
}
});
}
#Override
public void onAnimationRepeat(Animation animation) {
}
});
}
#Override
public void onAnimationRepeat(Animation animation) {
}
});
And that's all
My animation xml is something like
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="800"
android:fromXDelta="0%"
android:fromYDelta="-50%p"
/>
<alpha
android:duration="500"
android:fromAlpha="0.1"
android:toAlpha="1.0"
/>
</set>
If you use Kotlin, you can use this way:
doOnEnd {startDelay = 1000L
start() }
Where repeatCount = 1
look at this example:
val animations = arrayOf(-140f).map { translation ->
ObjectAnimator.ofFloat(binding.viewYatch, "translationX", translation).apply {
//Update
duration = 800
repeatCount = 1
repeatMode = ObjectAnimator.RESTART
doOnEnd {
startDelay = 1000L
start()
}
}
}
val set = AnimatorSet()
set.playTogether(animations)
set.start()

get Y position percentage programmatically

I'm doing some translate animations with a view. I'm trying both ways: By xml and programmatically.
This is how I have defined the translation by xml:
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate android:fromYDelta="0%" android:toYDelta="-70%" android:duration="1000"/>
</set>
This way it works fine, but I've realized that I better need the programmatically way as using the animationListener I can define actions to occurr when the animation finishes.
This is how I do it programmatically:
slide_up = new TranslateAnimation(valuesContainer.getX(),
valuesContainer.getX(),
valuesContainer.getY(),
valuesContainer.getY() - 70);
slide_up.setDuration(1000);
slide_up.setAnimationListener(new AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
// TODO Auto-generated method stub
}
#Override
public void onAnimationRepeat(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
//SOMETHING HAPPENS
}
});
The problem comes when defining the fromYDelta and toYDelta values (the image just moves in the Y axis). In the xml, I do it using percentages (%) and it works the way I need, but I don't know how to set the values this same way but programmatically.
I have come to a solution combining both of this methods.
I define the animation in a xml like this, called f.e. slide_up_anim.xml
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate android:fromYDelta="0%" android:toYDelta="-70%" android:duration="1000"/>
</set>
And then, I set the AnimationListener for this animation this way:
slide_up = AnimationUtils.loadAnimation(getActivity(), R.anim.slide_up_anim);
slide_up.setAnimationListener(new AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationRepeat(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
}
});
This way I can define the fromYDelta and toYDelta in percentage, and also listen for animation events.

setVisibility(View.GONE) doesn't disappear a view

In my activity, I have a start button, and when that's clicked it should fade out and finally disappear by setVisibility(View.GONE)
The problem is setting visibility to GONE doesn't disappear the view, it's still visible. I've purposefully made the view animation fade out to 0.1 (instead of 0) and I can see it in the background even after I've called setVisibility(View.GONE) on it.
The fadeout animation anim_fade_out.xml is:
<?xml version="1.0" encoding="utf-8"?>
<set
xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="#android:anim/linear_interpolator"
android:fillAfter="true" android:fillEnabled="true">
<alpha
android:fromAlpha="1.0"
android:toAlpha="0.1"
android:duration="200" />
</set>
The method is showTimer():
private void showTimer() {
final LinearLayout startButtonArea = (LinearLayout)findViewById(R.id.startButtonArea);
Animation animFadeOut = AnimationUtils.loadAnimation(getApplicationContext(), R.anim.anim_fade_out);
startButtonArea.startAnimation(animFadeOut);
animFadeOut.setAnimationListener(new AnimationListener() {
#Override
public void onAnimationEnd(Animation animation) {
startButtonArea.setVisibility(View.GONE);
Log.d("Animation ended","startButtonArea SHOULD BE GONE BUT IT ISN'T");
}
#Override
public void onAnimationRepeat(Animation animation) {}
#Override
public void onAnimationStart(Animation animation) {}
});
}
To reiterate, I know that the end alpha of the animation is 0.1 (it would be 0 usually) but I want to confirm that the view is really GONE and it isn't.
Because your fillAfter is true, the animation sets the properties after your onAnimationEnd is called. You can either change fillAfter to false, or do it like this:
#Override
public void onAnimationEnd(Animation animation) {
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
startButtonArea.setVisibility(View.GONE);
Log.d("Animation ended","startButtonArea SHOULD BE GONE BUT IT ISN'T");
}
}, 0);
}

how do i start animation after some time in android?

I want to start second animation after the end of first animation.
This is what i have done so far
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="#android:anim/linear_interpolator">
<translate
android:toYDelta="50%p"
android:duration="6000"
android:fillEnabled="false"
android:startOffset="7000"
android:fillAfter="false"/>
</set>
Any help will be appriciated. TIA
Use AnimationListener on your first animation, and when it is completed, start the second animation.
animation1.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
// Start the second animation.
}
#Override
public void onAnimationRepeat(Animation animation) {
}
});

Prevent snap between Android tween animations

I have a series of animations that I call in series like so:
final Animation anim1 = AnimationUtils.loadAnimation(thisObject, R.anim.animation1);
final Animation anim2 = AnimationUtils.loadAnimation(thisObject, R.anim.animation2);
final Animation anim3 = AnimationUtils.loadAnimation(thisObject, R.anim.animation3);
final Animation anim4 = AnimationUtils.loadAnimation(thisObject, R.anim.animation4);
anim1.setAnimationListener(new AnimationListener()
{
public void onAnimationStart(Animation animation) { }
public void onAnimationRepeat(Animation animation) { }
public void onAnimationEnd(Animation animation)
{
image.startAnimation(anim2);
}
});
anim2.setAnimationListener(new AnimationListener()
{
public void onAnimationStart(Animation animation) { }
public void onAnimationRepeat(Animation animation) { }
public void onAnimationEnd(Animation animation)
{
image.startAnimation(anim3);
}
});
// etc...
view.startAnimation(anim1);
While this works, the image snaps back to its original position for a split second between each animation. I've defined android:fillAfter as true in all my animation XML files, but this doesn't seem to change anything. Is there a way to prevent this snap between animations? Or is there a better way to achieve the same effect?

Categories

Resources