Android ShapeDrawable stroke is blurred - android

I created a rather simple shapedrawable with semi-transparent borders, and used it as a background for two adjacent view.
Either if the srtoke color is partially transparent, I'm expecting a solid stroke (like the image on the right), but what I get is a blurred stroke (image on the left).
What I'm doing wrong?
(images are taken from the ADT preview, in the emulator the effect is even more visible)
This is the ShapeDrawable (theme_base_bg_framed.xml):
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid
android:color="#color/base_frame_solid_color"
/>
<stroke
android:width="#dimen/frame_border_size"
android:color="#color/base_frame_border_color"
/>
<padding
android:left="#dimen/frame_padding_size"
android:top="#dimen/frame_padding_size"
android:right="#dimen/frame_padding_size"
android:bottom="#dimen/frame_padding_size"
/>
</shape>
It uses these color and dimen definitions:
<color name="base_frame_solid_color">#20ffffff</color>
<color name="base_frame_border_color">#40ffffff</color>
<dimen name="frame_border_size">2dp</dimen>
<dimen name="frame_padding_size">2dp</dimen>
Both drawables are assigned to the Views background
<style name="ViewWithBorder">
<item name="android:background">#drawable/theme_base_bg_framed</item>
</style>
Edit:
The colors used in the ShapeDrawable are alphaed for a reason. The view in the background is going to contain other views and/or images. This is a better example of what I get (left) and what I'm expecting to get (right).

I use this values to get the result you wanted:
colors.xml:
<color name="base_frame_solid_color">#20000000</color>
<color name="base_frame_border_color">#40ffffff</color>
shape:
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid
android:color="#color/base_frame_solid_color"
/>
<stroke
android:width="#dimen/frame_border_size"
android:color="#color/base_frame_border_color"
/>
</shape>
Hope this helps!

Ok, I found what's happening and how to fix it.
It seems that Android, when filling a ShapeDrawable with a border, doesn't fill it to it's full size but just to the middle of the stroke. So, with a stroke of 2dp, it leave a space of 1dp all around. This can be noticed only when using alphaed borders, like I'm doing, because normally the border cover it.
Tho fix this behaviour, I used a LayerList drawable containing two ShapeDrawables, one for the solid color (with no borders) and one for the stroke (with no solid color):
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape
android:shape="rectangle">
<solid
android:color="#color/base_frame_solid_color"
/>
</shape>
</item>
<item>
<shape
android:shape="rectangle">
<stroke
android:width="#dimen/frame_border_size"
android:color="#color/base_frame_border_color"
/>
<padding
android:left="#dimen/frame_padding_size"
android:top="#dimen/frame_padding_size"
android:right="#dimen/frame_padding_size"
android:bottom="#dimen/frame_padding_size"
/>
</shape>
</item>
</layer-list>
It works, but being the border superimposed to the "solid" background, it's color need some adjustment.

Related

How to create shapes on drawable layout android

I need to create a layout that will be with rounded corners, but in which there will be various shapes.
I have a sample (in the screenshot below). I created a layout with rounded corners and the right color, but I don’t know if I can create a few more shapes on it (these shapes are dark in the screenshot) and if I can place them where I want?
My code for background shape:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#color/purple_light" />
<corners android:radius="16dp" />
</shape>
You can use android layer list drawable. You can refer the docs here.
You have 2 choices:
1- Export the complete shape as a vector (SVG) and import it into Android Studio.
Then you can use this shape wherever you want.
(Whole purple background with triangle shaped inside of it)
2- Trying to draw that shape on Android Studio.
You have to do something like this:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="rectangle">
<solid android:color="#color/purple_200" />
<corners android:radius="1dp" />
</shape>
</item>
<item android:drawable="#drawable/ic_baseline_square_24"/>
<item android:drawable="#drawable/ic_baseline_triangle"/>
</layer-list>
But you need to completely design shapes with the drawable.
I tried quickly just for showing you the result:
Sample output

Linear Gradient CenterX

