Stop AnimatedVectorDrawable animation after playing - android

I have an AnimatedVectorDrawable that animates from play to pause state when clicked.
...
animatedVectorDrawable.registerAnimationCallback(new Animatable2.AnimationCallback() {
#Override
public void onAnimationEnd(Drawable drawable) {
//Reset the image back to its original state
//What I've tried so far
/* img.setImageResource(R.drawable.original_state)
animatedVectorDrawable.stop()
animatedVectorDrawable.reset() */
}
});
animatedVectorDrawable.start();
However, I've not been able to successfully get it back to its original state so that I can play it back again. How can I solve this?

You could do like this:
final Handler mainHandler = new Handler(Looper.getMainLooper());
animatedVector.registerAnimationCallback(new Animatable2.AnimationCallback() {
#Override
public void onAnimationEnd(final Drawable drawable) {
mainHandler.post(new Runnable() {
#Override
public void run() {
animatedVectorDrawable.start();
}
});
}
});
animatedVectorDrawable.start();

To get the initial state of the drawable use animatedVectorDrawable.seekTo(0) and the you can call animatedVectorDrawable.stop()

Related

Weird problem with button clicking in a layout that has a RecyclerView

I have run into a very strange problem. There is a layout I have with a RecyclerView and a button that switches on animation. The point is if I click the button right after the app executes - say 10 seconds, everything is fine. But if I leave the app running idle for some seconds, without touching anything, then when I click the button again, the animation simply doesn't start at all. And yet if after that I slide RecyclerView about the screen with my finger (in any place!) then the animation triggers all of a sudden. As if it was somehow frozen and "woke up" only after I interacted with the RecyclerView. As if RecyclerView after some seconds puts its animation-related objects to sleep somehow and they "wake-up" only after the RecyclerView is slided?.. Apparently the listener "goes to bed"... Is there a way to keep the animation-related objects "awake" at all times?
Here is the Animation function:
private void recyclerViewAnimate(final RecyclerView recyclerView, LayoutAnimationController controller) {
if(isAnimating){
return;
}
controller = AnimationUtils.loadLayoutAnimation(recyclerView.getContext(), R.anim.layout_recycleview_disappear);
recyclerView.setLayoutAnimation(controller);
recyclerView.setLayoutAnimationListener(new Animation.AnimationListener() {
public void onAnimationStart(Animation animation) {
isAnimating = true;
bt_add.animate().rotationXBy(180).setDuration(400).start();
addButtonLayout.animate().setDuration(400).alpha(0).withEndAction(new Runnable() {
#Override
public void run() {
addButtonLayout.setVisibility(View.INVISIBLE);
}
});
}
public void onAnimationRepeat(Animation animation) {}
public void onAnimationEnd(Animation animation) {
recyclerView.setVisibility(View.GONE);
layoutSettings.setVisibility(View.VISIBLE);
layoutSettings.animate().scaleX(0.95f).setDuration(0).withEndAction(new Runnable() {
#Override
public void run() {
layoutSettings.animate().alpha(1)
.scaleY(1.01f).scaleX(1f).setDuration(400).withEndAction(new Runnable() {
#Override
public void run() {
settingsText.animate().setDuration(300).alpha(1).start();
isAnimating = false;
recyclerView.setLayoutAnimationListener(null);
}
}).start();
}
}).start();
}
});
recyclerView.scheduleLayoutAnimation();
}
Instead of setting scheduleLayoutAnimation(); I needed to use startLayoutAnimation();

How to run code in each time in android

I want show animation in my application, and i want show this animation each 3000m/s.
I write below code, but in this code show just once.
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
YoYo.with(Techniques.Bounce)
.duration(1500)
.playOn(arrowHelpImage);
}
}, 3000);
How can i edit my code and show each 3000m/s ?
U could use something like this. change the animations used below. this animations will run infinite. provide animation on end Listner. Change animation duration to 3000ms and use this in handler.it will work
YoYo.with(Techniques.Bounce)
.duration(1200)
.interpolate(new AccelerateDecelerateInterpolator())
.withListener(new Animator.AnimatorListener() {
#Override
public void onAnimationStart(Animator animation) {}
#Override
public void onAnimationEnd(Animator animation) {
YoYo.with(Techniques.Bounce)
.duration(1200)
.interpolate(new AccelerateDecelerateInterpolator())
.withListener(this).playOn(arrowHelpImage);
}
#Override
public void onAnimationCancel(Animator animation) {}
#Override
public void onAnimationRepeat(Animator animation) {}
}).playOn(arrowHelpImage);
Put below code in your class.
private Handler handler;
private Runnable runnable;
below code in you oncreate
handler = new Handler();
runnable = new Runnable() {
#Override
public void run() {
YoYo.with(Techniques.Bounce)
.duration(1500)
.playOn(arrowHelpImage);
handler.postDelayed(runnable, Constants.SPLASH_DURATION);
}
};
handler.postDelayed(runnable, Constants.SPLASH_DURATION);
#Override
protected void onDestroy() {
super.onDestroy();
//Close the handler and the process of splash screen.
if (handler != null && runnable != null) {
handler.removeCallbacks(runnable);
}
}

