I have a FAB on a KitKat device using support library 23. I'm scaling the button for a transition effect (by containing it in a resizing view). This basically works apart from the shadow, which appears in a weird form (see the scaled red button in the screenshot, the blue button is full size).
What actually appears to happen is that the shadow is in 4 "corner" bitmaps that overlap to produce an odd effect.
Does anyone know how this can be fixed?
This looks interesting!
Unfortunately, I didn't succeed trying to reproduce the issue on - it'd be nice, if you can provide the code you run - but here's the code I wrote to animate&scale floating action button like this:
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.animate().scaleX(0.1f).scaleY(0.1f).setDuration(100).setListener(
new Animator.AnimatorListener() {
#Override
public void onAnimationStart(Animator animator) {}
#Override
public void onAnimationEnd(Animator animator) {
fab.setBackgroundTintList(getResources().getColorStateList(R.color.colorPrimary, getTheme()));
fab.setImageDrawable(getResources().getDrawable(R.drawable.common_full_open_on_phone, getTheme()));
fab.animate().scaleX(2).scaleY(2).setListener(null).setDuration(200).start();
}
#Override
public void onAnimationCancel(Animator animator) {}
#Override
public void onAnimationRepeat(Animator animator) {}
}).start();
Of course, particular animation speed and effects can be adjusted and improved.
I hope, it helps.
Use scale properties to resize your floating button. And shadow will be fine
<android.support.design.widget.FloatingActionButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleType="center"
android:scaleX="0.75"
android:scaleY="0.75"/>
Related
I am building an app using Android Studio, and I cannot figure out how to approach this issue I am facing.
I have a recyclerview that takes up about two-thirds of the lower half of the screen. Above it are three other elements. I need those elements to disappear when the recyclerview gets scrolled, and I need the recyclerview to scale up to fill the entire screen. I have found ways to do this, but they all cause the items inside of the recyclerview to scale up as well, distorting them.
Use this implementation:-
recyclerview.addOnScrollListener(new HidingScrollListener()
{
#Override
public void onHide()
{
tabss.animate().translationY(tabss.getHeight())
.setInterpolator(new AccelerateInterpolator(2)).start();
filtershow.animate().translationY(-filtershow.getHeight())
.setInterpolator(new AccelerateInterpolator(1));
}
#Override
public void onShow()
{
tabss.animate().translationY(0).setInterpolator(new
DecelerateInterpolator(2)).start();
filtershow.animate().translationY(0).setInterpolator
(new DecelerateInterpolator(1)).start();
}
});
What I'm trying to achieve
I have a group of buttons in a GridLayout. One of the buttons toggles the function of the other buttons between rounding up and rounding down.
I am trying to implement an animation that changes the color of the buttons in a ripple like effect. The circular reveal animation is the effect I want where the new colour spreads from the touch point on the toggling button to the rest of the other buttons. I only want the animation to grow outward from the touch point in both cases, switching from rounding up to rounding down and back.
Problem
The animation is only working in the first instance from rounding up to rounding down (my app starts with rounding up as the default). There is no animation when switching from rounding down back to rounding up; all the buttons just changes in colour and the toggle button changes icon.
This is my first app so I am having difficulty trying to work out where I've gone wrong.
My methodology and code
In my activity_main.xml layout file, I've created two sets of GridLayouts (each with child buttons) and layered them one on top of the other by wrapping both in a FrameLayout. One set is given a different colour to the other set; I also have a different icon for the toggling button for each set to differentiate between the two rounding method. I've set the visibility attribute on the second GridLayout parent to invisible.
<FrameLayout
<GridLayout
android:id="#+id/roundUp"
<ImageButton
android:id="#+id/buttonU1"
... />
<Button ... />
<Button ... />
</GridLayout>
<GridLayout
android:id="#+id/roundDown"
android:visibility="invisible"
<ImageButton
android:id="#+id/buttonD1"
... />
<Button ... />
<Button ... />
</GridLayout>
</FrameLayout>
In my MainActivity.java file:
import ...
boolean roundingMode;
public class MainActivity extends AppCompatActivity {
GridLayout roundUp, roundDown;
ImageButton buttonU1, buttonD1;
Button ...
#Override;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
roundUp = (GridLayout) findViewById(R.id.roundUp);
buttonU1 = (ImageButton) findViewById(R.id.buttonU1);
roundDown = (GridLayout) findViewById(R.id.roundDown);
buttonD1 = (ImageButton) findViewById(R.id.buttonD1);
roundingMode = true;
buttonU1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
buttonCircularRevealAnim(roundDown);
roundingMode = false;
}
});
buttonD1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
buttonCircularRevealAnim(roundUp);
roundingMode = true;
}
});
}
public void buttonCircularRevealAnim(View view) {
int originX = roundUp.getWidth() / 2;
int originY = roundUp.getHeight() / 2;
float finalRadius = (float) Math.hypot(originX,originY);
Animator anim;
if (roundingMode) {
anim = ViewAnimationUtils.createCircularReveal(roundDown, originX, originY, 0, finalRadius);
roundDown.setVisibility(View.VISIBLE);
anim.start();
anim.addListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
roundUp.setVisibility(View.INVISIBLE);
}
});
} else {
anim = ViewAnimationUtils.createCircularReveal(roundUp, originX, originY, 0, finalRadius);
roundUp.setVisibility(View.VISIBLE);
anim.start();
anim.addListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
roundDown.setVisibility(View.INVISIBLE);
}
});
}
}
Ignore the fact that I currently have the origin of the animation in the center of the GridLayout. I just want to get the basics working first.
I think the problem lies in the logic and/or the set up of the animation?
I've tried moving the originX, originY and finalRadius calculations into the if statement and using the roundUp (for roundingMode true) and roundDown GridLayouts (for roundingMode false) but that didn't work - so I figure it doesn't matter if it is invisible (in the scenario where you're switching from rounding down to rounding up).
Eventually understood that the circular reveal animation works to reveal an overlapping view that is initially invisible. So in order to use it to change the colour of a view back and forth you have to apply the new colour (from the revealed view) to the view underneath after the animation has ended and then make the revealed view invisible again with the other colour applied to it.
My original code was trying to reveal the view underneath which is of course impossible.
I found the following page very helpful:
http://myhexaville.com/2016/12/19/keep-your-app-material/
I use view property animator as mentioned below, in android. It works well in most devices but in some it gives above mentioned error. It always fails in emulator as well. Having same issue with object animator as well. Note that animation works if applied on a single view, but not a container with multiple childs. Kindly help
wordViewPropertyAnimator.rotationYBy(-90f).setDuration(resources.getInteger(R.integer.rotateAnimationHalf))
.setListener(new AnimatorListener() {
#Override
public void onAnimationStart(Animator animation) {
}
#Override
public void onAnimationEnd(Animator animation) {
wordViewPropertyAnimator.setListener(null);
wordViewPropertyAnimator.rotationYBy(-180f).setDuration(0).start();
wordViewPropertyAnimator.rotationYBy(-90f).
setDuration(resources.getInteger(R.integer.rotateAnimationHalf)).start();
}
#Override
public void onAnimationCancel(Animator animation) {
}
#Override
public void onAnimationRepeat(Animator animation) {
}
})
.start();
ObjectAnimator objectAnimator=ObjectAnimator.ofFloat(wordView,
View.ROTATION_Y, -90f);
objectAnimator.setDuration(200);
objectAnimator.start();
I know yous asked a while ago and problem don't need this answer anymore but I hope to help someone in the future:
I was having the same problem, tried the objectAnimator on XML and tried also ViewPropertyAnimator to animate my view and both gave the same result, so the solution I found was to change the layout that was applying the animation, I was applying it to a cardView and I simply surrounded it with a FrameLayout and applied the animation into the group view and it worked just fine. I hope it helps somebody in the future.
Looks like a platform issue, they need to fix it in future updates. Just use this library for now http://genzeb.github.io/flip
Actually i am able to create this design by using RotateAnimation but getting problem when i want to change it and applying any animation.We know, Animation does not alter the actual properties of the View, it only animates it. So every time i am facing the issue like :
animation get back to its real state after finishing the animation and
start every time from initial position.
So to avoid this i want to apply static design in xml . I tried using android:rotation but not getting as per the exact requirement.
suggestions and helps will be mostly appreciable. Please suggest.
I know android:fillAfter="true" causes many problems!
Another option would be you could add animation listeners to the animation and once that animation finished, you manually set final transfomrations to the views.
yourAnimation.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
/* Here, you could set them manually */
}
#Override
public void onAnimationRepeat(Animation animation) {
}
});
Once my app reaches ~4+ animations running concurrently, the animations start to lag a little. Are there any ways I could fix/optimize that? I am using ObjectAnimator and ValueAnimator.
So, if the views are not having to redraw themselves during the animations, you can enable hardware layers during the duration of the animations. For instance:
final View myView = // your view
Animator animator = ObjectAnimator.ofFloat(myView, View.ALPHA, 0f, 1f);
animator.setDuration(1000);
animator.addAnimatorListener(new Animator.AnimatorListener() {
#Override
public void onAnimationStart(Animator animator) {
myView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
}
#Override
public void onAnimationCancel(Animator animator) {
myView.setLayerType(View.LAYER_TYPE_NONE, null);
}
#Override
public void onAnimationEnd(Animator animator) {
// See http://stackoverflow.com/a/19615205/321697
myView.post(new Runnable() {
#Override
public void run() {
myView.setLayerType(View.LAYER_TYPE_NONE, null);
}
}
}
}
animator.start();
I'd suggest breaking that listener implementation out into a separate class, but the general idea is that you want to put the view into a hardware backed layer as soon as the animation starts (animation properties such as translation, rotation, scale, and alpha are incredibly cheap when backed by a hardware layer) and then clear the layer once the animation is complete.
In the onAnimationEnd callback, you'll notice a link to another answer where there's a bug with 4.0.x if you set the layer type to none in the onAnimationEnd callback. If you're only supporting 4.1 and above, the runnable indirection shouldn't be necessary.
EDIT: If you're animating a color transition, you probably don't want to do the above, as changing the color of the view will require it to be redrawn, causing it to rebuild the hardware layer on each frame.
If you have not used ViewPropertyAnimator, you better do. I moved and flipped(changed picture) 52 imageViews (one deck of playing cards) smoothly.
Here's an example on how to use ViewPropertyAnimator.