ImageView rotates only once using AccelerateDecelerateInterpolator - android

I am trying to rotate an image by 360 degree using AccelerateDecelerateInterpolator. I have included the code to rotate the image in an onclickfunction of a button. When i press the button for the first time, the image rotates. However, when i press it the next time, nothing happens.
public void displaySpinResult_Spinner(View view) {
arrow.animate().rotation(360).setInterpolator(new AccelerateDecelerateInterpolator()).start();
}

This is probably because the rotation value is retained. When you specify rotation(360) for the second time, the View is already rotated by 360degrees, so nothing happens.
You can either try rotation(arrow.getRotation() + 360), or use the rotationBy() method instead.

I think this is the solution:
public void displaySpinResult_Spinner(View view) {
arrow.animate().rotation(360).setInterpolator(new AccelerateDecelerateInterpolator()).start();
arrow.animate().rotation(360).setInterpolator(new AccelerateDecelerateInterpolator()).reset();
}

Related

Android - TransitionDrawable starting in 'end' state flickers when initially drawn

I have a RecyclerView holding a list of Artists. An artist can be marked as a favorite or not a favorite.
There's a heart to represent this state, and I have a transition drawable, where I'm going from a outlined heart, to a filled in heart based on if the artist in question has been marked as a favorite. The animation itself is working correctly and smoothly transitions between the two when the user clicks on the heart, and looks beautiful.
TransitionDrawable td = new TransitionDrawable(new Drawable[]{
ContextCompat.getDrawable(getActivity(), R.drawable.favorite_border),
ContextCompat.getDrawable(getActivity(), R.drawable.favorite)});
artistViewHolder.image.setImageDrawable(td);
if (artist.isFavorite()) {
td.startTransition(0);
}
In the onClick for the item, I call either .reverseTransition(300) or .startTransition(300) depending on the next state.
I'm running into problems anytime the view is created (1st screen load) and I need to start in the 2nd position (favorite). The initial load you can see it flicker from the empty heart to the filled heart, even though my animation time is set to 0 when it's created. This also happens anytime the list gets invalidated such as if it gets filtered into a smaller set of artists.
I guess since it needs to do things and isn't actually just setting the drawable, 0 isn't actually "instant". I can't find any other way to start in the "end" position though, other than to reverse the starting position of the images in the transition drawable itself.
If I do that though, start/reverse are going to behave differently on a heart by heart basis. At best, I would need to extend the transition drawable, and override the start/reverse/reset methods to take into account which initial state it's in, and that seems kind of hacky?
Am I missing something obvious to start in the end position but not cause that flicker?
Thanks!
You don't migtht remove flicker on td.startTransition(0);
So, you need change order in your Drawables array.
For example
Drawable favorite_border = ContextCompat.getDrawable(getActivity(), R.drawable.favorite_border);
Drawable favorite = ContextCompat.getDrawable(getActivity(), R.drawable.favorite);
TransitionDrawable td = new TransitionDrawable(isFavorite
? new Drawable[]{favorite, favorite_border}
: new Drawable[]{favorite_border, favorite});
artistViewHolder.image.setImageDrawable(td);
This will work provided that you do this in onBindViewHolder
Unless there's a better way to do this, I've gone ahead and extended it, and flipped the start/reverse call based off the initial state.
public class MyTransitionDrawable extends TransitionDrawable{
private boolean initialFavorite = false;
public MyTransitionDrawable(Drawable[] layers) {
super(layers);
}
public MyTransitionDrawable(Drawable[] layers, boolean initialFavorite) {
super(layers);
this.initialFavorite = initialFavorite;
}
public boolean isInitialFavorite() {
return initialFavorite;
}
#Override
public void startTransition(int durationMillis) {
if(!initialFavorite){
super.startTransition(durationMillis);
}else{
super.reverseTransition(durationMillis);
}
}
#Override
public void reverseTransition(int durationMillis) {
if(!initialFavorite){
super.reverseTransition(durationMillis);
}else{
super.startTransition(durationMillis);
}
}
}
`

Animating imageview broken if it's started again before one cycle finishes

I've got an ImageView that I rotate with animation by 180 degrees with OnClickListener. If it's triggered very fast (before one animation finishes) the animation bugs out and leaves the View at weird angle (for example rotated 47 degrees versus basic state).
How to prevent next animation before current one finishes or how to deal with it in another way?
bankExpandArrow.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (totalText.getVisibility() == View.GONE) {
totalText.setVisibility(View.VISIBLE);;
bankExpandArrow.animate().rotationBy(180f).start();
}
else {
totalText.setVisibility(View.GONE);
bankExpandArrow.animate().rotationBy(180f).start();
}
}
});
try using rotation instead of rotationBy

How to rotate buttons when orientation changes without rotating the layout?

I want to make an ImageButton rotate when the device orientation changes. It should rotate for 90, 180, 270 and 360 angles and its relative layout should remain steady so only the buttons move. How can this be done? I've done some research but found nothing that could help me.
You can detect an orientation change by Overriding onConfigurationChanged() like this:
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
//call your rotate method here
}
Then once you detect the orientation change event, you can perform an animated rotation on a Button like this:
public void rotateView(View view) {
Button button = (Button) view.findViewById(R.id.some_button);
RotateAnimation rotateAnimation = new RotateAnimation(0, 360);
rotateAnimation.setDuration(2000);
button.startAnimation(rotateAnimation);
}
You can set the starting and ending angle in the constructor of RotateAnimation, then set the duration for how long the animation should take (in milliseconds). Then you simply call startAnimation() on the view you want to animate.

How to stop imagebutton at current position when clicked during animation?

I have an ImageButton which moves down from the top of the screen. The image animates while moving down to the screen. I want to make it stop WHEREVER and WHENEVER it is clicked on. Basically if the image is clicked in the middle of the animation, I want to it to stop at that current position. My progress can be seen in the code block below, the code makes the image animate and move from top to bottom, when the image is clicked, the image moves straight to the desired position (500), instead of stopping at the current position. Please be really descriptive as I am a beginner in programming. Thank you.
final ImageButton image = (ImageButton)findViewById(R.id.image);
final ObjectAnimator objectAnimator= ObjectAnimator.ofFloat(image, View.TRANSLATION_Y, 0, 500); //where the image should move to
objectAnimator.setStartDelay(2000); //how long to wait before starting
objectAnimator.setDuration(2000); //how long animation lasts
objectAnimator.start();
image.setOnClickListener(
new ImageButton.OnClickListener() {
public void onClick(View v) {
image.setTranslationY(image.getY()); //gets current position of Y?
objectAnimator.end(); //ends the animation
}
}
);
From the documentation of ValueAnimator#cancel it seems that
objectAnimator.cancel();
should solve your problem.

Autoadvancing gallery animation

I have a Gallery widget set up to auto advance every 10000ms. However the transition between views is instantaneous and I would prefer to have a transition.
My advancing method is like so:
private void tickerAdvance() {
int selectedItemPosition = mTickerGallery.getSelectedItemPosition();
if (selectedItemPosition + 1 == mTickerGallery.getCount()) {
mTickerGallery.setSelection(0, true);
} else {
mTickerGallery.setSelection(selectedItemPosition + 1, true);
}
}
I was under the impression that setting the animation to true would cause it to animate between states. In my XML I've also added animationDuration="500", however the transition still pops between states instantly.
The problem is because you have used the setSelection() which obviously won't give you the feel of an Gallery being scrolled. SO instead of using setSelection() you have to override the onScroll() of gallery.
Here is how you do it.
Assuming that you have made the necessary steps for auto advancing periodically, now do this code.
MotionEvent e1, e2;
gallery.onScroll(e1, e2, scroll_limit , 0); //scroll limit is your integer variable for scroll limit.
The answer I came up with is that the Gallery API is terribly non-extensible. There are multiple package private or private methods that would unlock this functionality without a kludge including moveNext, FlingRunnable.startwithdistance, and scrollToChild. Alas, they are all unavailable.
Instead the best answer I was able to come up with was to override setSelection to get all the behaviors I needed. In the setSelection method I reverse the deceleration algorithm to calculate a velocity for a calculated distance and then call onFling. This is a nasty kludge could be made a ton better by making any of the above methods protected or public (I can't fathom a reason why at least moveNext and scrollToChild shouldn't be).
i had a similar task to make item to item animation and i decided to choose gallery, so i tried a lot of things, but the best way is to subclass gallery and add this:
boolean avoidSound = false;
public void showNext() {
avoidSound = true;
this.onKeyDown(KeyEvent.KEYCODE_DPAD_RIGHT, null);
}
public void playSoundEffect(int soundConstant) {
if (avoidSound) {
avoidSound = false;
} else {
super.playSoundEffect(soundConstant);
}
}
just call showNext() and it will do an animation

Categories

Resources