Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Animate Status Bar Color on DrawerLayout - Material Design

Tags:

java

android

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

oh no statusbar!

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.

like image 849
Spittal Avatar asked Jan 13 '15 00:01

Spittal


2 Answers

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?

like image 177
Spittal Avatar answered Nov 07 '22 04:11

Spittal


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);
like image 33
Mahdi Astanei Avatar answered Nov 07 '22 06:11

Mahdi Astanei