1

I'm using two ways to display buttons and edit texts in my application : one is by using a xml shape drawable, and applying it to the background of a button/edittext, the other is by using a canvas in a custom view.

I expect the result to be exactly the same, but it's not. You can see below the tiny difference between the respective strokes :

enter image description here

Both are round rectanlges with a 2dp stroke width, and a 8dp corners radius. Here is the code for each of them :

Left, the drawable shape used as a background :

<?xml version="1.0" encoding="UTF-8"?>
<shape
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <solid android:color="@color/transparent"/>
    <corners android:radius="@dimen/button_cornersRadius"/>
    <stroke
        android:width="@dimen/button_strokeWidth"
        android:color="@color/blue_light"/>
</shape>

Right, the onDraw method of the custom view :

protected void onDraw(Canvas canvas) {
canvas.drawPath(drawingPath,strokePaint);
canvas.drawText(text,demiWidth,textHeight,textPaint);
}

Whith :

    strokePaint     = new Paint(Paint.ANTI_ALIAS_FLAG);
    strokePaint     .setStyle(Paint.Style.STROKE);
    strokePaint     .setStrokeWidth((int)(2*densityObtainedWithDisplayMetrics)));
    strokePaint     .setColor(the exact same as above);

And I observe tiny differences when displaying gradients with the same supposedly equivalent ways : The shape drawable has a nicer display, the colors look better, the lines are not blurred.

Could someone explain me why / how to work around it? If I was to use only one way, it would be the second, but I don't want to since it doesn't look clean. Thanks for any help!

EDIT :

Surprisingly, this difference occurs only when the stroke width of the custom layout is odd. With even values the display is exactly the same!

Kirk
  • 16,182
  • 20
  • 80
  • 112
c-val
  • 181
  • 1
  • 2
  • 13
  • Try using `strokePaint.setDither(true);`. The `ShapeDrawable` may already be dithered by default. (Also, you could upload images to imgur or something, then post the link.) – Cat Jul 13 '12 at 17:25
  • It's in it, I didn't put it in the code because it doesn't change anything.. – c-val Jul 13 '12 at 17:27
  • @Soxxeh : I put the picture on imgur : http://imgur.com/njzxD – c-val Jul 13 '12 at 17:32
  • @0gravity : Isn't it equivalent to strokePaint = new Paint(Paint.ANTI_ALIAS_FLAG); ? – c-val Jul 13 '12 at 17:32
  • @Charles yea that is why I deleted the comment. I usually use `strokePaint.setAntiAlias(true);` instead of the way you are doing it, but it should be the same. You can try it just to be safe :) – 0gravity Jul 13 '12 at 17:35
  • @0gravity Yes I tried, doesn't change anything, it would have been to easy right ;) Actually I just tried without setting the antialiasing on, and the blur effect desappears, but the aliasing is really ugly.. – c-val Jul 13 '12 at 17:52

1 Answers1

2

I would recommend you take a look at the source for GradientDrawable (the object actually created from a <shape> XML tag) to see the draw calls that are put in place by the framework for the given shape created.

GradientDrawable.java

You can see in the inflate() method how the XML is parsed out into the object, and then the method draw() is where all the pertient Canvas code is contained.

EDIT: At quick glance, the only major difference I see is that the framework uses canvas.drawRoundedRect() instead of canvas.drawPath() when a single radius value is provided. It also does it for both the fill and stroke, even though in your case the fill is transparent. There may be other differences, I didn't trace all the code closely.

devunwired
  • 62,780
  • 12
  • 127
  • 139
  • I wish I could mark your answer as useful, but I don't have 15 reputation.. I was actually wandering on GrepCode ShapeDrawable code. Yes I tried the drawRoundRect and it doesn't change anything. It's wierd because if you look at the picture imgur.com/njzxD the antialising works the same on the corners, the difference is on the straight lines. The only other difference I see is the use of mStrokePaint.setColorFilter(mColorFilter); I don't know anything about colorfilers, and developer.android.com doesn't explain anything in the class reference.. – c-val Jul 13 '12 at 18:52
  • Anybody knows How to display Text in Android Canvas ShapeDrawable with RectShape? – LOG_TAG Aug 20 '14 at 11:37