To all,
I have animated image with Frame animations that I'm moving from up behind a view and onto the screen. When the TranslateAnimation is done I want to keep the finish position so setFillAfter is set to true.
My issue is that the Frame Animation is stopped when the TranslateAnimation is finished. How can I restart or keep the Frame Animation going?
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
id="selected" android:oneshot="false">
<item android:drawable="#drawable/a" android:duration="200" />
<item android:drawable="#drawable/b" android:duration="200" />
<item android:drawable="#drawable/c" android:duration="200" />
</animation-list>
loadingView = (RelativeLayout) findViewById(R.id.loadingBar);
loadingView.setVisibility(View.VISIBLE);
loadingImage = (ImageView) loadingView.findViewById(R.id.loading);
loadingImage.setBackgroundResource(R.drawable.loading);
animateImages = (AnimationDrawable) loadingImage.getBackground();
translateAnimation = new TranslateAnimation(Animation.RELATIVE_TO_SELF, 0.0f, Animation.RELATIVE_TO_SELF, 0.0f,
Animation.RELATIVE_TO_SELF,0.0f, Animation.RELATIVE_TO_SELF, -1.0f);
translateAnimation.setInterpolator(new AccelerateInterpolator());
translateAnimation.setDuration(2000);
translateAnimation.setFillEnabled(true);
translateAnimation.setFillAfter(true);
translateAnimation.setAnimationListener(new AnimationListener()
{
#Override
public void onAnimationStart(Animation animation)
{
// TODO Auto-generated method stub
animateImages.start();
}
#Override
public void onAnimationEnd(Animation arg0)
{
}
#Override
public void onAnimationRepeat(Animation animation)
{
// TODO Auto-generated method stub
}
});
loadingView.startAnimation(translateAnimation);
I had the same issue, and couldn't find a definitive solution. So a workaround for me was adding a long animation at the end, almost without changes (a Translation animation moving just a few pixels after a long while), so the frame by frame animation keeps playing during some minutes. For my app that's enought. Maybe you find this idea useful.
Related
I wrote code which can change background image random every 5 second.now i want to use fade in/out animation to change background image,but I do not know how I can use this animation.
This is a my source:
void handlechange() {
Handler hand = new Handler();
hand.postDelayed(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
// change image here
change();
}
private void change() {
// TODO Auto-generated method stub
Random rand = new Random();
int index = rand.nextInt(image_rundow.length);
mapimg.setBackgroundResource(image_rundow[index]);
handlechange();
}
}, 4000);
}
At the moment everything is OK. I can change background image random,but I don't know how can I use animation fade in/out.
If anyone knows solution please help me,
thanks.
You need to call these codes.
First, you have to make two xml files for fade in & out animation like this.
fade_in.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<alpha
android:fromAlpha="0.0"
android:toAlpha="1.0"
android:fillAfter="true"
android:duration="2000"
/>
</set>
fade_out.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<alpha
android:fromAlpha="1.0"
android:toAlpha="0.0"
android:fillAfter="true"
android:duration="2000"
/>
</set>
Second, you have to run animation of imageView like below and also you have to set AnimationListener to change fadeout when fadein finish.
Animation fadeOut = AnimationUtils.loadAnimation(YourActivity.this, R.anim.fade_out);
imageView.startAnimation(fadeOut);
fadeOut.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
Animation fadeIn = AnimationUtils.loadAnimation(YourActivity.this, R.anim.fade_in);
imageView.startAnimation(fadeIn);
}
#Override
public void onAnimationRepeat(Animation animation) {
}
});
For fade in animation , create new folder named 'anim' in your res folder and inside it, create 'fade_in.xml' with following code
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >
<alpha
android:duration="#android:integer/config_mediumAnimTime"
android:fromAlpha="0.0"
android:interpolator="#android:anim/decelerate_interpolator"
android:toAlpha="1.0" />
</set>
now to run this animation on your imageview, use following code in your activity
Animation anim = AnimationUtils.loadAnimation(YourActivity.this, R.anim.fade_in);
imageView.setAnimation(anim);
anim.start();
for fadeout animation, just swap values of android:fromAlpha and android:toAlpha
Hope this helps.
You can use relativeLayout, and add one layer of background view which set both height and width match_parent. All other UI element should put on top of this view. In your code. Define fadeOut and fadeIn animation. Find that background view by id, then do this:
xxxBackground.startAnimation(fadeOut);
xxxBackground.setBackgroundResource(R.drawable.your_random_pic);
xxxBackground.startAnimation(fadeIn);
You can use some interpolator to tune the performance.
You need AnimationDrawable with animation.
First step AnimationDrawable
-Create a file /res/anim/anim_android.xml
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"android:oneshot="false">
<item android:drawable="#drawable/android_1"
android:duration="100"/>
<item android:drawable="#drawable/android_2"
android:duration="100"/>
<item android:drawable="#drawable/android_3"
android:duration="100"/>
<item android:drawable="#drawable/android_4"
android:duration="100"/>
<item android:drawable="#drawable/android_5"
android:duration="100"/>
<item android:drawable="#drawable/android_6"
android:duration="100"/>
<item android:drawable="#drawable/android_7"
android:duration="100"/>
</animation-list>
-Add a ImageView with android:src="#anim/anim_android".
<ImageView
android:id="#+id/myanimation"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#anim/anim_android" />
Second step
-In your activity create AnimationDrawable and Animation
AnimationDrawable animationDrawable = (AnimationDrawable) imageView.getDrawable();
animationDrawable.setOneShot(true);
animationDrawable.start();
Animation animation = AnimationUtils.loadAnimation(YourActivity.this, android.R.anim.fade_in);
imageView.setAnimation(animation);
animation.start();
animation.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
Animation fadeOut = AnimationUtils.loadAnimation(YourActivity.this, android.R.anim.fade_out);
imageView.startAnimation(fadeOut);
}
#Override
public void onAnimationRepeat(Animation animation) {
}
});
you don't need Handler.
Answer by kimkevin animates a View (be it an ImageView, TextView etc.) and not a background of a View. Which means if you want to just highlight any View, you'll have to add another View behind it (lets call it backgroundView) and animate that backgroundView.
Use the following code for animating background of a view
val startColor = view.solidColor
val endColor = ContextCompat.getColor(context, R.color.your_color)
val colorAnim = ObjectAnimator.ofInt(view, "backgroundColor", startColor, endColor, startColor)
colorAnim.duration = 2000
colorAnim.setEvaluator(ArgbEvaluator())
colorAnim.start()
I use API 10.
I have an ImageView nested inside of a LinearLayout. The ImageView has an OnClickListener (or an OnTouchListener, I'm sure which one I ll use at the end). The ImageView is centered on the screen, and when clicked it performs the following animation.
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:fillEnabled="true"
android:fillAfter="true"
>
<alpha
android:fromAlpha="1"
android:toAlpha="0"
android:duration ="500"
/>
<translate
android:fromXDelta="0%"
android:toXDelta="-100%p"
android:duration ="1000"
/>
</set>
The problem is that after the animation ends, it returns to its first position, faded out to 0, but it is still clickable even if it doesn't show up. I click on an empty space where the ImageView was first positioned, and it performs the the animation again. Like clicking a ghost.
How do I make it so that the ImageView stays at the position written at android:toXDelta ??
You can set an animationListener to your animation to tackle the problem, I created this simple fonction:
public void startAnimation(final View v, final int animationResourceId, AnimationListener l){
Animation anim;
if(v!=null){ // can be null, after change of orientation
anim = AnimationUtils.loadAnimation(v.getContext(),resId);
v.setAnimation(anim);
anim.setAnimationListener(l);
v.startAnimation(anim);
}
}
Then every time I need to animate an view, I can do something like this:
startAnimation(myView, R.anim.my_anim, new AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationRepeat(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
myView.setVisibility(View.GONE);
}
});
I am creating an animation in android for two buttons.Button1 moves from bottom center to center of the screen vertically upwards direction(say in 2 seconds).Once it reaches there,the image should be there for say 2 seconds.Then the second image moves from center_right side of the screen to the center_left side of the screen while the first button is still present.Can some body please tell me how to make the first image be there for some time on the screen.Following is my code :
R.anim.alpha
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:fromYDelta="200%p"
android:toYDelta="-11%p"
android:duration="3000"
android:repeatCount="infinite"
/>
</set>
R.anim.anim_card
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:fromXDelta="600%"
android:toXDelta="-100%"
android:repeatCount="infinite"
android:duration="4000"
android:fillAfter="true"
/>
</set>
And in Java code:
Animation a = AnimationUtils.loadAnimation(this, R.anim.alpha);
a.reset();
_image.clearAnimation();
_image.startAnimation(a);
Animation b =AnimationUtils.loadAnimation(this, R.anim.anim_card);
b.reset();
btn_card.clearAnimation();
btn_card.startAnimation(b);
You will have to use AnimationListener for that:
Animation a = AnimationUtils.loadAnimation(this, R.anim.alpha);
a.reset();
_image.clearAnimation();
_image.startAnimation(a);
Animation b =AnimationUtils.loadAnimation(this, R.anim.anim_card);
b.reset();
a.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
btn_card.clearAnimation();
btn_card.startAnimation(b);
}
});
Hope it helps.
In my Android app, I have a floating Activity. It's started from outside my app using ActivityOptions.makeScaleUpAnimation to scale up from an "originating" rectangle. When my Activity finishes, I'd like it to do the reverse of that animation: i.e. it shrinks back to that rectangle as it fades out.
I know I can get the rectangle with getIntent().getSourceBounds(), and I'd hoped to be able to use overridePendingTransition() when finishing to achieve this effect, but overridePendingTransition() can only accept a fixed XML resource: there doesn't seem to be a way to make that animation depend on the source bounds. Is there something else I can use to achieve this effect?
My app is for API 11+, but as it's a cosmetic effect only, I'd be satisfied with a solution that depends on a later version.
I don think there is a way to scale down the activity window other than the overridePendingTransition call. However this code may help:
Scale up
ActivityOptions opts = ActivityOptions.makeCustomAnimation(getActivity(), R.anim.scale_up, 0);
startActivity(new Intent(this, SecondActivity.class),opts.toBundle());
Here is the scale_up animation file:
<set xmlns:android="http://schemas.android.com/apk/res/android">
<scale
android:fromXScale="0"
android:toXScale="1.0"
android:fromYScale="0"
android:toYScale="1.0"
android:pivotX="50%p"
android:pivotY="50%p"
android:duration="500"/>
</set>
Scale down
Call this code from the exiting activity:
finish();
overridePendingTransition(0, R.anim.scale_down);
Here is the scale_down animation file:
<set xmlns:android="http://schemas.android.com/apk/res/android">
<scale
android:fromXScale="1.0"
android:toXScale="0"
android:fromYScale="1.0"
android:toYScale="0"
android:pivotX="50%p"
android:pivotY="50%p"
android:duration="250"/>
</set>
You can vary the X and Y scale to get the desired rectangle. Hope this helps.
Based on my last comment, here is the solution which i have tried and it works. You may have to modify to suit your requirements.
Implement a Activity with Transparent background and with no title inside the manifest:
<activity
android:name="com.example.backgroundsensor.AnimatedActivity"
android:theme="#android:style/Theme.Translucent.NoTitleBar"
android:label="Animated activity" />
and let it set the content view with a layout as :
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/transparent"
tools:ignore="MergeRootFrame" >
<View
android:id="#+id/visibleAreaView"
android:layout_width="300dp"
android:layout_height="300dp"
android:layout_gravity="center"
android:background="#android:color/holo_green_dark" />
</FrameLayout>
The visibleAreaView is the one you will see on the screen, since activity is transparent. You can set the bounds of the view in OnCreate of the activity().
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.animated_activity);
// set the bounds of the animateView
}
Also, Override the finish method something like this:
boolean animateFirst=true;
#Override
public void finish() {
if(animateFirst)
{
animateFirst = false;
loadAnim();
}else
{
super.finish();
}
}
public void loadAnim() {
View v = findViewById(R.id.animateView);
float x= v.getX() + v.getRight()/2;
float y = v.getY();
anim = new ScaleAnimation(1.0f, 0.0f,1.0f, 0.0f, x, y);
anim.setDuration(300);
anim.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) {
findViewById(R.id.animateView).setVisibility(View.GONE);
AnimatedActivity.this.finish();
}
});
v.startAnimation(anim);
}
I have two linear layouts which I want to perform two different animation on both of these layouts and at the same time.
Now its working in sequential manner. i.e, after completing one its starting another.
here is my code.
Animation inFromRight = new TranslateAnimation(
Animation.RELATIVE_TO_PARENT, +0.0f,
Animation.RELATIVE_TO_PARENT, 0.0f,
Animation.RELATIVE_TO_PARENT, 0.0f,
Animation.RELATIVE_TO_PARENT, 0.0f);
inFromRight.setDuration(500);
inFromRight.setInterpolator(new AccelerateInterpolator());
Animation outtoLeft = new TranslateAnimation(
Animation.RELATIVE_TO_PARENT, 0.0f,
Animation.RELATIVE_TO_PARENT, -1.0f,
Animation.RELATIVE_TO_PARENT, 0.0f,
Animation.RELATIVE_TO_PARENT, 0.0f);
outtoLeft.setDuration(500);
outtoLeft.setInterpolator(new AccelerateInterpolator());
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.menu:
mainLayout.startAnimation(outtoLeft);
sideBar.startAnimation(inFromRight);
break;
}
}
outtoLeft.setAnimationListener(new AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationRepeat(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
mainLayout
.setLayoutParams(new LayoutParams(
LayoutParams.FILL_PARENT,
LayoutParams.FILL_PARENT, 40));
}
});
I think you need to use an AnimationSet.
From the doc:
Represents a group of Animations that should be played together. The
transformation of each individual animation are composed together into
a single transform.
Here you can see how an AnimationSet is supposed to be.
In your Activity
ImageView reusableImageView = (ImageView)findViewById(R.id.imageView1);
reusableImageView.setImageResource(R.drawable.flag);
reusableImageView.setVisibility(View.VISIBLE);
Animation an = AnimationUtils.loadAnimation(this, R.anim.yourAnimation);
reusableImageView.startAnimation(an);
Then, in yourAnimation.xml define all the animations you want
<set
xmlns:android="http://schemas.android.com/apk/res/android"
android:shareInterpolator="false">
<scale
android:pivotX="50%"
android:pivotY="50%"
android:fromXScale="1.0"
android:fromYScale="1.0"
android:toXScale="2.0"
android:toYScale="2.0"
android:duration="2500" />
<scale
android:startOffset="2500"
android:duration="2500"
android:pivotX="50%"
android:pivotY="50%"
android:fromXScale="1.0"
android:fromYScale="1.0"
android:toXScale="0.5"
android:toYScale="0.5" />
<rotate
android:fromDegrees="0"
android:toDegrees="360"
android:pivotX="50%"
android:pivotY="50%"
android:duration="5000" />
</set>
The way to solve this problem is to use an AnimatorSet with Animator objects. If you are worried about backwards compatibility, you can use the NineOldAndroids library to bring the API back all the way to Android 1.0
I solved it starting second animation in onAnimationStart event of the first animation. In my example right layout replacing left one, both of them are moving left at the same time. I use animate property of a View class http://developer.android.com/reference/android/view/View.html#animate() which is available starting API v.12
leftLayout.animate()
.translationX(-leftLayout.getWidth()) // minus width
.setDuration(300)
.setListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationStart(Animator animation) {
rightLayout.animate()
.translationX(-leftLayout.getWidth()) // minus width
.setDuration(300)
.setListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationEnd(Animator animation) {
leftLayout.setVisibility(View.GONE);
leftLayout.setTranslationX(0f); // discarding changes
rightLayout.setTranslationX(0f);
}
});
}
});