FragmentTransaction animation: onAnimationEnd is called before it really ended

My question is very similar to this question, except that I need it to work with fragments instead of Views.
As explained in that thread, there seems to be a bug(?) in Android when an AnimationListener is attached to an Animation, which results in the onAnimationEnd() callback getting called before the animation has really completely ended.
I'm using fullscreen fragments which are animated in the FragmentTransaction (v4 support library) to have a horizontal "roll-in" effect. This works smoothly everywhere except in the fragment where I start a camera preview. Therefore I want to only start the camera preview once the animation is finished.
I tried using this method in my Fragment:
#Override
public Animation onCreateAnimation(final int transit,final boolean enter,final int nextAnim)
{
Animation anim=super.onCreateAnimation(transit, enter, nextAnim);
if (anim==null && nextAnim!=0)
anim=AnimationUtils.loadAnimation(getActivity(), nextAnim);
if(anim!=null)
{
anim.setAnimationListener(new AnimationListener() {
#Override
public void onAnimationStart(Animation animation)
{
}
#Override
public void onAnimationRepeat(Animation animation)
{
}
#Override
public void onAnimationEnd(Animation animation)
{
scannerView.startCameraInHandlerThread();
}
});
}
Unfortunately starting the camera is quite an expensive operation and so my animation lags every time right before the animation is over. It looks ugly and my client is complaining about it.
I also thought about a cheap solution like waiting/sleeping on the camera thread, but the main thread actually needs to wait for the camera starting thread for synchronization otherwise it can deadlock in some cases, so sleeping actually makes the issue worse (the lag becomes longer).
Does anyone know how to solve this?
edit: someone asked for more code...
public void startCameraInHandlerThread()
{
if (mThread == null)
mThread = new CameraHandlerThread();
synchronized (mThread) {
mThread.openCamera();
}
}
private class CameraHandlerThread extends HandlerThread
{
Handler mHandler = null;
CameraHandlerThread()
{
super("CameraHandlerThread");
start();
mHandler = new Handler(getLooper());
}
synchronized void notifyCameraActionCompleted() {
notify();
}
void openCamera()
{
mHandler.post(new Runnable() {
#Override
public void run() {
startCamera();
notifyCameraActionCompleted();
}
});
try
{
wait();
}
catch (InterruptedException e)
{
Thread.currentThread().interrupt();
LOG.warn("Waiting for camera opening was interrupted");
}
}
}
I was able to come up with a workaround: Just delay the start of my method for a very short time to give the animation time to run to completion. On the devices that my client is going to use this works fine but I don't feel that it's a general enough solution, therefore I'm not going to mark this as the accepted answer.
#Override
public void onAnimationEnd(Animation animation)
{
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
scannerView.startCameraInHandlerThread();
}
}, 10); // will start after 10ms
}

SlindingMenu slowing toggle

I want to display for few seconds part of the sliding menu, Here is how I'm doin it:
#Override
public void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
showMenu();
}
}, 500);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
showContent();
}
}, 600);
}
However, the menu is displaying and disapeared quickly, is there a way to slow down the toggle so that the user can see part of the menu while it's appearing and disapearing slowly?
I made mViewAbove public in SlidingMenu.java, then used scrollBy(int, int):
#Override
public void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
final View viewAbove = getSlidingMenu().mViewAbove;
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
viewAbove.scrollBy(-60, 0);
}
}, 500);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
viewAbove.scrollBy(60, 0);
}
}, 2000);
}
Is there a way to slow down the toggle so that the user can see part of the menu while it's > appearing and disapearing slowly?
You would have to change the animation-changing-rate of the Interpolator of the Scroller here, if you want it to scroll slower. Maybe create a setter for the Interpolator, if you want it to scroll slow only temporary (I assume you only want to show to the user, that there is a SlidingMenu inside your app, right?), after that you could reset the rate of the Interpolator to the default.

Automatically scroll in PageViewer

I have a problem with pageviewer. I want to my page scroll every two seconds. I try something like this:
handler.postDelayed(new Runnable() {
public void run() {
viewPager.setCurrentItem(viewPager.getCurrentItem()+1, true);
}
},2000);
But it works only when I start activity. If i put this code to public void onPageSelected(int page) it works but I want to do when I click and manually scroll page I want to stop this handler but it doeasn't work. How I can do that?
You should define your Runnable and Handler like this:
private boolean pagerMoved = false;
private static final long ANIM_VIEWPAGER_DELAY = 2000;
private Handler h = new Handler();
private Runnable animateViewPager = new Runnable() {
public void run() {
if (!pagerMoved) {
viewPager.setCurrentItem(viewPager.getCurrentItem()+1, true);
h.postDelayed(animationFrame, ANIM_VIEWPAGER_DELAY);
}
}
};
Make sure that you setup and tear down in your onPause & onResume methods
#Override
public void onPause() {
super.onPause();
if (h != null) {
h.removeCallbacks(animateViewPager);
}
}
#Override
public void onResume() {
super.onResume();
h.postDelayed(animateViewPager, ANIM_VIEWPAGER_DELAY);
}
Finally, you'll need to listen for a touch event on your viewpager so that you can set pagerMoved to true (which will then stop further automatic page transitions).

Categories

Resources