I'm using Rotate3dAnimation to flip a card view which contains a ScrollView. But during animation ScrollView loses a clip somehow so I see top and bottom of ScrollView content outside the card view (and ScrollView) bounds until animation is done.
Why is that and how to beat this behaviour?
This unfortunately happens due to the way the bounds for the ScrollView are calculated. It seems the bounds are not "rotated" along with the view.
One work around is to take a snapshot of each view - both the front and the back of the card - and then to animate between these snapshots above the actual views.
The code would look something like this:
firstView.setDrawingCacheEnabled(true);
firstAnimationView.setBackgroundDrawable(new BitmapDrawable(firstView.getDrawingCache()));
secondView.setDrawingCacheEnabled(true);
secondAnimationView.setBackgroundDrawable(new BitmapDrawable(secondView.getDrawingCache()));
Animation flipOutAnimation = createFlipOutAnimation();
flipOutAnimation.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationEnd(Animation animation) {
firstAnimationView.setVisibility(View.GONE);
}
...
});
Animation flipInAnimation = createFlipInAnimation();
flipInAnimation.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationEnd(Animation animation) {
animationBackgroundView.setVisibility(View.GONE);
secondAnimationView.setVisibility(View.GONE);
}
...
});
firstAnimationView.startAnimation(flipOutAnimation);
secondAnimationView.startAnimation(flipInAnimation);
animationBackgroundView.setVisibility(View.VISIBLE);
firstAnimationView.setVisibility(View.VISIBLE);
secondAnimationView.setVisibility(View.VISIBLE);
For backwards compatible flip animations, I use http://genzeb.github.io/flip/
Related
I am developing two different animations as shown below.
The first animation I was able to develop using Object animator and FrameLayout. Basically, I created the two rectangles and the candlesticks inside a gravity-centered frame layout. When made to start the animation, I used the object animator to move them on either side and return to the initial position.
My second animation is the issue point here. In this animation, the rectangles will go on a circular path from their initial point and return back to their initial point. During this course, the candles need to move in sync with the rectangle giving a spring effect (or) kind of a sliced rectangle.
My initial idea was to re-use the first animation and just as the first animation runs, I would run a rotate animation on the frameLayout view.
But that doesn't seem to work wherein rotation works but the translation doesn't.
Can someone say if I have taken the right approach or should I use some other way to achieve this?
Adding the code that I have tried, but didn't work.
Animation anim = new RotateAnimation(0.0f, 360.0f, pivotX, pivotY);
anim.setDuration(500);
anim.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
for(View view : mCandleSticks) {
ObjectAnimator anim1 = ObjectAnimator.ofFloat(view, "translationX", view.getX(), targetPos, view.getX());
anim1.setDuration(500);//set duration
anim1.start();//start animation
}
}
#Override
public void onAnimationRepeat(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
}
});
frameLayout.startAnimation(anim);
Thanks in advance.
I am running into an issue where I have a header view that I would like to translate in and out of visibility--using translate animation--that is positioned directly above the main content view. To illustrate what I mean, look at the image below. The blue section is the header, and the orange section is the main content.
Example code
TranslateAnimation animation = new TranslateAnimation(0, 0, 0, -rlInfoBar.getHeight());
animation.setFillAfter(true);
animation.setDuration(10000);
animation.setAnimationListener(new TranslateAnimation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
}
#Override
public void onAnimationRepeat(Animation animation) {
}
});
rvItems.startAnimation(animation);
rlInfoBar.startAnimation(animation);
When I translate the blue section, even though the main section is declared "android:layout_below="#+id/" it remains in position. My idea was to then translate them both, however, when doing that the main content is shifted up but the bottom of the screen is also shifted up revealing the background of the parent view. How to solve this issue? Do I have to translate both views plus stretch the main content view or somehow anchor the main content view to the bottom of the screen?
Result of translating both views
Do I have to translate both views plus stretch the main content view or somehow anchor the main content view to the bottom of the screen?
Well, if you don't stretch the main content View then anchoring it to the bottom will cause a gap to appear at the top as soon as the header View moves up. So I think you'll need a set of animations (scale and translate) for it.
Or you use the Transition framework, in this case a ChangeBounds transition will do the job for both Views
View sceneRoot = <someViewGroupContainingBothViews>;
TransitionManager.beginDelayedTransition(sceneRoot, new ChangeBounds());
rlInfoBar.setY(<newY_CoordinateOfHeaderView>);
I am doing an animation inside a fragment.
I have 2 views on top of each other, one of them set on View.GONE.
when I press a button I want my 2nd fragment to translate animation from the bottom to top.
I am doing it fine and it's working great,
the problem is that in my first run, the xml view is gone, but he is in the same Y he is suppose to be.
so the first animation I do isn't doing anything, just switch from GONE to VISIBLE, after that, I press dismiss and the fragment goes away and comes back just like I want too.
my problem is just the first run.
how can I set my view Y to be 100% below my screen?
here's the code I use :
private void moreCustomAnimation() {
int yOffset = moreMenuFrameLayout.getMeasuredHeight();
TranslateAnimation moveAnim = new TranslateAnimation(0, 0, yOffset, 0);
moveAnim.setDuration(500);
moveAnim.setFillAfter(true);
blackView.setVisibility(View.VISIBLE);
moreMenuFrameLayout.setVisibility(View.VISIBLE);
moreMenuFrameLayout.startAnimation(moveAnim);
moveAnim.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
}
#Override
public void onAnimationRepeat(Animation animation) {
}
});
}
on the way out of the screen I use the same code just switch the
yOffset to the other Y integer, and set the view to GONE at animation end.
thanks a lot in advance for any help !
You can use the onGlobalLayout event to set the position of the view.
Like this:
moreMenuFrameLayout.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
moreMenuFrameLayout.setTranslationY(moreMenuFrameLayout.getMeasuredHeight());
moreMenuFrameLayout.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
});
This event happens when your views get their actual size and position before being drawn to the screen. However, they happen every time the view is drawn so you must remember to remove the listener right after the first time.
HTH
First time you can add the 'yOffset' value to the view orginal points
moreMenuFrameLayout.setY(currentYpostition + yOffset)
and this will place the view to the bottom of the screen. You can enable the visibility when the animation starts.
I have a LinearLayout, I'm applying a translation animation to it. I'm filling the animation before and after. Visually it works fine. The animation ends by translating the view off screen. But if I click an x,y coordinate on screen that happens to be where the view was at some point during its animation, a button on the view has its click listener fire.
The only solution I've found is to add an animation listener, and when the animation ends, mark the buttons on the (now out of view) layout to visibility=gone, enabled=false. This seems bizarre - the view is no longer on screen, but it's still responding to click events. Is this a known thing, I'm probably not setting the animation up correctly?
Thanks
----- Update --------
I refactored my animation a little. Instead of using animation.setFillAfter(true), I set the layout's visibility to GONE when the animation is complete. Now it doesn't register clicks when off-screen. Still interested to know if this is a known thing, as it'd be easier to simply not have to add an animation listener etc.
Translate Animations on lower level API( below honey comb) changes where the button is drawn, but not where the button physically exists within the container. So, you are on your own to handle this situation. For more information about this you can refer to this link. One way is to actually change the location of the button in the layout(not by animation). Here is how you can achieve this:
params = (LayoutParams) mBtn.getLayoutParams();
TranslateAnimation animation = new TranslateAnimation(0, 0, 0, 400);
animation.setDuration(2000);
animation.setAnimationListener(mAnimationListener);
mBtn.startAnimation(animation);
....
....
private AnimationListener mAnimationListener = new AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationRepeat(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
params.topMargin = params.topMargin + 400;
mButton.setLayoutParams(params);
}
};
Here by changing the layout params we are changing the physical position of the button.
In your case as view is going off the screen so you just need to change the visibility of the button(View.GONE) on animation end.
found many question on same issue.
How to set OnClickListener on the ImageView after rotation animation
How to write the onclick listener for a view after animation?
i also have same issue, any suggestion ?
You ought to write a fresh, concise question about your specific issue rather than just pointing to other questions. The two questions linked to aren't entirely clear.
I assume your issue is that after applying an animation (such as a TranslateAnimation, for example) to a View, the View no longer responds to touch events in its new position. The reason for this is because the View hasn't been moved to the new position in terms of layout parameters, but rather it has had a transformation applied.
The solution is quite simple: immediately after the animation has completed, actually move the View to the new position. You could set myAnimation.setFillAfter() = false, and set a listener to physically move the View to the target location when the animation has finished:
myAmazingAnimation.setFillAfter() = false;
myAmazingAnimation.setAnimationListener(new Animation.AnimationListener(){
#Override
public void onAnimationEnd(Animation animation) {
// Now actually move the View using LayoutParams
}
#Override
public void onAnimationRepeat(Animation animation) {
}
#Override
public void onAnimationStart(Animation animation) {
}
});
Another variation is to physically move the View at the beginning before animation is applied, and then apply an animation that makes the View start where it used to be and end at 0,0.