3

Is there a way to force an android view to redraw it's background? I have set a drawable shape with a gradient as background which works fine but after changing the view's height you can see those ugly gradient steps.

What can I do? I tried view.invalidate() and view.refreshDrawableState() without any visible difference.

Thank you!

//EDIT: Here are some more details and my code: After your answers I think the banding is a result of my probably bad code. Here is what I'm doing:

  1. Scaling a view
  2. setting its new width and height because the scaled view does not accept user input in other areas then the "old" one (see android weird (at least for me) behaviour of control after scaling / doesn't accept input in it's whole area )
  3. trying to set the background again (which contains a gradient and a rectangle with rounded corners)

Here is my code:

public void onAnimationEnd(Animation animation)
{
    MyView view = (MyView) ((ExtendedScaleAnimation) animation).getView();
    view.getLayoutParams().width = toWidth;
    view.getLayoutParams().height = toHeight;
    view.clearAnimation();
    view.requestLayout();
    view.refreshBackground(); // background will be changed
}

On the device you can see that the background drawable is changed but there is a flickering which seems to me like the backround change is applied before the animation is over. Programatically it should be over! Or am I wrong?

Thank you again!

Community
  • 1
  • 1
ShadowMare
  • 2,087
  • 2
  • 25
  • 27
  • 1
    Dithering should solve gradient banding problem, but I don't know how to enable it on a drawable shape in xml. Programmatically, every Drawable has setDither(boolean). – bigstones Jan 20 '11 at 14:44
  • 1
    We'll probably need to see more code. I would think view.invalidate() would work. You could try postInvalidate if you happen to not be on the ui thread. – Nick Campion Jan 20 '11 at 14:44
  • 1
    @bigstones: It's just `android:dither` in XML. I think the problem is not that the view isn't redrawing, it's that past a certain size, the display runs out of color steps, causing visible banding. This can probably be fixed by converting to Bitmap, and changing the color depth (what I've personally done for this problem is just use a relatively tall 9-patch gradient; seems to give better results) but there may be a better way. None that I've found, though. – Kevin Coppock Jan 20 '11 at 15:29
  • Thank you for your fast replies. Im on the UI-Thread. I set dither to true but sadly that did not change the outcome. My gradient is from "#919191" to "#e4e4e4" over 460px max. If I'm trying to only draw that gradient (for testing purposes) it seems fine. So it is probably not the size which causes the problem. – ShadowMare Jan 20 '11 at 15:45

1 Answers1

2

Can you try after resize: v.setBackgroundResource(null); v.setBackgroundResource(...my drawable...);

Lumis
  • 21,517
  • 8
  • 63
  • 67
  • I tried to set the background again, that did not change the problem with the banding. However, I'm doing this at the end of a ScaleAnimation and there is (after setting the background again) a short flickering. I assume it sets the background not in the state after scaling (which it should) but in the state before and the result of that causes the banding. Maybe you can have a look at my code (I've edited the question post). – ShadowMare Jan 20 '11 at 15:54
  • 1
    When you scale up the view in animation the quality deteorates so it is important to have the initial quality the best possible. Have you tried to improve the screen color depth by appliying this code just after super.onCreate(): getWindow().setFormat(PixelFormat.RGBA_8888); ? – Lumis Jan 20 '11 at 16:15
  • Thany you very much! That did the trick with the gradient. It's really smooth now. All that is remaining is the flickering problem but this was not the basic question so I'll mark this as solved. – ShadowMare Jan 20 '11 at 16:24
  • 1
    That is good! I had flickering problems with aniamtion too. Are you using android:fillAfter="true" in your animation XML? I had some strange effects when trying to apply more different transitions at once and had to experiment until I've got a smooth one I liked. – Lumis Jan 20 '11 at 16:35
  • Yes im using fillAfter="true". But the view seems to accept clicks only in its old before-scaling layout so I have to set the new width and height programatically. The flickering is after the animation completed, where it should just replace the old background with the new one. The new one has bigger rounded corners so one should not be able to see a difference when changing the background, BUT for some miliseconds you can see that the bigger corner radius is scaled too until it pops to it's expected apperance. – ShadowMare Jan 20 '11 at 16:45
  • 1
    I guess you are trying to zoom in on an object (view) when clicked, which scales up to its new size. Perhaps you have to take a different apporach here which would be more stable. After you scale your view up, it should be replaced with another view which is set for that proper size. Three is view switcher xml method, or using just smallWew.setVisibility(View.GONE) and then smallViewParent.addView(myBiggerView) method... something like that ;) – Lumis Jan 20 '11 at 17:11
  • You are completely right! I'm trying to avoid removing and adding the view because I would have to rewrite big parts of my logic. However I'll do that if there is no other solution. The unstable part of my approach seems to be the onAnimationEnd which seems to fire a short time before the animation actually finishes. I made a new question for that issue ( http://stackoverflow.com/questions/4750939/android-animation-is-not-finished-in-onanimationend ) Thank you once again, you helped me a lot! – ShadowMare Jan 20 '11 at 18:27