In my android project I have an image that i want to rotate it and create animation for long time.
I can run program and it works fine. but I don't know how can I stop it. if you know please tell me.
Thanks
This is my code, I have a menu with two items, When I click on Start item, startAnimation function runs and when I click on Stop item, stopAnimation runs.:
public class Hypnagogic extends Activity
{
ImageView imView;
Animation an;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
imView = (ImageView)findViewById(R.id.imView);
}
private void startAnimation()
{
an = AnimationUtils.loadAnimation(this, R.anim.spin);
imView.startAnimation(an);
}
private void stopAnimation()
{
;//there is no any stop function!
}
}
also, in res/anim I put spin.xml that is my animation
<?xml version="1.0" encoding="utf-8"?>
<set>
<rotate
android:fromDegrees="0"
android:toDegrees="-18000"
android:pivotX="50%"
android:pivotY="50%"
android:duration="50000" />
</set>
EDIT: I see. Okay, try the clearAnimation() method associated with the View class. You can call it directly on your ImageView, I'm almost certain this should work for your case:
imView.clearAnimation();
What have you tried? AnimationDrawable has a stop() method. You need to post how you're creating/starting the animation.
Related
I'm doing the following simple animation in Android:
<?xml version="1.0" encoding="UTF-8"?>
<rotate
xmlns:android="http://schemas.android.com/apk/res/android"
android:fromDegrees="0"
android:toDegrees="360"
android:pivotX="50%"
android:pivotY="50%"
android:repeatCount="infinite"
android:duration="2000"
android:interpolator="#android:anim/linear_interpolator"/>
I call the animation like this:
#Override
public void onWindowFocusChanged (boolean hasFocus) {
if (hasFocus) {
tvload.startAnimation(anim);
}
}
The animation starts immediately in pre-lollipop devices but in lollipop and Marshmallow it takes around 1 sec for it to start. This animation should start after intent.
Is there a way to make this animation start immediately instead of having the 1 second load time?
I would give the View#post() method a try. It will run the code you post next UI thread cycle which is usually as soon as the View is visible.
tvload.post(new Runnable() {
#Override
public void run() {
tvload.startAnimation(anim);
}
};
I need to make such animated splash screen. Can you help me?
One way is to use Tween Animation like the following. In your case needs more than one anim file
Animation animation = AnimationUtils.loadAnimation(getApplicationContext(), R.anim.myanimation);
Say like if you have to animate white circle image then do the following
ImageView image = (ImageView)findViewById(R.id.imageView);
Animation animation1 = AnimationUtils.loadAnimation(getApplicationContext(), R.anim.move);
image.startAnimation(animation1);
Now you need to create anim file in res/anim/move.xml
<?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">
<translate
android:fromXDelta="0%p"
android:toXDelta="75%p"
android:duration="800" />
</set>
This is an example. You need to find ways to modify these basic animations for your requirement . For more refer this link
To use a gif for your splash screen.
In your build.gradle file:
compile 'pl.droidsonroids.gif:android-gif-drawable:1.1.+'
In your activities layout:
<pl.droidsonroids.gif.GifImageView
android:id="#+id/gifView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="#drawable/gif"
/>
And finally in your class file:
private static int SPLASH_TIME_OUT = 1500;
private boolean isInFront;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_splash_gif);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
// This method will be executed once the timer is over
if(isInFront)
{
// Start your app main activity
Intent i = new Intent(SplashScreen_Gif.this, MainMenuActivity.class);
startActivity(i);
}
// close this activity
finish();
}
}, SPLASH_TIME_OUT);
}
You can use a gif image like this and use it on your splash screen instead of a normal jpg or png image
recently I wrote a function.it's about a refresh button in each list item. what I want is click the button or List Item, the refresh button starts rotate. stops when the request finished.
I use animation as follows:
<?xml version="1.0" encoding="UTF-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:fillAfter="true"
android:fromDegrees="0"
android:interpolator="#android:anim/linear_interpolator"
android:pivotX="50%"
android:pivotY="50%"
android:repeatCount="infinite"
android:toDegrees="358" />
and some source code are here:
public void refresh(View v) {
Animation rotation = AnimationUtils.loadAnimation(mContext,
R.anim.rotate);
rotation.setFillAfter(true);
v.startAnimation(rotation);
}
public void completeRefresh(View v) {
v.clearAnimation();
}
when the request finished, I call notifyDataSetChanged() to refresh the LiseView.
the problem is that the button was indeed rotating. but when I click it the second time. it's rotating but a little fuzzy. just like this:
any suggestions? thanks a lot.
What is most likely happening on your second (and subsequent clicks) is that the animation is running on it again.
In your current implementation, try using setTag(...) like this:
public void refresh(View v) {
if(v.getTag() != null && (boolean)v.getTag()) {
//do nothing, since we are setting the tag to be true once pressed
} else {
//this view hasn't been clicked yet, show animation and set tag
v.setTag(true);
Animation rotation = AnimationUtils.loadAnimation(mContext, R.anim.rotate);
rotation.setFillAfter(true);
v.startAnimation(rotation);
}
}
In your Adapter, you should keep track of which list items are being animated (I'm assuming multiple items can be clicked at the same time). Once you know that the 'request' is finished, you can update the adapter with the correct items and then call notifyDataSetChanged()
I have a menu option in my ActionBarSherlock Actionbar that kicks off an AsyncTask. I'm trying to get the icon to animate while the background task is running. I have it working, except when I click on the icon, the icon itself will "jump" a couple pixels over to the right, and it's very noticeable. Not exactly sure what is causing that to happen.
This is what I have so far:
private MenuItem refreshItem;
private void DoRefresh()
{
final LayoutInflater inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
final ImageView ivRefresh = (ImageView)inflater.inflate(R.layout.refresh_view, null);
final Animation rotation = AnimationUtils.loadAnimation(activity, R.anim.refresh);
ImageView ivRefresh.startAnimation(rotation);
refreshItem.setActionView(ivRefresh);
//AsyncTask is kicked off here
}
#Override
public boolean onOptionsItemSelected(final MenuItem item)
{
if (item.getItemId() == R.id.refresh) {
refreshItem = item;
this.DoRefresh();
return true;
} else {
return super.onOptionsItemSelected(item);
}
}
refresh_view.xml
<?xml version="1.0" encoding="utf-8"?>
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:src="#drawable/refresh"
/>
refresh.xml
<rotate
xmlns:android="http://schemas.android.com/apk/res/android"
android:fromDegrees="0"
android:toDegrees="360"
android:pivotX="50%"
android:pivotY="50%"
android:repeatCount="infinite"
android:interpolator="#android:anim/linear_interpolator"
android:duration="1100"
/>
UPDATE:
Been fooling around with this, with no luck. It has nothing to do with the animation because if I disable the animation, the icon still jumps over to the right. If I comment out setActionView, the icon does not jump, so it has something to do with that. Have no clue, driving me nuts.
I don't know if this will have any effect but if you play around with the pivotvalues you might sort out this problem. Perhaps only pivoting on one axis?
Alex Fu, your article was very helpful, but there are some improvements that can be made.
Restarting the animation in onAnimationEnd each time is inefficient. Instead, set the animation repeatcount to infinite before you start it, then when the action finishes, set the repeatcount to 0. The animation will finish the current loop, and then call onAnimationEnd, where you can call setActionView(null).
I've also encountered a problem (in the emulator at least, haven't tested on a real device, as I don't have one) with both ActionBarSherlock and the native ICS ActionBar, that the last few frames of the animation overlap with the static button after calling setActionView(null). My solution was to wrap the ImageView that is being animated in a LinearLayout, and then call setVisibility(View.GONE) on the LinearLayout. If you animate a view, using setVisibility to hide it won't work, but hiding its parent will.
Here's all the relevant code:
layout/actionbar_progress.xml (note that I've added ids, though only the ImageView needs one):
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/actionbar_progress_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/actionbar_progress_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="5dp"
android:src="#drawable/ic_action_refresh"
style="#style/Widget.Sherlock.ActionButton"
/>
</LinearLayout>
anim/refresh_rotate.xml:
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromDegrees="0"
android:toDegrees="360"
android:pivotX="50%"
android:pivotY="50%"
android:duration="1000"
android:interpolator="#android:anim/linear_interpolator"
android:repeatCount="infinite">
</rotate>
repeatCount is set to infinite, but this isn't necessary, as the java code has to set it to infinite anyway.
In onCreateOptionsMenu I have
...
menuInflater.inflate(R.menu.main, menu);
mRefreshItem = menu.findItem(R.id.menu_refresh);
...
this is just to avoid doing the findItem each time the refresh button is clicked.
In onOptionsItemSelected:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
...
case R.id.menu_refresh:
refresh();
break;
...
}
}
the refresh method is just a dummy 5 second delayed post; it calls refreshAnim to start the animation, then refreshAnimEnd when it's done to stop the animation:
private void refresh() {
refreshAnim();
getWindow().getDecorView().postDelayed(
new Runnable() {
#Override
public void run() {
refreshAnimEnd();
}
}, 5000);
}
And here are the most important parts, with comments:
private void refreshAnim() {
LayoutInflater inflater = (LayoutInflater) this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
//The inflated layout and loaded animation are put into members to avoid reloading them every time.
//For convenience, the ImageView is also extracted into a member
if (mRefreshIndeterminateProgressView == null || mRefreshRotateClockwise == null) {
mRefreshIndeterminateProgressView = inflater.inflate(R.layout.actionbar_progress, null);
mRefreshRotateClockwise = AnimationUtils.loadAnimation(this, R.anim.refresh_rotate);
mRefreshImage = mRefreshIndeterminateProgressView.findViewById(R.id.actionbar_progress_image);
}
//reset some stuff - make the animation infinite again,
//and make the containing view visible
mRefreshRotateClockwise.setRepeatCount(Animation.INFINITE);
mRefreshIndeterminateProgressView.setVisibility(View.VISIBLE);
mRefreshRotateClockwise.setAnimationListener(new AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {}
#Override
public void onAnimationRepeat(Animation animation) {}
#Override
public void onAnimationEnd(Animation animation) {
//This is important to avoid the overlapping problem.
//First hide the animated icon
//setActionView(null) does NOT hide it!
//as long as the animation is running, it will be visible
//hiding an animated view also doesn't work
//as long as the animation is running
//but hiding the parent does.
mRefreshIndeterminateProgressView.setVisibility(View.GONE);
//make the static button appear again
mRefreshItem.setActionView(null);
}
});
mRefreshItem.setActionView(mRefreshIndeterminateProgressView);
//everything is set up, start animating.
mRefreshImage.startAnimation(mRefreshRotateClockwise);
}
private void refreshAnimEnd() {
//sanity
if ( mRefreshImage == null || mRefreshItem == null ) {
return;
}
Animation anim = mRefreshImage.getAnimation();
//more sanity
if (anim != null) {
//let the animation finish nicely
anim.setRepeatCount(0);
} else {
//onAnimationEnd won't run in this case, so restore the static button
mRefreshItem.setActionView(null);
}
}
Just add this to your img_layout.xml if you are using the normal ActionBar:
style="?android:attr/actionButtonStyle"
Or this with the SherLock ActionBar:
style="#style/Widget.Sherlock.ActionButton"
If the menu option is an action item, you should apply the style Widget.Sherlock.ActionButton to the ImageView to keep consistency. Read this article I wrote on how to animate action items properly. http://alexfu.tumblr.com/post/19414506327/android-dev-animate-action-items
Okay so I don't understand how I'm supposed to do this.
All I want it to do is have an image fade on top of my game.
This method is in my MainGame class which extends SurfaceView and implements SurfaceHolder.Callback
Here is my fadein.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:interpolator="#android:anim/accelerate_interpolator"
android:duration="3000"
android:repeatCount="infinite"/>
</set>
I've tried:
public void Animation() {
ImageView myImageView= (ImageView)findViewById(R.id.block1);
Animation myFadeInAnimation = AnimationUtils.loadAnimation(this.getApplicationContext(), R.anim.fadein);
myImageView.startAnimation(myFadeInAnimation);
}
The method loadAnimation(Context, int) in the type AnimationUtils is not applicable for the arguments (MainGame, int)
as well as
public void Animation() {
ImageView myImageView= (ImageView)findViewById(R.id.myImageView);
Animation myFadeInAnimation = AnimationUtils.loadAnimation(this, R.anim.fadein);
myImageView.startAnimation(myFadeInAnimation);
}
The method getApplicationContext() is undefined for the type MainGame
I've also tried putting the Animation method in it's own class called fade that extends Activity and creating an animation object called Fade in my MainGame class and calling it in a method by
Fade.Animation();
Which I can compile and run but it crashes as soon as the method containing that runs.
Perhaps someone could provide me with a basic example or a tutorial? Any help would be great, thanks.
Instead of using getApplicationContext(), use the Context object from your Activity. This is probably handed to your SurfaceView in its constructor. You can save a reference to this in the View's constructor and use it when the View needs a context.