Search code examples
androidandroid-recyclerviewandroid-animationandroid-coordinatorlayout

View color transition onScroll in Android


I am trying to transition few of my view colors from 'color1' to 'color2' on up scroll and vice versa on down scroll.

The views are inside a CoordinateLayout and Scroll Listener implementation is inside a Custom Behaviour.

Current implementation UpScroll:

    int balanceLabelTextColor = Color.rgb(
            (int) (Color.red(color1) * magicFactor),
            (int) (Color.green(color1) * magicFactor),
            (int) (Color.blue(color1) * magicFactor)
    );
    balanceLabel.setTextColor(balanceLabelTextColor);

Current implementation DownScroll:

    int balanceLabelTextColor = Color.rgb(
            (int) (Color.red(color2) * magicFactor),
            (int) (Color.green(color2) * magicFactor),
            (int) (Color.blue(color2) * magicFactor)
    );
    balanceLabel.setTextColor(balanceLabelTextColor);

'magicFactor' takes value from (0,1) depending on scroll position.

This works fine when you only scroll up or down. The transition flip flops when you change the direction of scroll midway from up to down and vice versa.

Was looking for an implementation which takes both 'color1' and 'color2' and produce intermediate values for a smooth color transition.

Thanks.


Solution

  • Sounds like you're looking for something like ColorUtils.blendARGB.

    Blend between two ARGB colors using the given ratio.

    A blend ratio of 0.0 will result in color1, 0.5 will give an even blend, 1.0 will result in color2.

    @ColorInt
    public static int blendARGB(@ColorInt int color1, @ColorInt int color2,
            @FloatRange(from = 0.0, to = 1.0) float ratio) {
        final float inverseRatio = 1 - ratio;
        float a = Color.alpha(color1) * inverseRatio + Color.alpha(color2) * ratio;
        float r = Color.red(color1) * inverseRatio + Color.red(color2) * ratio;
        float g = Color.green(color1) * inverseRatio + Color.green(color2) * ratio;
        float b = Color.blue(color1) * inverseRatio + Color.blue(color2) * ratio;
        return Color.argb((int) a, (int) r, (int) g, (int) b);
    }