Android 背景中的颜色 "flowing"

Colors "flowing" in Android background

我有一个应用程序,我想设置它的背景,就像 Instagram 的登录页面一样,那个 "gradient colors"。颜色是 "moving" 并且它创造了一个很酷的效果。这是我到目前为止尝试过的:

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(">");
        }
    }

但这行不通。发生的事情是颜色没有改变,它保持黑色直到它到达最后一个 if 然后背景变成白色和黄色(分别是颜色 0xffffffff 和 0xffffff00),呈渐变形状。 那么,我该怎么做呢?我不在乎它是怎么做到的。无论是使用 GradientDrawable 还是使用动画 gif 作为背景(不起作用,gif 保持静止)或任何其他方式。谢谢。 (This is what I want, the gif isn't that good but you can see how the background is changing it's color)

您可以通过编程方式创建随时间改变渐变级别的内容,但这需要一些努力。或者,您可以使用 TransitionDrawable 在不同的渐变之间淡入淡出,这应该会产生类似的效果。

可以这样实现:

<?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>

然后,您可以在代码中激活转换,如下所示:

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

显然,您可能需要花一些时间让它看起来像您想要的样子,但这比硬编码过渡算法要容易得多!





下面的完整和工作代码

所以,我实现了我的想法,它看起来棒极了!我没想到会这么好看,但真的很酷。我很无聊,所以决定将整个事情都推到一个函数中,这样您(和其他人)就可以更轻松地使用它。

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

此处的主要功能是创建一个新线程,该线程将自动开始来回移动两个图像。一旦完成一个完整的过渡,它将开始淡入原始图像。大多数情况下,它会产生非常平滑和流动的效果,但在组合一些渐变可绘制对象时可能看起来很奇怪。该函数如下所示:

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

1) final ImageView image

第一个参数应该是要代表您的背景的图像对象。

2) final Drawable layers[]

第二个参数接受一个可绘制对象数组,它应该是像我上面显示的那样的两个图像。使用不同的渐变图像很有趣,观察颜色如何“流动”也很有趣。不过,请注意您的图像尺寸,因为我最初使用的是大量图像,这些图像会使应用程序崩溃或在动画过程中卡顿得很厉害。

3) final int speedInMs

最后一个参数仅表示从第一个可绘制对象完全过渡到第二个可绘制对象所需的时间(以毫秒为单位)。

这是这两张图片以 5000 毫秒的速度交叉淡入淡出的结果的 GIF(注意:我无法在此处放置 10 秒的 GIF 来显示整个过渡,但它非常流畅!):

Github Link To Repository

编辑 2: 我更新了 Github 和此处的函数,但我只是添加了多绘图支持,因此任意数量的图像数组都可以被添加进来,它将按时间顺序循环通过它们,直到到达终点,此时它将倒转并重复。性感。