Trying to add a help overlay to our app.
This overlay is a RelativeLayout with translucent background and it contains a few TextView and a few ImageView child elements. Now, i want each of the TextView / ImageView to fade-in one after another.
I am using a fade-in animation set (defined in the XML) and calling .startAnimation() on each view in the AnimationListener's OnAnimationEnd method. So, when the first View is done fading-in, i call the startAnimation method on the next view to be faded-in. I am using the same Animation object (animationFadeIn) as argument to startAnimation of all the views. Like so:
...
Animation animationFadeIn = AnimationUtils.loadAnimation(this.context, R.anim.fadein);
...
AnimationListener animationInListener = new AnimationListener(){
#Override
public void onAnimationEnd(Animation animation) {
animation_activity++;
switch(animation_activity) {
case SHOW_TEXT_DROP:
txtDrop.startAnimation(animationFadeIn);
break;
case SHOW_TEXT_SEND:
txtSend.startAnimation(animationFadeIn);
break;
case SHOW_IMAGE_TOUCH:
imgTouch.startAnimation(animationFadeIn);
break;
case SHOW_TEXT_DISABLE:
txtDisable.startAnimation(animationFadeIn);
break;
}
}
};
For fade-in animation, i referred this tutorial
Now, here's the problem:
First view fades-in
Second view fades-in, but first view fades-in again as well along with it
Same continues until all the views are done fading-in
Also, how do i add some delay before the next view fades-in setStartOffset ?
UPDATE
I noticed that if i create a second Animation object by
animationFadeIn2 = AnimationUtils.loadAnimation(this.context, R.anim.fadein);
and then use it for the startAnimation of other element, then it does not create this issue. So, i believe, there must be some property to be set on the Animation object so as to avoid this ?
I finally went ahead and created multiple Animation objects for each of the element. That solves the issue for time-being. It may not be the right/best approach.
Related
I'm trying to reuse AlphaAnimation object in a method of an Activity for every new MyView added every second to myLayout:
private AlphaAnimation showAnimation = new AlphaAnimation(0, 1);
private void addViewAndAnimate() {
MyView view = new MyView();
myLayout.addView(view);
showAnimation.setDuration(durationTime);
view.startAnimation(showAnimation);
}
but after I call addViewAndAnimate() the animation is not applied for latest added MyView only, but gets repeated for all MyViews added earlier.
Are view objects somehow bound to an animation? If so is there a way to detach them?
To remove animation from the View, use View.clearAnimation();
So you need to store somewhere a view, to which the animation is applied before, and clear it before applying it to new view. Also you can try to create a new Animation instance for each view.
Or start animation in Handler.post(). This shouldstart animation in the current view for sure
I want to apply an animation for multiple views at the same time, how can I apply said animation to several types of views (buttons, imageviews, and other views)?
If what you want is to apply an animation on several views at the same time, simply call the startAnimation method on those views one after the other. They will be simultaneous
//Get your views
View view1 = findViewById(R.id.view1);
View view2 = findViewById(R.id.view2);
View view3 = findViewById(R.id.view3);
//Get your animation
Animation youranimation = AnimationUtils.loadAnimation(this, R.anim.animationid);
//Start animations
view1.startAnimation(youranimation);
view2.startAnimation(youranimation);
view3.startAnimation(youranimation);
Or if you have a lot of views:
Animation youranimation = AnimationUtils.loadAnimation(this, R.anim.animationid);
int[] viewIds = new int[]{R.id.view1,R.id.view2,R.id.view3,R.id.view4};
for(int id : viewIds) findViewById(id).startAnimation(youranimation);
That is, assuming you want to animate several views at the same time, if what your're doing is one after the other we would dive into animation listeners and that's another story
You may use object animators.
There is an easy example in that link which you can also use.
You may also use this tutorial.
Use ValueAnimator instead, and set views property in onAnimationUpdate.
mShowAnimator = ValueAnimator.ofFloat(0f, 1f);
mShowAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator animation) {
for (View v : mTargetViews) {
v.setAlpha((Float)animation.getAnimatedValue());
}
}
});
You can create one large AnimatorSet() that includes several ObjectAnimators. This allows you to play all animations at the same time with no delay. See my answer here.
In Asyntask, I want to change textswitcher text and If I add new view, app crash.
Code sample:
textSwitcher.setInAnimation(MainActivity.this,android.R.anim.slide_in_left);
textSwitcher.setOutAnimation(MainActivity.this, android.R.anim.slide_out_right);
TextView tv=new TextView(MainActivity.this);
tv.setGravity(Gravity.CENTER | Gravity.LEFT);
tv.setTypeface(custom_font);
tv.setTextColor(Color.parseColor("#00285E"));
textSwitcher.addView(tv);
last line gives error after I decided to remove all views and I added textSwitcher.removeAllViews(); , then it gives null pointer. What do you think for fix ?
ViewSwitcher can only have two children, as it says on the documentation for that class. I personally have not seen anyone using ViewSwitcher, it is an old class and you can get the same effect or better on your own with ObjectAnimators now anyway.
You can create your own ViewGroup that let's you switch any view for any other. If it were me, I would just extend FrameLayout and simply add something like this:
public void switchView(View view) {
// add the new view and reveal
view.setAlpha(0);
addView(view);
view.animate().alpha(1f).start();
if (getChildCount() > 0) {
// simultaneously remove the previous view
final View child = getChildAt(0);
child.animate().alpha(0).setListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationEnd(Animator animator) {
// remove the child when the animation ends
removeView(child);
}
}).start();
}
}
This is completely arbitrary behaviour. You can overwrite ViewAnimator similar to ViewSwitcher class and replace the 0 / 1 handling by a variable subview count. Really easy!
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.