In my Android app, I have a fan image whose rotation speed is set by regulator.
This is the animation part:
private fun setFanSpeed(toggle:Boolean, speed:Float){
var speed:Float = speed
if (!toggle)
speed = 0F
val animation = RotateAnimation(0F, 720F,
Animation.RELATIVE_TO_SELF,0.5f,
Animation.RELATIVE_TO_SELF, 0.5f
)
animation.duration = speedToDuration(speed)*1000
animation.repeatCount = Animation.INFINITE
fan.animation = animation
fan.startAnimation(animation)
}
Unfortunately, the rotating fan feels weird because, instead of rotating at a constant speed i.e 720 rotation in a constant time it accelerates during the start of the animation, and decelerates to a stop during the end. Then speeds up again for the next rotation.
How can I remove the speed up and the speed down, and just make the animation work at a constant speed?
It seems that AccelerateDecelerateInterpolator is the default interpolator for Animation, against the caption in documentation. Specifying LinearInterpolator explicitly, you'll be able to make it rotate uniformly.
animation.interpolator = LinearInterpolator()
Related
I am making a Rollette game and I want to play sound in each crossing section like if 1 is crossing it should find some trigger or collision detection and ping one tick sound. My problem is that I am not able to find the collision detection on image. Below is the approaches that I have done.
I have taken LayoutView and placed a Rollette wheel image inside it.
In each section (0-9) has taken a green small button which will be used to detect the collision with the arrow. Once it collides there will be a Tick sound with up-down animation in arrow. (Image attached).
Problem.
I am not able to find the new co-ordinate of views in each rotation. It is returning the same static location every time and hence collision is never happening.
Rotation Code..
final RotateAnimation rotate = new RotateAnimation(0, 360f,
RotateAnimation.RELATIVE_TO_SELF, 0.5f, RotateAnimation.RELATIVE_TO_SELF, 0.5f);
rotate.setDuration(10000);
rotate.setFillAfter(true);
Collision detection code...
Rect arrowBtnRect = new Rect();
arrowBtn.getGlobalVisibleRect(arrowBtnRect);
Rect btn0Rect = new Rect();
btn0.getGlobalVisibleRect(btn0Rect);
if(arrowBtnRect.intersect(btn0Rect)) {
System.out.println("Collision detected "+numberSelected);
numberSelected = "0";
return true;
}
Your idea is brilliant!
But I have certain remarks on your approach:
setFillAfter() is not helping, according to documentations:
If fillAfter is true, the transformation that this animation performed will persist when it is finished.
I recommend using ObjectAnimator instead of RotateAnimation. While RotateAnimation is just making the view looks as if it is rotating until you call fillAfter (which happens after animation stops), ObjectAnimator makes the view really change its actual angle while rotating. See this: https://stackoverflow.com/a/29465710/10005752
Usage:
Random random = new Random();
float randomAngle = (float) (random.nextInt(360) + 1);
ObjectAnimator rouletteAnimator = ObjectAnimator.ofFloat(rouletteView, View.ROTATION, 0f, randomAngle);
rouletteAnimator.setDuration(10000);
rouletteAnimator.start();
Also, to elaborate more on my comment I recommend that get all angles that have buttons on them before starting animating, and when animation starts keep using rouletteView.getRotation(); to check what angle is at the top.
Example:
Button1 is at angle 90 and rouletteView is rotating Counter Clockwise. Then if rouletteView.getRotation() == 360 - 90 is true then Button1 is touching the arrow.
I hope I'm clear!
I'm developing a animation which must show a view increasing its size progresively more fast. I want to achieve the same effect that you see when a car is coming. When is far, the coming movement is slow, but the more near is the vehicle, the faster the car is for your vision.
When using ScaleX with ObjectAnimator, you have some possibilities of interpolation:
AccelerateDeccelerateInterpolator (default) -> very slow when the animation is close to finish...
AccelerateInterpolator -> Also slowing when the ScaleX is too much huge.
LinearInterpolator -> Even more slower when the ScaleX is too much huge.
FastOutSlowInInterpolator -> Still slow at the end.
How can the ScaleX animation get an effect of increasing speed of the scale with the time?
My sample code:
scaleX = ObjectAnimator.ofFloat(view, "scaleX", 0.1f, 20f);
scaleX.setDuration(10000);
scaleX.setInterpolator(new AccelerateInterpolator());
scaleX.start();
Thank you
Solved creating a custom cubic bezier curve using this web: https://matthewlein.com/ceaser/
Interpolator customInterpolator = PathInterpolatorCompat.create(cpX1,cpX2,cpY1,cpY2)
the resulting curve is similar to this:
|
|
_____/
I would like to have an image "bump" (or change its size) according to music. I don't need the music detect side, I just need a way to resize the image dymaically and according to an animation. What is the best way to do this?
If you're using at least API 11 and want to animate it smoothly, you can use an ObjectAnimator to animate various changes to the properties of a View. For example:
ObjectAnimator oa = ObjectAnimator.ofFloat(myView, View.SCALE_X, 1.0, 1.25);
oa.setDuration(25); //how long the animation lasts in ms, probably short for your purposes
oa.start();
This will scale the X size of the view myView from the default (1.0) to slightly larger (1.25). You will then need to do the same for the SCALE_Y property. Note that you will probably want to keep track of the current scale value so that your next animations look nice. For example:
float currentScale = 1.0;
...
void scaleMyView(float newScale) {
ObjectAnimator oa = ObjectAnimator.ofFloat(myView, View.SCALE_X, currentScale, newScale);
oa.setDuration(25);
oa.start();
currentScale = newScale;
}
See also the documentation on ObjectAnimators if you need more info. Hope this helps!
Every View has setScaleX and setScaleY methods. I believe you can use it for this. As far as syncing it to the music, that depends on the way you're playing it.
There is greate animation library for Android.
https://github.com/daimajia/AndroidViewAnimations
https://github.com/2359media/EasyAndroidAnimations
I have an Image (which looks like a round loading circle) that I want to rotate around it's own center.. I saw a lot of code which suggested to set the PivotY and PivotX to 0.5F or th half of the image. Both does not work.. After a lot of trial and error it does rotate around it's own center with the following code:
ImageView loading = FindViewById<ImageView>(Resource.Id.loadingGif);
RotateAnimation rAnim = new RotateAnimation(0.0F, 359.0F, Dimension.RelativeToSelf, 0.25F, Dimension.RelativeToSelf, 0.25F);
rAnim.Interpolator = new LinearInterpolator();
rAnim.RepeatCount = Animation.Infinite;
rAnim.Duration = 1000;
loading.StartAnimation(rAnim);
But the animation itself is not going smooth anymore, the image seems to rotate about 50degrees then starts to hang and skips half of the rotation and then continues normally on the top half of the rotation (I hope that makes any sense).
Any idea why my rotation does not rotate the full 360 degrees smoothly?
EDIT
I still haven't solved this problem, but I did just discover something peculiar about it. The animation is used on a loading screen with no extra functionalities on the moment of the animation. I noticed that when I keep my finger on the screen the animation DOES happen smoothly!!
This got me thinking that the issue maybe isn't in the animation code but something else.. but what I don't know yet..
I've finally found the answer!
I've included the line:
loading.setDrawingCacheEnabled(true);
And after that had to change the pivots to 0.5F too. And now the animation runs smoothly!
//Rotate image
ImageView loading = FindViewById<ImageView>(Resource.Id.loadingGif);
loading.setDrawingCacheEnabled(true);
rAnim = new RotateAnimation(0.0F, 359.0F, Dimension.RelativeToSelf, 0.5F, Dimension.RelativeToSelf, 0.5F);
rAnim.Interpolator = new LinearInterpolator();
rAnim.RepeatCount = Animation.Infinite;
rAnim.Duration = 1500;
loading.StartAnimation(rAnim);
I have a problem while using the scroller in my application.
I have used the scroller but it is not working properly as it is not able to maintain a consistent speed while automatically scrolling. The speed of the text is getting slower with time as the text moves upward.
Here is the code that I used for this purpose:
length = prompt_text.getLineCount();
Log.d("length",""+length);
prompt_text.setScroller(scroll);
scroll.startScroll(0,0,0,10 * length, 100000 / speedAmount);
Have you tried setting up the Scroller interpolator as a LinearInterpolator?
http://developer.android.com/reference/android/widget/Scroller.html#Scroller(android.content.Context,%20android.view.animation.Interpolator)
Sample:
yourScroller = new Scroller(yourContext, new LinearInterpolator());