Basically I want something to fade-in and then fade-out. Initially it should be invisible, and when the animation is ended, it should also be invisible.
targetView.alpha = 0f;
var aa = AlphaAnimation(0f, 1.0f);
aa.duration=2000;
aa.repeatMode = Animation.REVERSE;
aa.repeatCount = 1;
I have tried the code above, but it did not work. it seems that the alpha animation is multiplying the initial alpha with that animation. So, 0f * 1.0f = 0f = invisible.
After searching for an answer, I have tried this, but it did not work.
aa.fillBefore= true;
aa.fillAfter=true;
How can I make the animation ignore the initial alpha value? Is it impossible, and I should change the visibility at the start/end of the animation manually?
Yes you are right about "it seems that the alpha animation is multiplying the initial alpha with that animation. So, 0f * 1.0f = 0f = invisible.".
Just don't use targetView.alpha = 0f;, use targetView.setVisibility(View.INVISIBLE); instead.
Related
I am trying to implement similar animation like this, with Jetpack Compose
figure: https://dribbble.com/shots/4762799-Microinteraction-Exploration-002
For the play icon’s transformation (from a triangle to a rectangle) , it not difficult to get it done by using path morphing animation.After reading some gist, I found that I can build an ImageVector by supplying the pathData , that's new to me~
While for ****the part on the right, the rotation of the cube object. Well, maybe I should call that a rolling-over or whatever, because the cube changed its pivot after -90 degrees.
I'm wondering that wether I can create a VectorGroup for the cube’s pathData and animate it by updating its group parameters.
re: androidx.compose.ui.graphics.vector.ImageVector.Builder#addGroup
ImageVector.Builder(defaultWidth = 100.dp, defaultHeight = 100.dp, viewportWidth = 100, viewportHeight = 100)
.addGroup(name = "CubeRotation", rotate = params.rotate, pivotX = params.pivotX, pivotY = params.pivotY,)
.addPath(pathData = pathData, fill = SolidColor(Color.LightGray))
.clearGroup()
.build()
Here I trying to update the pivotX halfway through the animation, so I divide it into two section:
// rotate -90 degrees twice with different pivot
val rotate = if (fraction <= 0.5f) {
lerp(0f, -180f, fraction)
} else {
lerp(0f, -180f, fraction - 0.5f)
}
// change the pivotX
val pivotX = if (fraction <= 0.5f) 52f else 30f
GroupParams(
pivotX = pivotX,
pivotY = 100f,
rotate = rotate,
)
Frustratedly, after rotating by the first -90 degrees, the transformation that this rotation performed will NOT persist, -or- its transformation NOT being applied after the half time of the transition.
fraction: 0~0.5
fraction: 0.5~1
The code sample I've uploaded: IndicatorDrawable.kt
Can I implement the rotate transformation by just updating the pathData ?
For me, the VectorGroup in ImageVector looks like creating AnimatedVectorDrawable in xml, or maybe I should try some traditional way like ObjectAnimationSet in View system ?
How can I create an animation similar to the stock android launcher animation applied to apps when you change homescreen pages.
Here's a gif: https://i.stack.imgur.com/Zh7qE.gif
As the page swipes, the icons slightly overshoot their mark, and settle back to the center. I don't see how I can do that with a PageTransformer and I can't find any resources to point me in the right direction.
I once created a one-time bounce animation:
val pixels = binding.pager.width / 8
ValueAnimator.ofInt(0, pixels).apply {
duration = 200L
interpolator = DecelerateInterpolator()
repeatCount = 3
repeatMode = ValueAnimator.REVERSE
addUpdateListener {
binding.pager.scrollX = it.animatedValue as Int
}
}.start()
Use ofInt(0, pixels) for bouncing left or ofInt(0, -pixels) to bouncing right.
In my code I used a dragging distance of 1/8 of the view pager.
Feel free to choose how much you want to bounce:
val pixels = PIXELS_TO_DRAG
Finally, the repeatCount determines how many bounces - use 3 for 2 bounces, 5 for 3 bounces, 7 for 4 bounces etc.
You can fire this animation each time a pager transition end and tweak the parameters to get the desired behavior.
Enjoy,
Hope it helps :)
According to #Shlomi, you can do this implementation:
var currentPage = 0
binding.viewPager.onPageChangeListener {
val pixels = binding.vpBennefits.width / 8
ValueAnimator.ofInt(
0, if (currentPage < it)
pixels
else
-pixels
).apply {
duration = 200L
interpolator = DecelerateInterpolator()
repeatCount = 1
repeatMode = ValueAnimator.REVERSE
addUpdateListener {
binding.vpBennefits.scrollX = it.animatedValue as Int
}
}.start()
currentPage = it
}
By this way you can obtain the desired effect in both sides
I am wanting to hide an extended fab when it is clicked using an Animation. I want to scale the button down from original height and width to 0/gone. It disappears in the corner but the animation is laggy in the middle.
private fun animateHideScoreFab(){
val animX = ValueAnimator.ofInt(editScoreFab.measuredWidth, 0).apply {
duration = 1000
}
val animY = ValueAnimator.ofInt(editScoreFab.measuredHeight, 0).apply {
duration = 1000
}
animX.addUpdateListener {
val value = it.animatedValue as Int
editScoreFab.layoutParams.width = value
editScoreFab.requestLayout()
}
animY.addUpdateListener {
val value = it.animatedValue as Int
editScoreFab.layoutParams.height = value
}
AnimatorSet().apply {
this.interpolator = AccelerateDecelerateInterpolator()
play(animX).with(animY)
start()
}
}
Result:
Using AccelerateDecelerateInterpolator https://developer.android.com/reference/android/view/animation/AccelerateDecelerateInterpolator says
An interpolator where the rate of change starts and ends slowly but accelerates through the middle.
So in the middle the rate of change is faster than the start which could make it look laggy
Try another Interpolator like LinearInterpolator https://developer.android.com/reference/android/view/animation/LinearInterpolator.html which has a constant rate of change.
Update
For AccelerateDecelerateInterpolator if you look at the table in https://developer.android.com/guide/topics/graphics/prop-animation.html#interpolators between 400ms and 600ms the the value jumps 45.5% of the distance you and animating
The other factor of smoothness is not to use an Int but use a Float e.g. ValueAnimator.ofFloat so it has intermediate steps,
Update2
Re-laying out an item is expensive as it has to be measured and redrawn.
It should be faster and smoother just to scale the already drawn image as this is usually done by the GPU and thus faster and smoother. Also scaling a view takes a Float
example of scaling a Fab to top right onClick (Note using ObjectAnimator as it is simpler to implement)
Sorry in Java not Kotlin
FloatingActionButton fab = findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
AnimatorSet animationSet = new AnimatorSet();
// Set point to scale around to top right
view.setPivotY(0);
view.setPivotX(view.getMeasuredWidth());
ObjectAnimator scaleY = ObjectAnimator.ofFloat(view,"scaleY", 1f, 0f);
scaleY.setDuration(1000);
// Optional as AccelerateDecelerateInterpolator is the default
scaleY.setInterpolator(new AccelerateDecelerateInterpolator());
ObjectAnimator scaleX = ObjectAnimator.ofFloat(view,"scaleX", 1f, 0f);
scaleX.setDuration(1000);
// Optional as AccelerateDecelerateInterpolator is the default
scaleX.setInterpolator(new AccelerateDecelerateInterpolator());
animationSet.playTogether(scaleX, scaleY);
animationSet.start();
}
});
There's a scaleX and scaleY property in Views that you can interpolate from 1 to 0, this will give the effect of the View shrinking and not the container.
Second, for a scale animation work to the top if your parent layout params doesn't do for you, you have to set the pivot to the rightXtop corner with: view.pivotX = view.width; view.pivotY = 0
Also, if you using propertyListener and updating it yourself you can use only one ValueAnimator and do the calc yourself plus consider replacing editScoreFab.requestLayout() with editScoreFab.invalidate()
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 my animation to only spin for one rotation. Everytime I adjust the duration it just spins at the same speed for longer/slower. Where am I going wrong?
private static final float ROTATE_FROM = 0.0f;
private static final float ROTATE_TO = -10.0f * 360.0f;
protected RotateAnimation r = new RotateAnimation(ROTATE_FROM, ROTATE_TO,
Animation.RELATIVE_TO_SELF, 0.5f,
Animation.RELATIVE_TO_SELF, 0.5f);
r.setDuration(5000);
r.setRepeatCount(0);
r.setInterpolator(this, android.R.anim.linear_interpolator);
r.setAnimationListener(AndroidVideoPlayer.this);
favicon.startAnimation(r);
I believe what you are looking for is repeatCount
r.setRepeatCount(0)
http://developer.android.com/reference/android/view/animation/Animation.html#setRepeatCount(int)
From the documentation:
Sets how many times the animation should be repeated. If the repeat
count is 0, the animation is never repeated. If the repeat count is
greater than 0 or INFINITE, the repeat mode will be taken into
account. The repeat count is 0 by default.
Or are you saying that the animation continues to rotate for whatever duration you set? (i.e., you set it for 5000 it rotates for 5 seconds even if it overshoots the "end"). What if you set that value to less than the amount of time it takes to rotate your animation?
In that case it's probably your LinearInterpolator that's animating for a constant rate of change. You could maybe print the value of computeDurationHint() to see if the application is able to guess how long the duration should be.
P.S. What are your ROTATE_FROM and ROTATE_TO values?
It was the -10.0f that was the problem!