I am using this part of code to create the animation:
private void animate(final ImageView imageView, final Drawable[] 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 = 1000; // Configure time values here
int timeBetween = 300;
int fadeOutDuration = 1000;
imageView.setVisibility(View.VISIBLE); //Visible or invisible by default -
// this will apply when the animation ends
imageView.setImageDrawable(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 Animation.AnimationListener() {
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) {
animate(imageView, images, 0, forever); //Calls itself to start the animation all
// over again in a loop if forever = true
}
}
}
public void onAnimationRepeat(Animation animation) {
// TODO Auto-generated method stub
}
public void onAnimationStart(Animation animation) {
// TODO Auto-generated method stub
}
});
}
That piece of code works, the problem is that there's nothing between the fade in and fade out which makes you see whats under those picture (white screen).
I want the fade in to start while the fade out is running so you won't see the white background but always the pictures.
I've tried changing the timeBetween value to be zero (and even negative) which should change the offset of the second animation which will lead to the animations starting at the same time but without success - It only makes the image disappear faster and still doesn't make the requested effect (Fade in and Fade out together)
Could anyone explain how is it possible to make fade in and fade out activate simultaneously
I think the best way to do this is to have two ImageViews, both inside the same FrameLayout so that they overlap (which can also be done with RelativeLayout).
Top ImageView gets image 1.
Bottom ImageView gets image 2.
Animate top ImageView alpha from 1 to 0.
As top ImageView fades out, bottom ImageView becomes visible.
After animation ends, switch bottom image to top and set alpha back to 1.
Load new image in bottom
Repeat animation
Hi I was looking for a solution and found this Question.
I used Bitmaps for my solutions but I'm sure you can change it back.
Same is true for using the 2 imageviews (not passed with function)
This is my solution:
private void animate(final Bitmap[] images, final int imageIndex, final boolean forever) {
final ImageView imageView0 = mImageSlideShow0;
final ImageView imageView1 = mImageSlideShow1;
imageView0.setVisibility(View.VISIBLE);
imageView1.setVisibility(View.VISIBLE);
AnimationSet animationIn = null;
AnimationSet animationOut = null;
//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 fadeDuration = 1000; // Configure time values here
Animation fadeIn = new AlphaAnimation(0, 1);
fadeIn.setInterpolator(new DecelerateInterpolator()); // add this
fadeIn.setDuration(fadeDuration);
Animation fadeOut = new AlphaAnimation(1, 0);
fadeOut.setInterpolator(new AccelerateInterpolator()); // and this
fadeOut.setStartOffset( 2 * fadeDuration); //time that image is visible without any animations
fadeOut.setDuration(fadeDuration);
animationIn = new AnimationSet(false); // change to false
animationIn.addAnimation(fadeIn);
animationIn.setRepeatCount(1);
animationOut = new AnimationSet(false); // change to false
animationOut.addAnimation(fadeOut);
animationOut.setRepeatCount(1);
int animationInIndex = imageIndex;
int animationOutIndex = 0;
//if first image take last one in array
if(imageIndex != 0)
{
animationOutIndex = animationInIndex - 1;
}
else
{
animationOutIndex = images.length - 1;
}
//select the correct fade in / fade out view
if(mCurrentImageViewActive == 0)
{
//set correct image image view
imageView0.setImageBitmap(images[animationInIndex]);
imageView1.setImageBitmap(images[animationOutIndex]);
//set correct animation image view
imageView0.setAnimation(animationIn);
imageView1.setAnimation(animationOut);
//set next fade in view
mCurrentImageViewActive = 1;
}
else
{
imageView1.setImageBitmap(images[animationInIndex]);
imageView0.setImageBitmap(images[animationOutIndex]);
imageView1.setAnimation(animationIn);
imageView0.setAnimation(animationOut);
//set next fade in view
mCurrentImageViewActive = 0;
}
//if fade out is done call next action
animationOut.setAnimationListener(new Animation.AnimationListener()
{
public void onAnimationEnd(Animation animation)
{
if (images.length - 1 > imageIndex)
{
animate(images, imageIndex + 1,forever); //Calls itself until it gets to the end of the array
}
else
{
if (forever)
{
animate( images, 0,forever); //Calls itself to start the animation all over again in a loop if forever = true
}
}
}
public void onAnimationRepeat(Animation animation) {
// TODO Auto-generated method stub
}
public void onAnimationStart(Animation animation) {
// TODO Auto-generated method stub
}
});
}
Related
I am new to Java and am trying to delay one line of code after a user presses a button. The line of code incraments an array, i++. The reason I would like to do this is because I am animating two textViews by fading them. The one textView fades out while the other fades in and I am trying to change the word being displayed by only incrementing my array index after they have the same Alpha which is half of the animations set duration, 500. I have looked online and I have seen some suggesting a swing timer and other suggesting to use thread.sleep. Any suggestions? Here is the code for that button :).
public void nextWord(View view) { //nextWord is the onclick of the button
Button nextButton = findViewById(R.id.nextButton);
Button showTextButton = findViewById(R.id.showTextButton);
TextView wordTextView = findViewById(R.id.wordTextView);
EditText editTextView = findViewById(R.id.enterEditText);
ImageView logoImageView = findViewById(R.id.logoImageView);
TextView wordTextView1 = findViewById(R.id.wordTextView1);
i++; // need to delay this
String displayHint;
String displayText;
displayText = enterWord() + chooseArray();
displayHint = chooseArray();
wordTextView.setText(displayText);
editTextView.setHint(displayHint);
wordTextView1.setText(displayText) ;
enteredWords[i] = editTextView.getText().toString();
if (i%2 == 0) {
ObjectAnimator alphaAnimation = ObjectAnimator.ofFloat(wordTextView, View.ALPHA, 1f, 0f);
alphaAnimation.setDuration(1000);
ObjectAnimator otherAlphaAnimation = ObjectAnimator.ofFloat(wordTextView1, View.ALPHA, 0f, 1f);
otherAlphaAnimation.setDuration(1000);
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.playTogether(otherAlphaAnimation,alphaAnimation);
animatorSet.start();
} else {
ObjectAnimator alphaAnimation = ObjectAnimator.ofFloat(wordTextView, View.ALPHA, 0f, 1f);
alphaAnimation.setDuration(1000);
ObjectAnimator otherAlphaAnimation = ObjectAnimator.ofFloat(wordTextView1, View.ALPHA, 1f, 0f);
otherAlphaAnimation.setDuration(1000);
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.playTogether(otherAlphaAnimation,alphaAnimation);
animatorSet.start();
}
}
Try with
new Handler().postDelayed(Runnable r, long delay)
Use it like
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
// fade in new text view
}
}, 1000); // time needed for first animation to finish
Now, when first animation takes 1000 ms to finish, then second will start after 1000 ms too. You can put it inside final value to manipulate those delays at once to keep them synchronized
want to turn a card in my app. I have 2 ImageViews 1 Cardfront and 2 Cardback.
My theory ->
I change the width of the cardfront from 100% to 0%
I change the width of the cardback from 0% to 100%
I googled for solution on changing the width of am ImageView while runtime, but the solution I found don't work.
// Code for step 1
ViewGroup.LayoutParams params = ivBomb.getLayoutParams();
int width = params.width;
for (int i = 1; i<width; i++) {
params.width--;
ivBomb.setLayoutParams(params);
Thread.sleep(10); // To see the change
}
When I start it without the Thread.sleep(10);, it disappears instantly. But when I start it with the Thread.sleep(10);, it waits ~7s and then disappears instantly.
What am I doing wrong?
You can use animation to get the flip card effect. This card flip animation tutorial here is for a fragment, but you can use the same animations for your views like
Animation cardFlipRightOut = AnimationUtils.loadAnimation(this, R.anim.card_flip_right_out);
cardFlipRightOut.setAnimationListener(new Animation.AnimationListener(){
#Override
public void onAnimationStart(Animation arg0) {
}
#Override
public void onAnimationRepeat(Animation arg0) {
}
#Override
public void onAnimationEnd(Animation arg0) {
Animation cardFlipLeftIn = AnimationUtils.loadAnimation(this, R.anim.card_flip_left_in);
cardFrontView.startAnimation(cardFlipLeftIn);
}
});
cardBackView.startAnimation(cardFlipRightIn);
Try calling one of these after setLayoutParams() :
1. requestLayout()
2. invalidate()
Since, requestLayout() should be called, when view's position or bounds in the parent layout have been changed, while invalidate() should be called when view's appearance has been changed. When you call requestLayout() then onLayout() and onMeasure() methods of the view will be fired, on the other hand when you call invalidate(), then onDraw() method will be fired.
I want to display ImageViews in GridView using animation. I can display them and apply animation correctly.
But issue is that, if I apply animation on ImageView1 and then to ImageView2 (before animation on ImageView1 is ended) then animation on ImageView1 gets interrupted and ImageView1 is directly set to final state.
Note that I download image using ThreadPoolExecutor with 2 threads. Whenever an image is done downloading, I call addImage(image) method of below ImageAdapter which in turn adds image in GridView and GridView is refreshed to display latest set of images. And Here, while rendering, new image is displayed with animation and this animation(I guess) interrupts animation of currently animating images.
ImageAdapter :
public class ImageAdapter extends BaseAdapter {
private Context mContext;
private List<Bitmap> images;
private ArrayList<Integer> colors;
private boolean[] alreadyLoadedIndexes;
Animation animation;
AnimatorSet animator;
public void addImage(Bitmap img) {
images.add(img);
notifyDataSetChanged();
}
public void setAnimation(Animation animation) {
this.animator = null;
this.animation = animation;
}
public void setAnimator(AnimatorSet animation) {
this.animation = null;
this.animator = animation;
}
public void resetImages() {
images.clear();
notifyDataSetChanged();
alreadyLoadedIndexes = null;
alreadyLoadedIndexes = new boolean[20];
}
// Constructor
public ImageAdapter(Context c) {
mContext = c;
images = new ArrayList<Bitmap>();
colors = new ArrayList<Integer>();
colors.add(Color.CYAN);
colors.add(Color.BLUE);
colors.add(Color.GRAY);
colors.add(Color.YELLOW);
colors.add(Color.MAGENTA);
alreadyLoadedIndexes = new boolean[20];
}
#Override
public int getCount() {
return 20;
}
#Override
public Object getItem(int position) {
return 20;
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ImageView imageView = new ImageView(mContext);
imageView
.setBackgroundColor(colors.get((int) ((Math.sqrt(position) + 2 * position) % 5)));
// If image at index 'position' is available
if (images.size() > position) {
// If loading this image first time then only apply animation
if (!alreadyLoadedIndexes[position]) {
// If animation is specified
if (this.animation != null) {
imageView.setImageBitmap(images.get(position));
imageView.startAnimation(animation);
}
// If animator set is specified
else if (this.animator != null) {
imageView.setImageBitmap(null);
imageView.setBackgroundColor(colors.get((int) ((Math
.sqrt(position) + 2 * position) % 5)));
animator.setTarget(imageView);
animator.start();
Log.e("", "setting image after " + animator.getDuration()
/ 2);
new Handler().postDelayed(
new runnable(imageView, images.get(position)), 500);
} else {
// Use default animation if nothing is specified.
imageView.setImageBitmap(images.get(position));
animation = AnimationUtils.loadAnimation(mContext,
R.anim.fade_in);
imageView.startAnimation(animation);
}
} else {
imageView.setImageBitmap(images.get(position));
}
alreadyLoadedIndexes[position] = true;
}
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
imageView.setLayoutParams(new GridView.LayoutParams(150, 150));
return imageView;
}
class runnable implements Runnable {
ImageView image;
Bitmap bitmap;
public runnable(ImageView img, Bitmap bitmap) {
this.image = img;
this.bitmap = bitmap;
}
#Override
public void run() {
Log.e("", "setting image.");
image.setImageBitmap(bitmap);
}
}
}
try layout animation controlor for GridView, it will animate the views item by item with respect to time duration. check this link ,
Have you tried to apply the animation outside adapter getView method like:
mGridView.getChildAt(childIndexNeededToAnimate).startAnimation(animation);
These child views are independent and not being recycled anymore since they are already drawn.
You have some alternative.
First you can use Animation in your adapter class if you don't want to change your code.
For that check this.
In your adapter class inside the getView you have to call animation like this ,
Animation animation = null;
animation = AnimationUtils.loadAnimation(context, R.anim.push_left_in);
animation.setDuration(500);
convertView.startAnimation(animation);
return convertView;
Second you should use GridLayoutAnimationController in which A layout animation controller is used to animated a grid layout's children.
Sample 1
Sample 2
Just a guess. I'm neither sure if it will help nor if I read your code right. I suppose the problem is harder than I guess.
However, you are using the same animation object for every item. Maybe you should create a new animation for each item. This could be the reason why your animation stops when you launch a new one because the new call just reuse and restarts it.
Good luck.
You problem is notifyDataSetChanged(); it interrupt the animation. Try calling it when the animation is finished.
I am new to android and I need help.
I want my image which is falling from the top of screen to get invisible when I click a button on the keyboard which has the same tag as the image. Although I have implemented the above points a problem arises when I want to show the next animation again immediately after the previous image gets invisible. This is my code for animation.
public void startAnimation(final ImageView aniView)
{
animator= ValueAnimator.ofFloat(0 ,.85f);
animator.setDuration(Constants.ANIM_DURATION);
animator.setInterpolator(null);
//generation of random values
Random rand = new Random();
index = rand.nextInt((int) metrics.widthPixels);
//for debugging
i = Integer.toString(index);
Log.e(" index is :", i);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener()
{
#Override
public void onAnimationUpdate(ValueAnimator animation)
{
float value = ((Float) (animation.getAnimatedValue())).floatValue();
aniView.setTranslationX(index);
aniView.setTranslationY((height+ (50*mScale))*value);
//aniView.setTranslationY(height);
}
});
animator.start();
}
//keyboard methods goes here
#Override
public void onClick(View v)
{
gettext(v);
}
private void gettext(View v)
{
try
{
String b = "";
b = (String) v.getTag();
String img_val = map.get(b);
int imgid = (Integer) imageView.getTag();
Log.e("img values=:", img_val+" "+imgid);
if(img_val.equals(ALPHABETS[imgid]))
{
imageView.setVisibility(View.INVISIBLE);
animator.start();
//trying to start the animation again
}
I am using the animation.addupdateListener to call the animation again and again but it only calls when the .ofFloat finishes on the value. When I click on the appropriate button the animation gets invisible but the next animation starts again after the same time. I want to start it immediately.
Basically calling start() again won't work. you need to "reset" the animation somehow, did you try calling end() before ?
animator.end();
animator.start();
i have a method i created that is called throughout my project, i made it because i have a Crouton (toast) that tells a user to activate there account, or it will also alert them when there is no valid internet connection... And i dont want it to interfere with the top of my View because theres user actions that are important there. Im using a RelativeLayout
First off, this piece of code doesnt work anyways, but as i was fixing it i realized my bar i have at the bottom to switch between different Activities is now gone because it was slid down, im thinking i can just resize the hieght.
can anyone point me int he right direction for two things, one resizing height instead of sliding the whole view down, and two, help me fix the crash im getting, which occurs on setLayoutParam
i call this like this teknoloGenie.slideViewDown("100", findViewById(R.id.RootView));
public void slideViewDown(final String distX, final View view) {
final TranslateAnimation slideDown = new TranslateAnimation(0, 0, 0, Float.parseFloat(distX));
slideDown.setDuration(500);
slideDown.setFillEnabled(true);
slideDown.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationRepeat(Animation animation) {
}
#Override public void onAnimationEnd(Animation animation) {
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams)view.getLayoutParams();
params.addRule(RelativeLayout.CENTER_HORIZONTAL, -1);
params.setMargins(0, view.getTop()+Integer.parseInt(distX), 0, 0);
view.setLayoutParams(params);
view.requestLayout();
}
});
view.startAnimation(slideDown);
}
If you want to animate the height of a View, you need to write your own custom-animation and modify the LayoutParams of your animated view.
In this example, the animation animates the height of the animated View.
This is how it could look like:
public class ResizeAnimation extends Animation {
private int startHeight;
private int deltaHeight; // distance between start and end height
private View view;
/**
* constructor, do not forget to use the setParams(int, int) method before
* starting the animation
* #param v
*/
public ResizeAnimation (View v) {
this.view = v;
}
#Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
view.getLayoutParams().height = (int) (startHeight + deltaHeight * interpolatedTime);
view.requestLayout();
}
/**
* set the starting and ending height for the resize animation
* starting height is usually the views current height, the end height is the height
* we want to reach after the animation is completed
* #param start height in pixels
* #param end height in pixels
*/
public void setParams(int start, int end) {
this.startHeight = start;
deltaHeight = end - startHeight;
}
#Override
public boolean willChangeBounds() {
return true;
}
}
In code, create a new Animation and apply it to the RelativeLayout that you want to animate:
View v = findViewById(R.id.youranimatedview);
// getting the layoutparams might differ in your application, it depends on the parent layout
RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) v.getLayoutParams();
ResizeAnimation a = new ResizeAnimation(v);
a.setDuration(500);
// set the starting height (the current height) and the new height that the view should have after the animation
a.setParams(lp.height, newHeight);
v.startAnimation(a);
To your LayoutParams problem:
My guess is that you are getting a ClassCastException because you are not using the correct LayoutParams class. If your animated view for example is contained by a RelativeLayout, you can only set RelativeLayout.LayoutParams to it. If your View is contained by a LinearLayout, you can only set LinearLayout.LayoutParams for your View.