Is it possible to dither a gradient drawable? - android

I'm using the following drawable:
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle"
>
<gradient
android:startColor="#color/content_background_gradient_start"
android:endColor="#color/content_background_gradient_end"
android:angle="270"
/>
</shape>
The problem is that I get severe banding on hdpi devices (like the Nexus One and Droid) since the gradient goes from the top of the screen to the very bottom.
According to http://idunnolol.com/android/drawables.html#shape_gradient there isn't a "dither" attribute for a gradient. Is there anything I can do to smooth the gradient?
Note: adding dither="true" to shape doesn't seem to work.

I wrote the documentation you referenced. I've taken another look at the code and unfortunately there's no way to enable dithering on a GradientDrawable except by explicitly calling GradientDrawable.setDither() in code.
(The way the codes looks, technically you could include the Gradient as the only child of a <selector>, and enable dithering on the entire selector; however, it's definitely a hack.)
I'm not convinced enabling dithering will actually solve your problem, as dithering (at least as it's noted in the official Android docs) are for solving banding problems when the device has too small of a color palette. This seems to be a banding problem due to the size of the gradient.

Hi all i have the same problem, there is one solution which works but it's not very good.
getWindow().setFormat(PixelFormat.RGBA_8888);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_DITHER);
It works for me but the problem is that the whole windows is dithered. I was looking to find a way to dither only the gradient but i couldn't find anything. android:dither="true" in xml is not working and GradientDrawable.setDither(true) is also not working. So any ideas how can i dither only the gradient ?

I faced a very similar problem last year and came to no useful conclusion on the android-developers list.
However, a while ago I discovered — after trying <gradient> and all sorts of Drawables with various dither attributes and manually creating dithered PNGs — that if I manually create a new image using GIMP, and specify the density at this point (i.e. explicitly entering 120, or 240 etc) when creating the image, it looks great, even on hdpi devices. And this is despite it being a grayscale gradient, with not so many colours.
The PNG when saved ends up being comparatively large (at least for 240dpi), but it looks great.

Related

creating a gradient with certain effects in android

I understand how to create gradients using start color, end color, etc like below:-
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<gradient
android:type="radial" android:gradientRadius="260"
android:startColor="#A74171" android:endColor="#690136"/>
</shape>
But I dont understand how to bring about more complex effects. For Eg:- I am faced with a task of making a textview look like a button where it will look a little raised at the center, something like the image attached .
How can such an effect be brought by code without using images?
Here's the good news: Something like the button, shown in the picture, already exists. Maybe in other colors, but with a little painting you should get there easily. Check out the design downloads
When there're good news, than there might be some news with - lets say - more work involved. This link to Drawable Resource gives you an overview of what is possible with XML.
When you get out of XML possibilities, you must create your own Drawable, which is described here which is extremely powerful.
You can always paint your own drawings, load them as bitmap and use them. There you must be very sensitive on the size of the bitmap and the good looking (painted with enough pixels). I mysef have not found the right mix up to now.
All in all, in my experience, even the most complex XML drawables are quite efficient, whereas my own Drawables, painted at runtime are always a cause for lagging on the UI-Thread.

Nine-Patch Drawable vs Shape Drawable. Which should be preferred?

My co-worker and I developed two apps in parallel, each with similar styling. The main view background of these apps is a radial gradient. He implemented his as a nine-patch image and I did it with a shape drawable. Both generate similar and acceptable results.
So my question is, which should we use? Are there are trade-offs between memory consumption and performance? I imagine that the image could take time to load, but that the shape drawable takes more time to draw (due to calculations). Are these then stored in a cache and those penalties only happen the first time they are displayed or are these issues on-going???
Shape Drawable:
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<gradient
android:startColor="#003472"
android:endColor="#000034"
android:gradientRadius="350"
android:type="radial"/>
</shape>
Nine Patch:
Shape drawable is great for gradient kind of images with simple constant color changes.
On the other hand, 9-patch images are great for images with lots of detail, constant color in streching regions.
Was just bumping into this problem earlier.
DO NOT USE SHAPE IN XML IF YOU HAVE ANIMATION THAT INVOLVES IT. The reason is that the caching (especially if you are using hardware acceleration on) will make it really seem "laggy" as the screen will not refresh as often.
Take a look at the answer given by #Ivan Bartsov. But through careful code analysis he concludes that for most general cases, using a 9 patch requires less process uses less memory than generated gradients. Therefore for most cases it's best to use 9 patches.
Take a look at his answer for mode details: What should i use for better performance, nine-patch or drawable xml resource?

Gradient compatibility issue - ICS defaults to fewer colors than all the previous versions of Android

