Reputation: 32221
At the first click of a button, I want to slide a View
along the x-axis (by 200 pixels to the right let's say). And on the second press of the button, I want to slide the View
back along the x-axis to its original position.
The View.setTranslationX(float)
method jumps the View to the target horizontal locations with calls myView.setTranslationX(200);
and myView.setTranslationX(0);
respectively. Anyone know how I can slide the View
to the target horizontal locations instead?
Note 1: A
TranslateAnimation
is no good since it doesn't actually move theView
but only presents the illusion of it moving.Note 2: I didn't realise at the time of posing the question that the
setTranslationX(float)
andsetTranslationY(float)
methods were introduced as of API Level 11. If you're targeting Honeycomb (API Level 11) upwards, then Gautam K's answer will suffice. Otherwise, see my answer for a suggested solution.
Upvotes: 21
Views: 44763
Reputation: 32221
This one's had me stumped for a fair few days (getting it to work pre- Ice Cream Sandwich) but I think I've finally got there! (thanks to Gautam K and Mike Israel for the leads) What I did in the end was to extend my View
(a FrameLayout
) to start the translate right/left animations as required and to listen for the end of the animations in order to relocate my FrameLayout
right/left as appropriate, as follows:
public class SlidingFrameLayout extends FrameLayout
{
private final int durationMilliseconds = 1000;
private final int displacementPixels = 200;
private boolean isInOriginalPosition = true;
private boolean isSliding = false;
public SlidingFrameLayout(Context context)
{
super(context);
}
public SlidingFrameLayout(Context context, AttributeSet attrs)
{
super(context, attrs);
}
public SlidingFrameLayout(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
}
@Override
protected void onAnimationEnd()
{
super.onAnimationEnd();
if (isInOriginalPosition)
offsetLeftAndRight(displacementPixels);
else
offsetLeftAndRight(-displacementPixels);
isSliding = false;
isInOriginalPosition = !isInOriginalPosition;
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom)
{
super.onLayout(changed, left, top, right, bottom);
// need this since otherwise this View jumps back to its original position
// ignoring its displacement
// when (re-)doing layout, e.g. when a fragment transaction is committed
if (changed && !isInOriginalPosition)
offsetLeftAndRight(displacementPixels);
}
public void toggleSlide()
{
// check whether frame layout is already sliding
if (isSliding)
return; // ignore request to slide
if (isInOriginalPosition)
startAnimation(new SlideRightAnimation());
else
startAnimation(new SlideLeftAnimation());
isSliding = true;
}
private class SlideRightAnimation extends TranslateAnimation
{
public SlideRightAnimation()
{
super(
Animation.ABSOLUTE, 0,
Animation.ABSOLUTE, displacementPixels,
Animation.ABSOLUTE, 0,
Animation.ABSOLUTE, 0);
setDuration(durationMilliseconds);
setFillAfter(false);
}
}
private class SlideLeftAnimation extends TranslateAnimation
{
public SlideLeftAnimation()
{
super(
Animation.ABSOLUTE, 0,
Animation.ABSOLUTE, -displacementPixels,
Animation.ABSOLUTE, 0,
Animation.ABSOLUTE, 0);
setDuration(durationMilliseconds);
setFillAfter(false);
}
}
}
And, lastly, to slide the SlidingFrameLayout
right/left, all you've got to do is call the SlidingFrameLayout.toggleSlide()
method. Of course you can tweak this SlidingFrameLayout
for your purposes to slide a greater number of pixels, to slide for longer etc, but this should be sufficient to get you started :)
Upvotes: 5
Reputation: 7958
Try looking into ObjectAnimator and its super class Value Animator
you can do something like this
ObjectAnimator anim = ObjectAnimator.ofFloat(this, "translationX", 0,200);
and then
anim.start();
Use a boolean
value and toggle it with 200,0
in the object animator to slide back
PS: you can use setDuration
method to set how long the animation should take to complete
Try looking at the support library which provides backward compatibility.
As @AdilHussain pointed out there is a library called nineoldandroids which can be used for the same purpose on older androids.
Upvotes: 26
Reputation: 2889
I had a similar issue, TranslateAnimation does actually move the view if you call setFillAfter now (android bug). I had to do something similar so I said, hey lets use an animation listener and then just move everything to the correct location. Unfortunately there is a bug on animation listeners as well (stackoverflow solution). So I created my own layout class according to the solution in the stackoverflow solution and I was good to go :)
Upvotes: 2