I wish to have an animated background like this gif:
.
I don't have a mac or adobe after effects software to create a lottie json for such animation, and i want a more command over animation than simply using a gif. From what i have read over the internet, I have to use either TransitionManager or TranslationAnimation , but i am unable to figure out the correct code for it.
I am also interested in knowing if there is a plugin, or some way to make minor edits to already available lottie files like background color change , items color change, items removal, etc just like the way we could do for simple vector images(Using Android Studio, or at the very least, some free software). I found this lottie file which was doing a very great job for me, but i couldn't modify its colors
found it! When i logged the values of some variables like view.getX() or view.getRootView().getX(), i was able to figure out, that my view will have its location as 0,0 . so After that it was all a need for finding the screen size to finally make this infinite cloud moving animation. I am not sure if this function is good in terms of memory or performance , but on my device, its running smoothly.
private void showCloudMovingContinuouslyAnimation(View v) {
DisplayMetrics displayMetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
int runtimeScreenWidth = displayMetrics.widthPixels;
int totalDuration = runtimeScreenWidth*5;
int viewPositionX = 0, viewPositionY = 0;
TranslateAnimation outToRight = new TranslateAnimation(
viewPositionX, (runtimeScreenWidth / 2f) + 50,
viewPositionY, viewPositionY);
outToRight.setDuration(totalDuration / 2);
outToRight.setRepeatCount(Animation.INFINITE);
TranslateAnimation inFromLeft = new TranslateAnimation(
-((runtimeScreenWidth / 2f) + 50), viewPositionX,
viewPositionY, viewPositionY
);
inFromLeft.setDuration(totalDuration / 2);
inFromLeft.setRepeatCount(Animation.INFINITE);
boolean shouldRemainThereAfterAnimationFinishes = true;// useful when animating for single time
AnimationSet animationSet=new AnimationSet(true);
animationSet.setInterpolator(new LinearInterpolator());
animationSet.setRepeatCount(Animation.INFINITE);
animationSet.addAnimation(inFromLeft);
animationSet.addAnimation(outToRight);
v.startAnimation(animationSet); // start animation
}
Related
I am trying to figure out how to animate an image from left to right, and then from right to left.
For example imagine the following image:
At full resolution, the width of the image would exceed the width of the screen. So initially, only the left side of the image should be visible, but as the animation is running, slowly the right side becomes visible, eg.:
Once the right side of the image was fully uncovered, the animation starts in reverse:
Any ideas how to achieve this?
Android APIs or any techniques would be of great help.
Using ObjectAnimator.
Well, I didn't really know, how to size image in without cropping, so I made view's width 1000dp.
Here is solution:
ImageView imageView = findViewById(R.id.imageView);
imageView.post(() -> {
Point point = new Point();
getWindowManager().getDefaultDisplay().getSize(point);
float width = imageView.getMeasuredWidth();
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(imageView, "translationX", 0, -(width - point.x));
objectAnimator.setRepeatMode(ValueAnimator.REVERSE);
objectAnimator.setRepeatCount(ValueAnimator.INFINITE);
objectAnimator.setDuration(10000);
objectAnimator.start();
});
Let me explain.
First, I get size of device.
Point point = new Point();
getWindowManager().getDefaultDisplay().getSize(point);
Then, I get width of view and creating ObjectAnimator
float width = imageView.getMeasuredWidth();
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(imageView, "translationX", 0, -(width - point.x));
First argument is a view, that will be animated. Second argument tells objectAnimator what method (in this case setter) to use. We use translationX, so objectAnimator use setTranslationX().
All other arguments tells objectAnimator from where to where it should animate.
We substracting point.x from width for animation stops when edge of image is shown. Else, imageView will slide to the left until image disappears.
For example:
ObjectAnimator.ofFloat(imageView, "translationX", 0, 200, 100, 300);
says that image should go by axis X to the point 0, then 200, then 100 and in the end 300.
objectAnimator.setRepeatMode(ValueAnimator.REVERSE);
tells that after animation done, do it again, but in reverse.
objectAnimator.setRepeatCount(ValueAnimator.INFINITE);
tells that animation must repeat itself infinitely.
objectAnimator.setDuration(10000);
Duration of the animation in milliseconds.
Try with TranslateAnimation:
First, you have to know how big is the view:
ImageView picture = findViewById(R.id.picture);
int pictureWidth = picture.getWidth();
private void animation(View view, float pictureWidth) {
Animation offSet = new TranslateAnimation(0, - moveTo, 0, 0);
offSet.setInterpolator(new AccelerateDecelerateInterpolator()); // just to make a smooth movement
offSet.setDuration(durationInMillis);
}
The code above will move to the left showing the right side of the image,
you can add something similar to reverse the movement.
There are for sure better and more complete solutions, this is just (I think) the easier.
I have a small game in my application, if you get something right balloons float up the screen, the balloons are views moved by 2 ObjectAnimators in an animation set, and on my main debugging device it works fine but on other devices (including tablets) it looks aweful the values are all over the place and the views violently sway from one side to the next.
here is a snippet of what im doing:
//2 square balloons floating
sb = (ImageView)findViewById(R.id.squareballoon);
sb.setVisibility(View.VISIBLE);
sb2 = (ImageView)findViewById(R.id.squareballoon2);
sb2.setVisibility(View.VISIBLE);
sp.play(inflate, 1, 1, 0, 0, 1);
//left balloon
ObjectAnimator sqbalAnim3 = ObjectAnimator.ofFloat(sb,"x",-500,500);
sqbalAnim3.setDuration(700);
sqbalAnim3.setRepeatCount(5);
sqbalAnim3.setRepeatMode(ValueAnimator.REVERSE);
ObjectAnimator sqbalAnim = ObjectAnimator.ofFloat(sb,"y",2000,-1800);
sqbalAnim.setDuration(3000);
sqbalAnim.setRepeatMode(ValueAnimator.RESTART);
AnimatorSet animSetXY = new AnimatorSet();
animSetXY.playTogether(sqbalAnim, sqbalAnim3);
animSetXY.start();
//right balloon
ObjectAnimator sqbalAnim4 = ObjectAnimator.ofFloat(findViewById(R.id.squareballoon2),"x",-1500,-500);
sqbalAnim4.setDuration(700);
sqbalAnim4.setRepeatCount(5);
sqbalAnim4.setRepeatMode(ValueAnimator.REVERSE);
ObjectAnimator sqbal2Anim = ObjectAnimator.ofFloat(findViewById(R.id.squareballoon2),"y",1800,-1800);
sqbal2Anim.setDuration(3000);
sqbal2Anim.setRepeatMode(ValueAnimator.RESTART);
AnimatorSet animSetXY2 = new AnimatorSet();
animSetXY2.playTogether(sqbal2Anim,sqbalAnim4);
animSetXY2.start();
//balloon animation end
animSetXY2.addListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
sp.play(dropSound,1,1,0,0,1);
sb.setBackgroundResource(R.drawable.burst);
pop = (AnimationDrawable) sb.getBackground();
pop.start();
sb2.setBackgroundResource(R.drawable.burst);
pop = (AnimationDrawable) sb2.getBackground();
pop.start();
}
});
return true;}
//end of square balloons
ive read i can use a fraction rather than explicit values, can anybody help me out with this or point in the right direction,
any and all suggestions welcome, many thanks
I guess your problem is in parameters you are using (hardcoding) like:
ObjectAnimator.ofFloat(sb,"x",-500,500);
ObjectAnimator.ofFloat(sb,"y",2000,-1800);
Since such values are only good for the device (screen actually) you are testing on. Other devices has other screens with other resolutions and you should consider it. Also you should maybe calc values from dp to pixels. What are 500 and 2000 actually? If its pixels then most probably thats the problem.
Take a look here (for dp to px):
What is the difference between "px", "dp", "dip" and "sp" on Android?
Android: 'dp' to 'px' conversion?
So I am trying to get a button on the screen to move when it is clicked. It currently is setup to count clicks, but I want the button to move everytime you click it. I have tried a translate animation, which didn't work because the button still fires the onClick from the original location.
I leared about ObjectAnimator and have been trying to get that to work since the onClick event will move with the button, but I can't seem to get it to work. I also need help getting the button to move randomly within it's layout parent. Any help would be greatly appreciated :)
Here's my current Object Animator Code. Please note it is not setup for random movement yet, since I am unsure of how to get it to do that:
ObjectAnimator animX = ObjectAnimator.ofFloat(btnCount, "xTranslate", 0f, 50f);
ObjectAnimator animY = ObjectAnimator.ofFloat(btnCount, "TranslateY", 0f, 50f);
AnimatorSet animSet = new AnimatorSet();
animSet.playSequentially(animX, animY);
animSet.setDuration(500);
animSet.start();
Easiest way to get this done will be as given below. Do this on your onClick listener.
btnCount.animate().xBy(10).yBy(10);
With regards to random, I guess you can use something as simple as this... In any case, you may have to take care of reaching the screen limit.
Random r = new Random();
btnCount.animate().xBy(r.nextInt(10)+1).yBy(r.nextInt(10)+1);
Found that using the below did what I needed it to:
Random r = new Random();
int buttonHeight;
int buttonWidth;
buttonHeight = btnCount.getHeight();
buttonWidth = btnCount.getWidth();
int xLeft = r.nextInt(480 - buttonHeight);
int yUp = r.nextInt(800 - buttonWidth);
int xRight = r.nextInt(480 + buttonHeight);
int yDown = r.nextInt(800 + buttonHeight);
btnCount.setX(xLeft);
btnCount.setY(yUp);
btnCount.setX(xRight);
btnCount.setY(yDown);
There are 4 types of animations in android - rotate, alpha,scale and translate.
I want to prepare curved translate animation.
Is it possible.?
What Android version do you use? Since API level 11 you can use custom Animators which can easily implement your curve translation.
If you use a version below that there is afaik only the possibility to manually concatenate multiple linear translations using the translate animation and setting animation listeners
EDIT:
Example:
View view;
animator = ValueAnimator.ofFloat(0, 1); // values from 0 to 1
animator.setDuration(5000); // 5 seconds duration from 0 to 1
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener()
{
#Override
public void onAnimationUpdate(ValueAnimator animation) {
float value = ((Float) (animation.getAnimatedValue()))
.floatValue();
// Set translation of your view here. Position can be calculated
// out of value. This code should move the view in a half circle.
view.setTranslationX((float)(200.0 * Math.sin(value*Math.PI)));
view.setTranslationY((float)(200.0 * Math.cos(value*Math.PI)));
}
});
I hope it works. Just copied & pasted (and shortened and changed) the code from one of my apps.
Here are the animators I use:
Purpose: Move View "view" along Path "path"
Android v21+:
// Animates view changing x, y along path co-ordinates
ValueAnimator pathAnimator = ObjectAnimator.ofFloat(view, "x", "y", path)
Android v11+:
// Animates a float value from 0 to 1
ValueAnimator pathAnimator = ValueAnimator.ofFloat(0.0f, 1.0f);
// This listener onAnimationUpdate will be called during every step in the animation
// Gets called every millisecond in my observation
pathAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
float[] point = new float[2];
#Override
public void onAnimationUpdate(ValueAnimator animation) {
// Gets the animated float fraction
float val = animation.getAnimatedFraction();
// Gets the point at the fractional path length
PathMeasure pathMeasure = new PathMeasure(path, true);
pathMeasure.getPosTan(pathMeasure.getLength() * val, point, null);
// Sets view location to the above point
view.setX(point[0]);
view.setY(point[1]);
}
});
Similar to: Android, move bitmap along a path?
Consider the following web link. It is a game in C. You need to isolate the projectile() function and try to understand the variables defined within it. Once you get that try implementing it in your own code.
http://www.daniweb.com/software-development/c/code/216266
I want to draw a infinitely repeating parallax using Cocos2D on Android.
Now, there are some solutions given to this problem in Objective C, but I'm stuck with my implementation in Android. I have tried using
CCSprite background = CCSprite.sprite("background_island.png");
CCTexParams params = new CCTexParams(GL10.GL_LINEAR,GL10.GL_LINEAR,GL10.GL_REPEAT,GL10.GL_REPEAT);
background.getTexture().setTexParameters(params);
But it only extends the background in 1 direction.
I guess I have to use 2 sprites, such that as soon as 1st finishes, the other starts and vice versa, but I'm stuck with the implementation.
I had the same problem and figured it out.
Try this. Declare the background and offset as a member:
CCSprite _bg;
float _bgOffset;
In your scene constructor:
CGSize winSize = CCDirector.sharedDirector().displaySize();
_bg = CCSprite.sprite("yourbg.png"); // needs to be square, i.e. 256x256
_bg.setTextureRect(0, 0, winSize.width, winSize.height, false);
_bg.getTexture().setTexParameters(GL10.GL_LINEAR, GL10.GL_LINEAR, GL10.GL_REPEAT,
GL10.GL_REPEAT);
_bg.setAnchorPoint(CGPoint.zero());
this.addChild(_bg);
And in your update(float dt) method:
if (_bgOffset > 2000000000)
_bgOffset = 0; // don't want problems, do we?
_bgOffset += dt * PIXELS_PER_SECOND; // this can be dynamic if you want
_bg.setTextureRect(0, _bgOffset, _bg.getTextureRect().size.width,
_bg.getTextureRect().size.height, false);
See "Repeating Backgrounds" in http://www.raywenderlich.com/3857/how-to-create-dynamic-textures-with-ccrendertexture for the Objective C code
If you need to go both ways, you could perhaps start with a non-zero _bgOffset and see if that works.
Hope this helps someone!
Please check out below link for Parallax vertical endless background: http://kalpeshsantoki.blogspot.in/2014/07/create-vertical-endless-parallax.html
CGSize winSize = CCDirector.sharedDirector().displaySize();
//I made graphics for screen 720*1200....so I made this dynamic scale to support multiple screens
float sX = winSize.width / 720.0f;
float sY = winSize.height / 1200.0f;
background = CCVerticalParallaxNode.node(sX, sY, true);
background.addEntity(1f, "background.png", 0);
background.addEntity(3, "road_simple.png", winSize.width / 2);
background.addEntity(1.7f, "road_side.png", 0);
addChild(background);