I have an animation that slides across the screen, while the animation is playing I want it to disapear if it has been clicked!
I have tried to use OnClickListener() and also OnClickMethods, both only work after the animation has finished playing!
TranslateAnimation animation = new TranslateAnimation(answer, answer, 0, height * -1); // xfrom , xto, y from,y to
animation.setDuration(5000);
Floater0.startAnimation(animation);
animation.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationRepeat(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
if (AdPlayer0.isPlaying()) {
answer = rn.nextInt(width) + 1; //useless
TranslateAnimation animation0 = new TranslateAnimation(answer, answer, 0, height * -1); // xfrom , xto, y from,y to
animation0.setDuration(5000);
animation0.setFillEnabled(true);
Floater1.startAnimation(animation0);
Floater1.setVisibility(View.VISIBLE);
Floater0.startAnimation(animation);
}
}
});
I was reading the answer here and something interesting was mentioned:
Animations do NOT effect the 'physical' location of the views on screen. If you want it to actually move then you need to adjust the properties of the view.
I have now tested the above quote, and it seems to be true! I have also looked into how to adjust the position properties of the view after the animation has ended, however I want to change its position before an animation has ended(While its playing)!
Any suggestions for a work around? ideally I would want to change the physical position of the view while the animation is played!
A TranslationAnimation only moves the pixels on the screen, so an OnClickListener does not animate with it. Use ViewPropertyAnimator instead and set an OnClickListener then it should work.
The code would look something like this :
Floater1.animate().setDuration(5000).translationX(answer).translationY(height * -1);
Check out all the available methods in the docs.
Edit/Update :
.translationX(float toX)
means -> animate the view to this point on the x axis.
The animation always starts at the current position of the view, so you don't need a fromX. There are also other methods which you can use :
.translationXBy(float byX)
.translationYBy(float byY)
With these you can translate the view BY the float value, and not TO a certain point on the screen.
Related
I have a spinning wheel, which is an ImageView, in my app, and the animation is working well, but the issue is for just a split second it snaps back to it's original position (0 degree rotation). The .gif below shows what I am talking about.
The last split second of the rotation it has that awkward snap back that makes the animation look extremely unsmooth.
I am looking for a way to fix this but I cannot quite figure it out. This is my code right now that animates the ImageView and rotates it to the final position of the animation
ImageView readyButton = findViewById(R.id.spinnerready);
final ImageView spinnerSpin = findViewById(R.id.spinnerspin);
final Animation animRotate = new RotateAnimation(ROTATE_FROM, ROTATE_TO, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
animRotate.setDuration(5000);
animRotate.setRepeatCount(0);
readyButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
float newDeg = ROTATE_TO;
spinnerSpin.startAnimation(animRotate);
spinnerSpin.postDelayed(new Runnable() {
#Override
public void run() {
spinnerSpin.setRotation(ROTATE_TO);
}
}, 5000);
while(newDeg > 360) {
newDeg = newDeg - 360;
}
}
});
I have also tried changing the delay of the rotation to 4500 instead of 5000 but the issue is not fixed. Is there a way to eliminate the ImageView from going back to its original position after the animation?
I'm writing a simple app that implements a material design compliant nav drawer as described by this Stack post: https://stackoverflow.com/a/27153313/1621380
The ScrimInsetsFrameLayout works great and everything is dandy until I attempt to programmatically change the color of the status bar. My app uses the Palette API to change the toolbar and status bar color dynamically.
I'm using the property animation api to animate the toolbar and it works great! but I try to do the same animation on the statusbar and it doesn't seem to want to animate. Here's an example
Here is the code for my animator:
public static void fadeStatusBar(final DrawerLayout layout, Integer from, Integer to) {
if(android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
ValueAnimator colorAnimation = ValueAnimator.ofObject(new ArgbEvaluator(), from, to);
colorAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator animator) {
layout.setStatusBarBackgroundColor((Integer) animator.getAnimatedValue());
}
});
colorAnimation.start();
}
}
Note: That same code is fading the toolbar, so its proven to work.
My question is; does anyone know of a way to get a smooth transition when using DrawerLayout.setStatusBarBackgorundColour()?
Note: I have used the Window method window.setStatusBarColor() method, and it animates fine but breaks the "transparent statusbar" when the NavDrawer is pulled in.
As advised #adneal's comment on my original question the answer was to invalidate the view during the animation.
DrawerLayout calculates the top inset and draws the status bar background itself. So, you just need to make a call to View.invalidate to force it to redraw while the animation is being updated. #adneal
I've updated my code to this
ValueAnimator colorAnimation = ValueAnimator.ofArgb(from, to);
colorAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator animator) {
layout.invalidate();
layout.setStatusBarBackgroundColor((Integer) animator.getAnimatedValue());
}
});
colorAnimation.start();
For anyone wondering why this worked, I found this stack post enlightening: When it's necessary to execute invalidate() on a View?
you can do this Easily like below:
1 - set your statusbar color to transparent by using this:
<item name="colorPrimaryDark">#android:color/transparent</item>
2 - define application's view to change it background:
View root = *A_view_on_the_activity*.getRootView();
3 - then add this function to your project:
private void color_change(final View view,int from_color,int to_color){
final float[] from = new float[3],
to = new float[3];
String hexColor_from = String.format("#%06X", (0xFFFFFF & from_color));
String hexColor_to = String.format("#%06X", (0xFFFFFF & to_color));
Color.colorToHSV(Color.parseColor(hexColor_from), from); // from
Color.colorToHSV(Color.parseColor(hexColor_to), to); // to
ValueAnimator anim = ValueAnimator.ofFloat(0, 1); // animate from 0 to 1
anim.setDuration(600); // for 300 ms
final float[] hsv = new float[3]; // transition color
anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener(){
#Override public void onAnimationUpdate(ValueAnimator animation) {
// Transition along each axis of HSV (hue, saturation, value)
hsv[0] = from[0] + (to[0] - from[0])*animation.getAnimatedFraction();
hsv[1] = from[1] + (to[1] - from[1])*animation.getAnimatedFraction();
hsv[2] = from[2] + (to[2] - from[2])*animation.getAnimatedFraction();
view.setBackgroundColor(Color.HSVToColor(hsv));
}
});
anim.start();
}
4 - and then change the hole application's background color animation by using the function that Written above:
color_change(root, from_color, to_color);
I have a button that I want to put on a 45 degree angle. For some reason I can't get this to work.
Can someone please provide the code to accomplish this?
API 11 added a setRotation() method to all views.
You could create an animation and apply it to your button view. For example:
// Locate view
ImageView diskView = (ImageView) findViewById(R.id.imageView3);
// Create an animation instance
Animation an = new RotateAnimation(0.0f, 360.0f, pivotX, pivotY);
// Set the animation's parameters
an.setDuration(10000); // duration in ms
an.setRepeatCount(0); // -1 = infinite repeated
an.setRepeatMode(Animation.REVERSE); // reverses each repeat
an.setFillAfter(true); // keep rotation after animation
// Aply animation to image view
diskView.setAnimation(an);
Extend the TextView class and override the onDraw() method. Make sure the parent view is large enough to handle the rotated button without clipping it.
#Override
protected void onDraw(Canvas canvas) {
canvas.save();
canvas.rotate(45,<appropriate x pivot value>,<appropriate y pivot value>);
super.onDraw(canvas);
canvas.restore();
}
I just used the simple line in my code and it works :
myCusstomView.setRotation(45);
Hope it works for you.
One line in XML
<View
android:rotation="45"
... />
Applying a rotation animation (without duration, thus no animation effect) is a simpler solution than either calling View.setRotation() or override View.onDraw method.
// substitude deltaDegrees for whatever you want
RotateAnimation rotate = new RotateAnimation(0f, deltaDegrees,
Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
// prevents View from restoring to original direction.
rotate.setFillAfter(true);
someButton.startAnimation(rotate);
Rotating view with rotate() will not affect your view's measured size. As result, rotated view be clipped or not fit into the parent layout. This library fixes it though:
https://github.com/rongi/rotate-layout
Joininig #Rudi's and #Pete's answers. I have created an RotateAnimation that keeps buttons functionality also after rotation.
setRotation() method preserves buttons functionality.
Code Sample:
Animation an = new RotateAnimation(0.0f, 180.0f, mainLayout.getWidth()/2, mainLayout.getHeight()/2);
an.setDuration(1000);
an.setRepeatCount(0);
an.setFillAfter(false); // DO NOT keep rotation after animation
an.setFillEnabled(true); // Make smooth ending of Animation
an.setAnimationListener(new AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {}
#Override
public void onAnimationRepeat(Animation animation) {}
#Override
public void onAnimationEnd(Animation animation) {
mainLayout.setRotation(180.0f); // Make instant rotation when Animation is finished
}
});
mainLayout.startAnimation(an);
mainLayout is a (LinearLayout) field
As mentioned before, the easiest way it to use rotation available since API 11:
android:rotation="90" // in XML layout
view.rotation = 90f // programatically
You can also change pivot of rotation, which is by default set to center of the view. This needs to be changed programatically:
// top left
view.pivotX = 0f
view.pivotY = 0f
// bottom right
view.pivotX = width.toFloat()
view.pivotY = height.toFloat()
...
In Activity's onCreate() or Fragment's onCreateView(...) width and height are equal to 0, because the view wasn't measured yet. You can access it simply by using doOnPreDraw extension from Android KTX, i.e.:
view.apply {
doOnPreDraw {
pivotX = width.toFloat()
pivotY = height.toFloat()
}
}
if you wish to make it dynamically with an animation:
view.animate()
.rotation(180)
.start();
THATS IT
#Ichorus's answer is correct for views, but if you want to draw rotated rectangles or text, you can do the following in your onDraw (or onDispatchDraw) callback for your view:
(note that theta is the angle from the x axis of the desired rotation, pivot is the Point that represents the point around which we want the rectangle to rotate, and horizontalRect is the rect's position "before" it was rotated)
canvas.save();
canvas.rotate(theta, pivot.x, pivot.y);
canvas.drawRect(horizontalRect, paint);
canvas.restore();
fun rotateArrow(view: View): Boolean {
return if (view.rotation == 0F) {
view.animate().setDuration(200).rotation(180F)
true
} else {
view.animate().setDuration(200).rotation(0F)
false
}
}
That's simple,
in Java
your_component.setRotation(15);
or
your_component.setRotation(295.18f);
in XML
<Button android:rotation="15" />
I have one big problem. I use this code to animate ImageView to horizontal move one ImageView from current X position to 0.
Here is the animation code
translate = new TranslateAnimation(0, translateX, 0, 0);
translate.setDuration(400);
translate.setAnimationListener(new AnimationListener() {
public void onAnimationEnd(Animation animation) {
txtTitle.setText(String.format("Translate: %d %d", translateX, lpView1.leftMargin));
lpView1.leftMargin = 0;
mainSwitchBtn.setLayoutParams(lpView1);
}
public void onAnimationRepeat(Animation animation) {
}
public void onAnimationStart(Animation animation) {
}
});
translate.reset();
translate.setFillAfter(false);
mainSwitchBtn.clearAnimation();
mainSwitchBtn.startAnimation(translate);
When animation is ended, I have moved ImageView to 0. At that I see flicker of ImageView. I do not know what is a problem. Can some one help me?
EDIT: Founded Problem
I have founded what is a problem in my code.
I have replaced this code
mainSwitchBtn.setLayoutParams(lpView1);
With this
mainSwitchBtn.layout(0, 0, 0, 0);
I do not know what is a difference between setting margins in layout params and set params to view object or use .layout function but now I have not flickering.
It seems like animation ends and your imageview returning to original non-animated image, maybe you should try to use HorizontalScrollView instead of animation
I have a linearLayout that disappears when I hit a button, it comes back when I press the button again. But it does it so fast, it doesn't look nice.
I do this via:
disappearView.setVisibility(View.GONE);
I would like to add some animation... If I just set visibity to invisible the space where the layout was is still there. So I tried this:
if (disappearView.getVisibility() == View.VISIBLE){
Animation out = AnimationUtils.makeOutAnimation(this, true);
disappearView.startAnimation(out);
disappearView.setVisibility(View.INVISIBLE);
disappearView.setVisibility(View.GONE);
}
else {
Animation in = AnimationUtils.loadAnimation(this, android.R.anim.fade_in);
disappearView.startAnimation(in);
disappearView.setVisibility(View.VISIBLE);
}
This does the animation too fast and disappears. You can't see it at all. Do I need to use a thread to start gone after invisible is set...or a delay? Or is there a better way of doing all this?
I'm not sure exactly what you're trying to accomplish...do you want the LinearLayout to fade out over a little bit of time rather than instantly disappear? And then once it fades out be removed from the parent via View.GONE?
If so, you can use an AlphaAnimation for the fade out and then attach a listener like EvZ posted:
AlphaAnimation fadeOutAnimation = new AlphaAnimation(1, 0); // start alpha, end alpha
fadeOutAnimation.setDuration(1000); // time for animation in milliseconds
fadeOutAnimation.setFillAfter(true); // make the transformation persist
fadeOutAnimation.setAnimationListener(new AnimationListener() {
#Override
public void onAnimationEnd(Animation animation) {
linearLayout.setVisibility(View.GONE);
}
#Override
public void onAnimationRepeat(Animation animation) { }
#Override
public void onAnimationStart(Animation animation) { }
});
linearLayout.setAnimation(fadeOutAnimation);
You can try to use onAnimationEnd : Animation.AnimationListener