So I have implemenented a fragment of code which works perfectly found on another thread
The code is listed below :
private void animate(final ImageView imageView, final int images[], final int imageIndex, final boolean forever){
//imageView <-- The View which displays the images
//images[] <-- Holds R references to the images to display
//imageIndex <-- index of the first image to show in images[]
//forever <-- If equals true then after the last image it starts all over again with the first image resulting in an infinite loop. You have been warned.
int fadeInDuration = 500; // Configure time values here
int timeBetween = 3000;
int fadeOutDuration = 1000;
imageView.setVisibility(View.INVISIBLE); //Visible of invisible by default
imageView.setImageResource(images[imageIndex]);
Animation fadeIn = new AlphaAnimation(0, 1);
fadeIn.setInterpolator(new DecelerateInterpolator()); //Add this
fadeIn.setDuration(fadeInDuration);
Animation fadeOut = new AlphaAnimation(1, 0);
fadeOut.setInterpolator(new AccelerateInterpolator()); //and this
fadeOut.setStartOffset(fadeInDuration + timeBetween);
fadeOut.setDuration(fadeOutDuration);
AnimationSet animation = new AnimationSet(false); //change to false
animation.addAnimation(fadeIn);
animation.addAnimation(fadeOut);
animation.setRepeatCount(1);
imageView.setAnimation(animation);
animation.setAnimationListener(new AnimationListener() {
#Override
public void onAnimationEnd(Animation animation) {
if(images.length -1 > imageIndex){
animate(imageView, images, imageIndex + 1, forever); // Calls itself until it gets to the end of the array.
}
else{
if(forever == true){
animate(imageView, images, 0, forever); //Calls itself to start the animation all over again in a loop if forever = true
}
}
}
#Override
public void onAnimationRepeat(Animation animation) {
// TODO Auto-generated method stub
}
#Override
public void onAnimationStart(Animation animation) {
// TODO Auto-generated method stub
}
});
}
Basically this code accepts an Array of images and creates a slideshow with fadeIn and FadeOut effects. Once it reaches the end the animation stops. How can I modify the code to keep animating forever?
Found the solution Guys.
Just had to make a slight alteration! On the else statement I had to set Forever to false!
else{
if(forever == false){
animate(imageView, images, 0, forever);
}
}
Related
I have an app with a RecyclerView and in each item I implemented Swipe to star/dismiss behavior using onTouch(). There's no problem with my implementation and I can handle right and left swipe and claim drag from RecyclerView.
Each item is RevealFrameLayout that consists of content on the top, and below there is the original layout and the layout to be revealed, just like this:
Top layout:
Below layout (top revealed layer):
Below layout (default layout before reveal):
There I reveal the top revealed layers (colored ones) and everything works, until I added another ObjectAnimator to hide the star layout (make starred/unstarred), when The reveal works for the first time, and then another swipe will execute the hide animator, then 3rd time, where it's supposed to reveal once again, it really starts the animation (by debugging start() is executed) but it doesn't show up. 4th time the hiding animator works but no revealed layout.
The method to trigger any action:
void triggerAction(SwipeAction swipeAction, final Note note, final int position) {
if (swipeAction.getActionId() == SwipeAction.STAR) {
if (note.isStarred() && !hidden && !hideAnimating && !justAnimated) {
starActionLayout.setVisibility(View.VISIBLE);
archiveActionLayout.setVisibility(View.GONE);
Animator hideAnim = AnimationUtils.createHideAnimation(revealStar);
hideAnim.addListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationEnd(Animator animation) {
revealStar.setVisibility(View.INVISIBLE);
hideAnimating = false;
hidden = true;
note.setStarred(false);
MainActivity.notesController.set(position, note);
super.onAnimationEnd(animation);
}
});
hideAnim.start();
revealStar.setVisibility(View.VISIBLE); // DEBUG: Only to make sure the star layout is shown.
justAnimated = true;
hideAnimating = true;
revealAnimating = false;
revealed = false;
hidden = false;
} else if (!note.isStarred() && !revealAnimating && !revealed && !justAnimated) {
starActionLayout.setVisibility(View.VISIBLE);
archiveActionLayout.setVisibility(View.GONE);
final ObjectAnimator revealAnim = (ObjectAnimator) AnimationUtils.createCircularReveal(revealStar, (int) getCenterX(starActionImage), (int) getCenterY(starActionImage), 0, (float) getRadius(starActionLayout));
revealAnim.addListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationEnd(Animator animation) {
revealAnimating = false;
revealed = true;
note.setStarred(true);
MainActivity.notesController.set(position, note);
super.onAnimationEnd(animation);
}
});
revealAnim.start();
justAnimated = true;
revealAnimating = true;
hideAnimating = false;
hidden = false;
revealed = false;
revealStar.setVisibility(View.VISIBLE);
}
} else if (swipeAction.getActionId() == SwipeAction.ARCHIVE) {
if (!revealAnimating && !revealed) {
int added = starActionLayout.getWidth();
starActionLayout.setVisibility(View.GONE);
archiveActionLayout.setVisibility(View.VISIBLE);
Animator revealAnim = AnimationUtils.createCircularReveal(revealArchive, (int) getCenterX(archiveActionImage) + added, (int) getCenterY(archiveActionImage), 0, (float) getRadius(archiveActionLayout));
revealAnim.addListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationEnd(Animator animation) {
revealAnimating = false;
revealed = true;
super.onAnimationEnd(animation);
}
});
revealAnim.start();
revealAnimating = true;
revealArchive.setVisibility(View.VISIBLE);
}
}
}
There's no problem with my conditions as debugging shows that the reveal animator show code is executed when it should. And AnimationUtils is a custom class that wraps ViewAnimationUtils.createCircularReveal(params) and another custom ObjectAnimator createHideAnimator() and there's no problem with that too.
AnimationUtils.java:
package com.skaldebane.util.graphics;
import android.animation.Animator;
import android.animation.ObjectAnimator;
import android.os.Build;
import android.view.View;
import android.view.ViewAnimationUtils;
import android.view.animation.LinearInterpolator;
public class AnimationUtils {
public static Animator createCircularReveal(View view, int centerX, int centerY, float startRadius, float endRadius) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) return ViewAnimationUtils.createCircularReveal(view, centerX, centerY, startRadius, endRadius);
else return io.codetail.animation.ViewAnimationUtils.createCircularReveal(view, centerX, centerY, startRadius, endRadius);
}
public static Animator createHideAnimation(View view) {
ObjectAnimator hideAnim = new ObjectAnimator();
hideAnim.setPropertyName("alpha");
hideAnim.setFloatValues(1.0F, 0.0F);
hideAnim.setDuration(300);
hideAnim.setInterpolator(new LinearInterpolator());
hideAnim.setTarget(view);
return hideAnim;
}
}
Note: Don't tell me to use ItemTouchHelper instead as that is not the subject of my question and it doesn't solve the problem either.
I just figured out the problem. It was simple but hard to notice. When I was applying the hide animator it was setting alpha permanently to 0, which meant the view would never appear again. I only had to use view.setAlpha(1.0F); directly after calling view.setVisiblity(View.INVISIBLE);.
I have an requirement to show the text on Recyclerview with FadeIn & FadeOut animation.
Below is the dynamic list where it's need to loop infinite items i.e; 1-2-3-1-2-3-1-2-3
List<String> mImageDesc = new List<String>();
mImageDesc.add("1");
mImageDesc.add("2");
mImageDesc.add("3");
I have used below code but which is not working for me.
final Animation animationFadeIn = AnimationUtils.loadAnimation(mContext, R.anim.fade_in_animation);
final Animation animationFadeOut = AnimationUtils.loadAnimation(mContext, R.anim.fade_out_animation);
Animation.AnimationListener animListener = new Animation.AnimationListener(){
// Required to change the image
int i = 0;
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationRepeat(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
if (animation == animationFadeIn) {
// Start fade-out animation
mTxtImageDescription.startAnimation(animationFadeOut);
} else if (animation == animationFadeOut) {
*while(mImageDesc.listIterator().hasNext()) {
System.out.println(mImageDesc.listIterator().next());
mTxtImageDescription.setText(mImageDesc.listIterator().next());
mTxtImageDescription.startAnimation(animationFadeIn);*
}
}
}
};
// Set listener to animation
animationFadeIn.setAnimationListener(animListener);
animationFadeOut.setAnimationListener(animListener);
// Start fade-in animation
mTxtImageDescription.setText(mImageDesc.get(0));
mTxtImageDescription.startAnimation(animationFadeIn);
In the last line off your while loop you have RE-started the 'animationFadeIn' ,so
the 'animListener' callbacks will be called forever .Notice if while loop was that repeating you would have 'StackOverflowError'.
I'm developing a puzzle game. The essence of the issue is this. I has buttons (ImageButton) in the ArrayList mButtons collection and each button has listener, I prescribe an animation of the button for the listener. When I click on the button, the animation works well, BUT !!! if I go back to that button, I can't move it and not press it! As though on top of it the textures were superimposed! Other buttons are pressed. I checked different ways:
v.getAnimation().reset();
v.getAnimation().cancel();
v.clearAnimation();
v.setAnimation(null);
v.getAnimation().setAnimationListener(null);
did not help! If there are any tips and you have encountered the same issue, please reply!
Picture for understanding:
The code to make it clearer:
public class TouchButtonAction implements View.OnClickListener {
private GameController mController;
private List<ImageButton> mButtons;
private List<GridLayout.LayoutParams> mParams;
private final Animation myAnimA;
private volatile boolean isAnimAFinish = true;
public TouchButtonAction(Context context, GameController controller,
List<ImageButton> buttons, List<GridLayout.LayoutParams> params) {
this.mParams = params;
this.mButtons = buttons;
this.mController = controller;
this.myAnimA = AnimationUtils.loadAnimation(context, R.anim.bounce_swap);
final ButtonBounceInterpolator mInterpolatorA = new ButtonBounceInterpolator(0.07, 20);
this.myAnimA.setInterpolator(mInterpolatorA);
// this.myAnimA.setAnimationListener(new Animation.AnimationListener() {
// #Override
// public void onAnimationStart(Animation animation) {
// isAnimAFinish = false;
//// animation.setFillAfter(false);
//// animation.reset();
//
// }
//
// #Override
// public void onAnimationEnd(Animation animation) {
//// animation.reset();
// animation.cancel();
// isAnimAFinish = true;
//// synchronized (this){
//
//// }
// }
//
// #Override
// public void onAnimationRepeat(Animation animation) {
//
// }
// });
#Override
public void onClick(final View v) {
int a = mButtons.indexOf((ImageButton) v);
int b = 0;
for (ImageButton button : mButtons) {
if (!button.isEnabled()) {
b = mButtons.indexOf(button);
}
}
if (here check logic) {
SoundPlay.playSoundPool(SoundPlay.TOUCH);
if (isAnimAFinish){
// v.post(new Runnable() {
// #Override
// public void run() {
// synchronized (this){
v.startAnimation(myAnimA);
isAnimAFinish = false;
// }
//
// }
// });
}
if (v.getAnimation() != null){
if (v.getAnimation().hasEnded()){
Log.d("LOGGG", "hasEnded Anim");
v.getAnimation().reset();
v.getAnimation().cancel();
v.clearAnimation();
v.setAnimation(null);
v.getAnimation().setAnimationListener(null);
isAnimAFinish = true;
}
}
Collections.swap(mButtons, a, b);
mController.getGridLayout().removeAllViewsInLayout();
mController.getGridLayout().removeAllViews();
for (int i = 0; i < mButtons.size(); i++) { // i < 12
ImageButton button = mButtons.get(i);
mController.getGridLayout().addView(button, mParams.get(i));
}
mController.getGridLayout().invalidate();
} else {
SoundPlay.playSoundPool(SoundPlay.TOUCH_BANG);
}
mController.checkSolution(mButtons);
}
If you want to hide the button after click, then you can use button.setVisibility(View.GONE) or if you want, that after click user can't to click that button anymore, you can use after click button.setClickable(false). I think I helped you. If you have questions, ask me.
How to remove excess texture? Maybe you can keep two images, one with texture, and another without. Upon clicking first one with texture, hide it and show second one.
It turns out that it was not necessary to use AnimationUtils.loadAnimation (), but quite other classes that allow manipulating objects, such as widgets.
Example animation bouncing button:
AnimatorSet as = new AnimatorSet ();
float y = view.getTranslationY (), distance = 20F;
as.playSequentially (
ObjectAnimator.ofFloat (view, "translationY", y-distance), // animation 1
ObjectAnimator.ofFloat (view, "translationY", y), // animation 2
ObjectAnimator.ofFloat (view, "translationY", y - (distance / 2)), // animation 3
ObjectAnimator.ofFloat (view, "translationY", y)); // animation 4
as.setDuration (600);
as.start ();
And the animation of your widget starts to jump. I hope this helped you as much as me.
while (cursor.moveToNext()) {
words.setText(cursor.getString(1) + " : " + cursor.getString(2));
image.setLayoutParams(new ViewGroup.LayoutParams(words.getMeasuredHeight(),words.getMeasuredHeight()));
ll.addView(words);
ll.addView(image);
wm.addView(ll, parameters);
final ValueAnimator animator = ValueAnimator.ofFloat(0.0f, 1.0f);
animator.setRepeatCount(0); // Times of repeat
animator.setInterpolator(new LinearInterpolator());
animator.setDuration(4000); //Fast and Furious
// animator.setStartDelay(5000);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator animation) {
final float progress = (float) animation.getAnimatedValue();
final float width = words.getWidth();
final float translationX = width * progress;
words.setTranslationX(translationX);
words.setTranslationX(width - translationX); //Right to Left
}
});
animator.start();
animator.addListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationEnd(Animator animation) {
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
ll.removeView(words);
ll.removeView(image);
wm.removeView(ll);
}
}, 3000);
}
});
}
This is my code. I have am issue in threads (i think so). As you see. cursor gets all data in my database. After that, it get each one through while loop.
When loop started, animator.start() run in 7s. But while loop finished earlier. So in next loop, it can't addView() because it doesn't remove removeView. It look like this picture: processing.So, the while loop need finished threads before running new loop.
I'm a newer in Java and i dont understand about threads much. Please help me. Thank you.
I am trying to get the coordinates of the image on the screen. I currently have an ImageView within an activity. I understand that the getLocationOnScreen() method can only be called once the layout has been created, so calling this method within the oncreate function would return [0,0]. But I do not know how to get this method to return the correct values. I have tried overiding various superclass methods, like the onstart method or the onTouchEvent method and it still returns [0,0] to me. The code I currently have is as follows:
#Override
public void onCreate(Bundle savedInstanceState)
{
// Some code here after which ..
image = (ImageView) findViewById(R.id.imageVfi);
image.setImageBitmap(imageData.entrySet().iterator().next().getValue());
}
Then I have the onStart method which I have overriden
#Override
public void onStart()
{
super.onStart();
image.setOnTouchListener(new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
int[] dim = new int[2];
image.getLocationOnScreen(dim);
new AlertDialog.Builder(DisplayPicture.this)
.setIcon(R.drawable.icon)
.setTitle("Touch coordinates : " +
String.valueOf(dim[0]) + "x" + String.valueOf(dim[1]))
.setPositiveButton("OK",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which)
{
// TODO Auto-generated method stub
}
}).show();
// image calculations go here
return true;
}
});
}
This returns 0X0 to me. Any help is much appreciated.
ImageView does not offer a way to get the location of its image on screen. You can only query the location of the ImageView itself. You can try to use ImageView.getImageMatrix() but I'm not sure we populate it when the image is simply centered (as opposed to scaled, etc.)
Solution after following advice given above
Solution:
Following the advice provided by Romain Guy below, I was able to get the co-ordinates but adding the following code to the onStart overidden method.
display = ((WindowManager) getSystemService(WINDOW_SERVICE)).getDefaultDisplay();
int orientation = display.getOrientation();
float rowStart=0, rowEnd=0, columnStart=0, columnEnd=0;
if(orientation ==0)
{
final Matrix matrix = image.getImageMatrix();
float[] values = new float[9];
matrix.getValues(values);
rowStart = values[0];
columnStart = values[5];
rowEnd = image.getWidth()-rowStart;
columnEnd = image.getHeight()-columnStart;
}else if(orientation == 1)
{
final Matrix matrix = image.getImageMatrix();
float[] values = new float[9];
matrix.getValues(values);
rowStart = values[2];
columnStart = values[3];
rowEnd = image.getWidth()-rowStart;
columnEnd = image.getHeight()-columnStart;
}
If it's only the image view that you have in your activity, then it will be positioned by default in the top left corner with coordinates 0x0.