Colors "flowing" in Android background

1

I have an application and I want to set it's background just like the Instagram's login page, the one with that "gradient colors". The colors are "moving" and it creats a cool effect. This is what I've tried so far:

protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_take_one);
        colorFul = (RelativeLayout) findViewById(R.id.background);
        GradientDrawable gd = new GradientDrawable(GradientDrawable.Orientation.TL_BR, new int[] {a,b});
        gd.setCornerRadius(0f);
        colorFul.setBackgroundDrawable(gd);
        for(int i = 0; i<6; i++){
            if(a == 0xff000000){
                a = 0xff00ffff;
                b = 0xff444444;
            }else if(a == 0xff00ffff){
                a = 0xff888888;
                b = 0xff00ff00;
            }else if(a == 0xff888888){
                a = 0xffcccccc;
                b = 0xffff00ff;
            }else if(a==0xffcccccc){
                a = 0xffff0000;
                b = 0xffffffff;
            }else if(a==0xffff0000){
                a = 0xffffffff;
                b = 0xffffff00;
            }
            System.out.println("||");
            SystemClock.sleep(1000);
            System.out.println(">");
        }
    }

But this doesn't work. What happens is that the collors don't change, it remains black until it gets to the last if and then the background become white and yellow(that are, respectively, the collors 0xffffffff and 0xffffff00), in gradient shape. So, how can I do it? I don't care how it's done. Whether it is with GradientDrawable or using an animated gif as background(which didn't work, the gif remained still) or any other way. Thanks. (This is what I want, the gif isn't that good but you can see how the background is changing it's color)

android
colors
instagram
gradient

1 Answer

3

You could programmatically create something that changes the level of gradient over time, but that would require some effort. Alternatively, you could use a TransitionDrawable to fade between different gradients, which should produce a similar effect.

This can be implemented as follows:

<?xml version="1.0" encoding="UTF-8"?>
<transition xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- use two gradients, extending from opposite sides of the page-->
    <item android:drawable="@drawable/gradientLeft" />
    <item android:drawable="@drawable/gradientRight" />
</transition>

Then, you can activate the transition in code as follows:

TransitionDrawable transition = (TransitionDrawable) myLayout.getBackground();
transition.startTransition(1500);

Obviously you'll probably need to spend some time to get it looking the way you want, but this would be far easier than hard-coding a transitional algorithm!





COMPLETE AND WORKING CODE BELOW

So, I got my idea implemented, and it looks awesome! I didn't expect it would look this nice, but it's really cool. I was bored so decided I would shove the whole thing into a function so it's easier for you (and others) to utilize.

MainActivity.java

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ImageView image = (ImageView) findViewById(R.id.background);

        Drawable backgrounds[] = new Drawable[3];
        backgrounds[0] = ContextCompat.getDrawable(this, R.drawable.gradient1);
        backgrounds[1] = ContextCompat.getDrawable(this, R.drawable.gradient2);
        backgrounds[2] = ContextCompat.getDrawable(this, R.drawable.gradient3);

        Crossfade(image, backgrounds, 10000);
    }

    public void Crossfade(final ImageView image, final Drawable layers[], final int speedInMs) {
        class BackgroundGradientThread implements Runnable {
            Context mainContext;
            TransitionDrawable crossFader;
            boolean first = true;

            BackgroundGradientThread(Context c) {
                mainContext = c;
            }

            public void run() {
                Handler mHandler = new Handler(mainContext.getMainLooper());
                boolean reverse = false;

                while (true) {
                    if (!reverse) {
                        for (int i = 0; i < layers.length - 1; i++) {
                            Drawable tLayers[] = new Drawable[2];
                            tLayers[0] = layers[i];
                            tLayers[1] = layers[i + 1];

                            final TransitionDrawable tCrossFader = new TransitionDrawable(tLayers);
                            tCrossFader.setCrossFadeEnabled(true);

                            Runnable transitionRunnable = new Runnable() {
                                @Override
                                public void run() {
                                    image.setImageDrawable(tCrossFader);
                                    tCrossFader.startTransition(speedInMs);
                                }
                            };

                            mHandler.post(transitionRunnable);

                            try {
                                Thread.sleep(speedInMs);
                            } catch (Exception e) {
                            }
                        }

                        reverse = true;
                    }
                    else if (reverse) {
                        for (int i = layers.length - 1; i > 0; i--) {
                            Drawable tLayers[] = new Drawable[2];
                            tLayers[0] = layers[i];
                            tLayers[1] = layers[i - 1];

                            final TransitionDrawable tCrossFader = new TransitionDrawable(tLayers);
                            tCrossFader.setCrossFadeEnabled(true);

                            Runnable transitionRunnable = new Runnable() {
                                @Override
                                public void run() {
                                    image.setImageDrawable(tCrossFader);
                                    tCrossFader.startTransition(speedInMs);
                                }
                            };

                            mHandler.post(transitionRunnable);

                            try {
                                Thread.sleep(speedInMs);
                            } catch (Exception e) {
                            }
                        }

                        reverse = false;
                    }
                }
            }
        }

        Thread backgroundThread = new Thread(new BackgroundGradientThread(this));
        backgroundThread.start();
    }
}

activity_main.xml

    <?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
    android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">
    <ImageView android:id="@+id/background"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:src="@drawable/gradient2"
        android:scaleType="fitXY"/>
    <TextView android:text="Hello World!" android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
</RelativeLayout>

gradient1/2.jpg
gradient2.jpg gradient1.jpg

The primary function here creates a new thread that will automatically begin shifting the two images back and forth. Once one full transition has completed, it will then begin to fade back into the original image. It creates a really smooth and flowy effect most of the time, but may look weird when combining some gradient drawables. The function looks like this:

public void Crossfade(final ImageView image, final Drawable layers[], final int speedInMs)

1) final ImageView image

The first parameter should be the image object that is going to represent your background.

2) final Drawable layers[]

The second parameter takes an array of drawables, which should be two images like the ones I showed above. Playing around with different gradient images is fun, and quite interesting to watch how colors "flow". Be careful with your image sizes, though, as I had initially used massive images that had crashed the app or stuttered terribly in the animation process.

3) final int speedInMs

The last parameter simply represents the time (in milliseconds) it will take to completely transition from the first drawable to the second.

Here's a GIF of the result of these two images crossfading with a speed of 5000ms (note: I couldn't put a 10 second GIF on here showing the whole transition, but it's quite smooth!):

Super Flowy Colors

Github Link To Repository

EDIT 2: I updated the Github and the function on here, but I just added in multi-drawable support so an array of any number of images can be added in and it will cycle through them chronologically, until reaching the end at which point it will reverse through and repeat. Sexy.

answered on Stack Overflow Mar 6, 2016 by Shane Duffy • edited Jun 20, 2020 by Community

User contributions licensed under CC BY-SA 3.0