2

A simple question for you guys with which I've had quite some trouble.

Goal: Have a RelativeLayout with a shape (xml) as background, and when something specific happens, have it fade from transparent to solid red (maintaining the shape), and after that back to transparent again. Seems easy enough, yet I've been unable to reach my goal.

First attempt:

Relativelayout has shape state_ok.xml as background initially:

//state_error.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" >
    <corners android:radius="11dp" />
    <solid android:color="#ffff0000" />
</shape>

//state_ok.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" >
    <corners android:radius="11dp" />
    <solid android:color="#00ff0000" />
</shape>

//MyView with static runnable creator class for easiness's sake.
private static class FadeRunnable implements Runnable {
    final Context ctx; final RelativeLayout layout; final int from, to;
    //of course there's a constructor with these four params

    public void run() {
        Drawable[] color = {
                ctx.getResources().getDrawable(from), 
                ctx.getResources().getDrawable(to)
        };
        TransitionDrawable trans = new TransitionDrawable(color);
        layout.setBackgroundDrawable(trans);
        trans.startTransition(2500);
    }
}

final FadeRunnable in = new FadeRunnable(context, layout, R.drawable.state_error, R.drawable.state_ok);
final FadeRunnable out = new FadeRunnable(context, layout, R.drawable.state_ok, R.drawable.state_error);

Thread fading = new Thread() {
    public void run() {
        MyView.this.context.runOnUiThread(in);
        Thread.sleep(2500);
        MyView.this.context.runOnUiThread(out);
    }
};
fading.start();

Outcome: It instantly becomes red and after 2500ms it instantly becomes transparent and fades to solid red. I can't wrap my head around it.

Second Attempt: using Animations

final Runnable inRunnable = new Runnable() {
    @Override
    public void run() {
        Animation inAnim = AnimationUtils.loadAnimation(context, R.anim.fadein);
        layout.startAnimation(inAnim);
    }
};
final Runnable outRunnable = new Runnable() {
    @Override
    public void run() {
        Animation inAnim = AnimationUtils.loadAnimation(context, R.anim.fadeout);
        layout.startAnimation(inAnim);
    }
};
new Thread() {
    public void run() { 
        context.runOnUiThread(inRunnable);
        CommonToolkit.sleep(2500);
        context.runOnUiThread(outRunnable);
    }
}.start();

Outcome: the contents of the layout are made opaque and transparent again, not the background of itself.

Other Attempts

After that I tried something with a ValueAnimator, but that didn't work either.

Then I tried changing background colors (with for loop and setBackgroundColor(int color)), but that way the shape isn't maintained (and I think it's overkill to make 256 drawables with a different color).

Question:
How can I change the color from a View from #00ff0000 to #ffff0000 and back to transparent red again while maintaining the shape xml background?

sources:
How to Apply Corner Radius to LinearLayout
Fade animation blinks - Android
Animate change of view background color on Android
How to reference colour attribute in drawable?
android: Animate color change from color to color
animation fade in and out
In Android, how do I smoothly fade the background from one color to another? (How to use threads)

PS:
When I use code below, the it keeps looping: it fades from transparent to RED, then instantly transparent again, etc, however, I don't have a while true loop, so I have no clue how this is possible. I removed the background entry from the layout from the xml.

Thread forThread = new Thread() {
    public void run() {
        for (int i = 0; i < 256; i++) {
            final int j = i;
            context.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    layout.setBackgroundColor(Color.argb(j, 0xff, 0, 0));
                }
            });
            CommonToolkit.sleep(10);
        }
        for (int k = 255; k > -1; k++) {
            final int l = k;
            context.runOnUiThread(new Runnable() { 
                @Override
                public void run() {
                    layout.setBackgroundColor(Color.argb(l, 0xff, 0, 0));
                }
            });
            CommonToolkit.sleep(10);
        }
    }
};
forThread.start();
Community
  • 1
  • 1
stealthjong
  • 10,858
  • 13
  • 45
  • 84

2 Answers2

3

make 2 drawable xmls with red and transparent color. (layout_bg_red, layout_bg_trans). create another drawable "my_layout_transition" as:

<?xml version="1.0" encoding="UTF-8"?>
<transition xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/state_ok" />
    <item android:drawable="@drawable/state_error" />
</transition>

assign this transition xml as background for view you want.

add these 2 methods to activity:

public void startTransition(int millis, View v) {
    if (v.getBackground() instanceof TransitionDrawable) {
        TransitionDrawable d = (TransitionDrawable)v.getBackground();
        d.startTransition(millis);
    }
}

public void reverseTransition(int millis, View v) {
    if (v.getBackground() instanceof TransitionDrawable) {
        TransitionDrawable d = (TransitionDrawable)v.getBackground();
        d.reverseTransition(millis);
    }
}

and then call startTransition(500, myLayoutView) and reverseTransition(500, myLayoutView);

example for start then reverse transition:

public void startAndReverseTransition(final int millis, final View v) {
    if (v.getBackground() instanceof TransitionDrawable) {
        final TransitionDrawable d = (TransitionDrawable)v.getBackground();
        d.startTransition(millis);
        v.postDelayed(new Runnable() {
            @Override
            public void run() {
                d.reverseTransition(millis);
            }
        }, millis);
    }    
}
Autocrab
  • 3,474
  • 1
  • 15
  • 15
  • I tried this method as well. Problem: when I implement it as described, it does not fade from transparent to red, it's instantly red. – stealthjong Dec 23 '13 at 11:31
  • Include `handler.postdelayed(Runnable, time)` for the reverse in your answer and it might just work. However, when I call startTransition on a View which has already started a transition, it ends in the final state (red). – stealthjong Dec 23 '13 at 13:33
0

Try this : transparent.xml:

<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<corners android:radius="11dp" />
<solid android:color="#00000000" />

</shape>

red.xml

<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<corners android:radius="11dp" />
<solid android:color="#FF0000" /></shape>

bg_translate.xml

<transition xmlns:android="http://schemas.android.com/apk/res/android" >

<item android:drawable="@drawable/transparent"/>
<item android:drawable="@drawable/red"/></transition>

Set bg_translate.xml as background android:background="@drawable/bg_translate" now in code change backgroumd color:

TransitionDrawable transition = (TransitionDrawable) v.getBackground(); transition.startTransition(time);

and reverse it using

transition.reverseTransition(time);

time is fade time in miliseconds

Jaiprakash Soni
  • 4,100
  • 5
  • 36
  • 67