I am trying to make a transparent gradient background for a button, something like this:
(The start color is not grey but transparent)
But I am getting this:
(where white portion is too narrow)
This is my gradient.xml:
<!-- Here centerX does not work -->
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<gradient
android:centerX="30%"
android:startColor="#android:color/transparent"
android:endColor="#android:color/white"/>
</shape>
I have also tried adding a centerColor, but then the transparent area turns to grey!
<!-- Here the startColor turns greyish -->
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<gradient
android:centerColor="#android:color/white"
android:centerX="30%"
android:endColor="#android:color/white"
android:startColor="#android:color/transparent" />
</shape>
Thanks in advance!
If what you need is just gradient moved to the left side of the drawable, try something like this:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:left="100dp">
<color android:color="#android:color/white"/>
</item>
<item android:width="100dp">
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<gradient
android:centerX="30%"
android:endColor="#android:color/white"
android:startColor="#android:color/transparent"/>
</shape>
</item>
</layer-list>
This layer consist of two rectangles:
White rectangle moved to the right by 30dp
Gradient rectangle, whose width is 30dp
centerX works only when you have a centerColor set.
But if you set the center color to #android:color/transparent the gradient goes from opaque white to transparent black, not white.
#android:color/transparent is defined as #00000000, which is a transparent black and not white. Usually it doesn't matter because color is transparent anyway, but in case of gradients it gives a black tint.
So, you need
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<gradient
android:startColor="#00ffffff"
android:centerColor="#00ffffff"
android:endColor="#ffffffff"
android:centerX="30%" />
</shape>
In this case the color is same (#ffffff i.e. white) across the gradient, but alpha is varied from 00 to ff.

Layerlist not showing items correctly Android

I've got two shape drawable xml files that I am using on imagebuttons. One contains a ring, the other contains an oval small enough to fit into the larger ring, similar to a radiobutton. In this image http://imgur.com/mYPALoT you can see (from left to right) the ring, the smaller middle oval, and the combined image showing the layerlist view of both together. This doesn't work and instead shows a complete filled in oval.
Here is the ring xml:
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="ring"
android:innerRadiusRatio="3"
android:thickness="1dp"
android:useLevel="false">
<solid android:color="#1976D2" />
<size
android:height="20dp"
android:width="20dp" />
</shape>
Here is the oval xml:
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="#1976D2" />
<size
android:height="7dp"
android:width="7dp" />
</shape>
Here is the layerlist xml:
<?xml version="1.0" encoding="utf-8"?>
<layer-list
xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/ring_select" />
<item android:drawable="#drawable/ring_center" />
</layer-list>
I'm not familiar with layerlists as I am new to android. What am I doing wrong?
In case another person descends upon this page by the guiding of the knowledegable Google...
I have a workaround that may or may not work for you: instead of using <scale> , try <inset>. You can use a combination of the <item>'s android:top / android:bottom / android:left / android:right and the <inset>'s android:insetXXX to size the image
You can do things like set the sides of each inset value relative to your source image's dimensions. For example, if you have a 64 pixel-wide image and want to cut it down by 50%, you can do (64 / 4 = 16) for each side
I finally found the answer. Basically, the oval in front needs to have this added to it's line:
<item android:top="10dp" android:bottom="10dp" android:left="10dp" android:right="10dp">
The dimensions need to be the same since this is an oval. I'm still not sure why the oval stretched to the entire size of the ring, especially since the size was defined. If anyone has any idea why the top oval stretched like that, please let me know.

Shape Drawable with only two sides

I am trying to implement in XML a ShapeDrawable like this, but so far without success.
How do I make the Stroke visible only for two sides?
Is that even possible?
Otherwise what cloud I use (I seed it as background of a TextView).
Here is a solution which is using a LayerListDrawable:
background_white_lateral_border.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item>
<shape android:shape="rectangle" >
<solid android:color="#android:color/white" />
</shape>
</item>
<item>
<inset
android:insetLeft="1dp"
android:insetRight="1dp" >
<shape android:shape="rectangle" >
<solid android:color="#android:color/black" />
</shape>
</inset>
</item>
</layer-list>
Note: This firstly draws a white rectangle and then a black rectangle with a left and right inset of 1dp on top of it, giving the effect of lateral borders. It's just something to keep in mind, in case you worry about performance (which is in my opinion negligible for minor styling like this).
AFAIK, that is not possible with a single ShapeDrawable. A nine-patch PNG, or a LayerListDrawable of two ShapeDrawables (one per line) should work though.

How to make a double gradient with XML (iphone like)

How can I make this kind of drawable gradient with XML?
I can do a simple gradient from color A to color B but i don't know how to combine two gradients in the same drawable.
I finally found a solution with a layer-list which is good enough for me :
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<!-- First part is a gradient -->
<item android:left="0dp" android:right="0dp">
<shape android:shape="rectangle">
<gradient android:angle="-90" android:startColor="#9dcbf6"
android:endColor="#177ee6" />
</shape>
</item>
<!-- Second part is plain color. Slightly transparent -->
<item android:top="1sp" android:bottom="20sp" >
<shape android:shape="rectangle">
<solid android:color="#10ffffff"/>
</shape>
</item>
</layer-list>
The middle is set to 20 sp because the container has a 40sp height , but you can adjust to your will by editing : android:bottom="20sp"
You can have three colors in a gradient. A start color, end color and a center color.
<gradient
android:angle="integer"
android:centerX="integer"
android:centerY="integer"
android:centerColor="integer"
android:endColor="color"
android:gradientRadius="integer"
android:startColor="color"
android:type=["linear" | "radial" | "sweep"]
android:usesLevel=["true" | "false"] />
Alternatively you can use a LayerList Drawable and just piece them together.

Categories

Resources