Gingerbread (2.3.3) emulator left, ICS (4.0.3) emulator right. Notice the gradient fade effect difference inside the red box (open in separate window to see the full sized image).
Mainview background:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#drawable/app_bg"
android:orientation="vertical" >
...
</LinearLayout>
app_bg.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<gradient android:startColor="#000" android:centerColor="#333"
android:endColor="#000" android:angle="270" />
</shape>
What is causing this issue? How to fix this, so that the ICS gradient would look as smooth as the 2.3.3 version? Does the problem occur only on emulator?
I think the problem is that android is (on the right) drawing the gradient using fewer colours. I believe you want to enable dithering to help disguise the drop in the color depth. Maybe see this answer link
I'm not totally sure how it works, but I believe android will sometimes default to RGB_565 mode, even if the device is capable of 24bit colors.
ICS automaticly adds gradient effect if hardware acceleration is enabled in application.
It is also possible to force hardware acceleration for all apps, you will notice that some apps will have gradient background, instead of black.
I saw your comment that using PixelFormat.RGBA_8888 didn't help.
You can also try adding the dither flag: window.addFlags(WindowManager.LayoutParams.FLAG_DITHER);.
You can see my previous related answer about dithering and colours here:
Awful background image quality in Android
Just verified on ICS 4.0.3 device: this is emulator ONLY problem.

How to determine appropriate dimensions for ExpandableListView groupIndicator icons?

I'm working on an app that involves and ExpandableListView. We should like to replace the groupIndicator with one of our own choosing.
I created a spec for the indicator that would show a different png depending on the state of the selector (expanded or not expanded)
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/arrow_down" android:state_expanded="true"/>
<item android:drawable="#drawable/arrow_right"/>
</selector>
I then set up my layout xml to use:
(Note that childDivider is a one pixel tall png rather than a color because setting that to a color seems to be bugged)
This works, except that our icon is stretched out vertically. That makes sense, because we just created a 25x25 icon and hoped for the best. I'm trying to figure out the dimensions of the native icon so that I can match it, but that's where I run into trouble.
Digging through the source code (ExpandableListView.java) I found that, by default, the class will use com.android.internal.R.styleable.ExpandableListView_groupIndicator. So I have an id, but no icon yet.
I'd love to be able to do:
Bitmap image = BitmapFactory.decodeResource(this.getResources(), com.android.internal.R.styleable.ExpandableListView_groupIndicator);
imWidth = image.getWidth();
imHeight = image.getHeight();
But as the "internal" suggests, it's not visible to me in user space.
I also found getIndicate() in ExpandableListView.java, but it is private, so I can't get to that either.
I'm quite new to diving into the platform source code, and I don't know how else to track down that image. Can anyone help me out?
Edit: Thanks CommonsWare. To spell out the rest for anyone else looking:
android:drawable/expander_group is defined in /frameworks/base/core/res/res/drawable/expander_group.xml.
expander_group.xml mentions that it uses #drawable/expander_ic_maximized and #drawable/expander_ic_minimized.
Those drawables can be found in /frameworks/base/core/res/res/drawable/expander_ic_maximized.9.png and /frameworks/base/core/res/res/drawable/expander_ic_minimized.9.png, among other places for specific densities and such. The "9" explains why the default icons don't have distortion problems - they're patch-9 graphics. The density-agnostic versions of the icons are 34px by 38px.
base.git's core/res/res/values/styles.xml defines com.android.internal.R.styleable.ExpandableListView_groupIndicator as android:drawable/expander_group. That is a StateListDrawable in your SDK's copy of the resources. The underlying PNGs are of varying sizes based upon density.

Creating Nine (9) Patch png files with Gradients

I want to create a nine patch button background with a gradient for my android app. I was wondering how gradients work. I would think that the os would have to figure out how to apply the gradient as the button stretched and I'm guessing that information (a graphic vector equation) is not available in the 9 patch file? So is there a solution for this problem? Also, what about dithering, etc. I have created a few nine-patch button backgrounds, but none of them have a gradient. yet. Thanks in advance.
Why do you want to use a 9-patch for that? 9-patches stretch an area of an image by copying/duplicating pixels. That will not work well with gradients. Have you considered using a GradientDrawable instead?
<shape android:shape="rectangle">
<gradient android:startColor="..." android:endColor="..." />
</shape>
See shape drawables.
As to your question about dithering, I didn't address that with my previous reply.
You'll have to enable dithering from your application code I'm afraid, as far as I know there is no way to do it from XML. You can use the setDither(true) call on your drawable, as documented here.
This will make for much nicer gradients, since it mitigates the banding artifacts you see on gradient images. I haven't tried this on shape drawables though, just PNG files.
Also, if you're targeting Gingerbread it may be worth reading Bitmap quality, banding and dithering. Apparently they snuck a change into 2.3 which addresses these issues.

Categories

Resources