How To Create A Custom Ring shaped drawable android - android

How can a achieve a curve like this:

The easiest solution would be to use a VectorDrawable. Create a new drawable
custom_ring.xml
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="100dp"
android:height="100dp"
android:viewportHeight="700"
android:viewportWidth="700">
<path
android:pathData="M0,0Q350,150,700,0L700,200Q400,300,0,200"
android:strokeColor="#color/colorPrimary"
android:strokeWidth="1"
android:fillColor="#color/colorYellow"/>
</vector>
And then add it as the background for the required view
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/custom_ring" />
Details on VectorDrawables
VectorDrawables are easy enough to understand and it is possible to get simple shapes created within Android Studio itself. For more complex shapes you'd have to resort to other tools to generate SVG files which can later be converted to VectorDrawables in AS.
For details refer to this post to get an idea on how to work with VectorDrawables.
I'll try to give a line by line explanation for the custom_ring.xml file I have used. It is correct to the best of my knowledge though I am open to suggestions and corrections.
Height and Width
Vector drawables are immune to scaling as far as I have observed. The only condition is that the aspect ratio needs to be maintained (I could be wrong here).
When familiarising myself with drawables for the first time, I used to wonder why height and width were required fields. I used to change the values to different values and never observed any change in the preview. It took me longer than truly necessary to realise that this value is required to give the correct dimensions to the view which contains it. For example, if you have an ImageView and set its height and width to wrap_content the ImageView will assume a height and width equal to the value set in the Vector height and width property respectively.
Viewport height and width
I cannot explain better than this image
Setting the viewport as I have in the post makes it possible to actually draw (almost like you'd do with Logo) on a coordinate plane with it's coordinates ranging from (0,0) in the top left corner to (700,700) at the bottom right.
The path
Stroke width: Specifies the width of the outline.
Fill color: Fills the area between the first and last point in the path data with color.
Path data: Probably the most important element and least understood. Please read the post I had linked above. It gives a pretty good explanation.
M0,0 (Moveto instruction) moves the cursor to the coordinate 0,0 without drawing.
Q350,150,700,0 creates a quadratic curve from the current cursor location (which we got by (M0,0)) to (700,0) which is the last 2 parameters of the Q instruction. The first 2 parameters of the Q instruction (350,150) dictate the shape and size of the curve. For example,
<path
android:pathData="M0,0Q350,750,700,0"
android:strokeColor="#FF0000"
android:strokeWidth="10"/>
would generate this curve
while
<path
android:pathData="M0,0Q50,750,700,0"
android:strokeColor="#FF0000"
android:strokeWidth="10"/>
would render the curve like this. Notice the change caused by changing Q350,700,700,0 to Q50,750,700,0
Changing the 2nd parameter will define the amplitude of the curve.
<path
android:pathData="M0,0Q350,350,700,0"
android:strokeColor="#FF0000"
android:strokeWidth="10"/>
will give
L350,350 (Lineto instruction) would draw a line from the current cursor position to the coordinates (350,350)
<path
android:pathData="M0,0L350,350"
android:strokeColor="#FF0000"
android:strokeWidth="10"/>
will draw the below line
That's about all the info you need to figure out how I've written the path data for the curve in the question.

First set a shape in xml like this in white color
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners
android:bottomLeftRadius="150dp"
android:bottomRightRadius="150dp"
android:topLeftRadius="0dp"
android:topRightRadius="0dp" />
<stroke
android:width="0.6dp"
android:color="#color/prefered_color" />
<padding
android:bottom="0dp"
android:left="0dp"
android:right="0dp"
android:top="0dp" />
<solid android:color="#color/white" />
</shape>
which will produce a shape like this
Again make shape in orange which will be placed under the white shape which will be like
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners
android:bottomLeftRadius="150dp"
android:bottomRightRadius="150dp"
android:topLeftRadius="0dp"
android:topRightRadius="0dp" />
<stroke
android:width="0.6dp"
android:color="#color/prefered_color" />
<padding
android:bottom="0dp"
android:left="0dp"
android:right="0dp"
android:top="0dp" />
<solid android:color="#color/orange" />
</shape>
Place Orange shape under the first layout having background in white with some negative MarginTop.

Related

Create Single Pixel Rectangle

I want to create a single pixel stroke rectangle, but android is rendering two pixels.
Here is my xml code:
<item>
<shape android:shape="rectangle">
<solid android:color="#FFF" />
<stroke android:width="1px" android:color="#000" />
</shape>
</item>
Here is the top left corner of what is rendered:
My only guess is that this background is not lining up with the device pixels.
So, essentially a line? You could try using something like
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="line">
<solid android:color="#FFF" />
<stroke android:width="1px" android:color="#000"/>
</shape>
EDIT: whoops, think I misunderstood. You could always just draw a rectangle using lines though I guess.
px has different meanings on different screen sizes. I'm guessing this is on a bigger screen? Try changing the unit to dp and the anti-aliasing affect should disappear
edit: actually this wont solve your issue if you just want the physical thickness of the line on your screen to be half its current size. It will make it look equivalent on all types of screen though and keep a solid appearance, if that's your complaint
This was caused by the bi-linear filtration introduced in honeycomb and later. There are two solutions:
Disable all hardware acceleration in the manifest (bad idea) with this tag
android:hardwareAccelerated="false"
Use the xml attribute on affected views to render with software only
android:layerType="software"
I found the solution here:
Blurred 1dip shape lines (borders) on Android

Dynamic radial circle in the middle of the screen

Why is it so difficult to make this little thing work? : /
I want to create something like android's lock screen.
I have an XML:
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval" >
<stroke
android:width="#dimen/dp_5"
android:color="#color/black" />
<gradient
android:type="radial"
android:startColor="#color/green"
android:endColor="#color/red"
android:gradientRadius="#dimen/dp_50" />
</shape>
This circle is a background of a TextView, so the following happens:
1. wrap_content creates a little circle in the center of the screen
2. fill_parent creates an elipse taking the whole screen, instead of a circle
In addition I would like to change the startColor and endColor programmatically - Didn't find any documentations\threads which solved this SIMPLE issue.

How to control the gradient on a shape?

I have a screen with a label on top. This label is done with a TextView.
As a background I'd like to have a vertical gradient, starting with color1, changing to color2 and back to color1.
At the moment I have:
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<stroke android:width="1px" android:color="#000000" />
<gradient
android:startColor="#FFFFFFFF"
android:centerColor="#FF8800"
android:endColor="#FFFFFFFF"
android:type="linear"
android:angle="270"
/>
<corners android:radius="10dp"/>
</shape>
My problem is that the centerColor line is too thin. I want it to ocupy all the letters space.
I can't find any way to make the gradient to be faster.
I've already tried to use a layout-list but with no success.
Any idea?
This is a much more different track to follow but have you considered working with 9-patch image files? This will allow you to stretch the parts of the gradient that you wish to and make the centre line as big as needed by segmenting up the background properly.
Here are some great tutorials I have used to learn about them:
draw 9 patch tutorial
And from Google's own Android mouth:
Android 9 patch
All Drawable resources for Android

How to add corners to a view

I added a full border around a view but I need to add just the corner as shown image below :
I mean the red corner only .
I tried to adjust the below border xml , but it didn't work :
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<stroke android:width="10dp" android:height="10dp" android:color="#B22222" />
<solid android:color="#FCE6C9" />
<corners android:radius="20dp" />
</shape>
Any help will be appreciated
I don't think it's possible to do this using a ShapeDrawable, as it would require you to use some sort of margin or padding on the drawable itself. There actually is a padding attribute, but unfortunately that only has effect on the content of the View, and not the drawable itself.
That being said, an easy solution would be to create a 9-patch in stead and apply that as background to the TextView. Just for demonstration purposes: make the 9-patch look somewhat like this:
Edit:
On second thought, there's actually another option that relies on using a LayerDrawable to create the desired effect. It's a bit tedious to create and I have my doubts it'll be more efficient than using a 9-patch, but at least you don't have to render out images, which means that if you need to make e.g. a change in colours, it's more straightforward.
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/rounded" />
<item android:drawable="#android:color/white" android:left="30dp"
android:right="30dp" />
<item android:bottom="30dp" android:drawable="#android:color/white"
android:top="30dp" />
<item android:bottom="30dp" android:left="10dp" android:right="10dp"
android:drawable="#color/pink" android:top="30dp" />
<item android:bottom="10dp" android:left="30dp" android:right="30dp"
android:drawable="#color/pink" android:top="10dp" />
</layer-list>
Some details: #drawable/rounded is the code snippet you posted yourself. The following two items are simply white rectangles with an offset, to create the white edges. Now, since these will also overlay the pink surface, we need two more pink rectangles (again with specific offsets) to counter that. The result is a background that looks exactly like what you're showing in your question.
Note that you might want to see if you can optimise this a bit. At the least I'd recommend not hardcoding the offsets (like I did for simplicity), but store them in a dimens.xml file so you can keep these values centralized and consistent by referencing them from both the ShapeDrawable and LayerDrawable.
Addendum: On pre-ICS (or perhaps pre-Honeycomb) devices, there appears to be an issue with directly referencing colours with the android:drawable attribute. You can however easily get around this by setting up another drawable (be it either a 9-patch or ShapeDrawable) to represent this colour. For example, in the snippet above, you would replace android:drawable="#color/pink" with android:drawable="#drawable/color_pink", where color_pink can simply be an xml file containing:
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#FCE6C9" />
</shape>
Obviously you will need to do the same for all other colours referenced in the LayerDrawable. Tested on Gingerbread 2.3.7.
I would create a 9-patch file and set it to be the background of the main container. The steps to do that would be.
You create the background you would like roughly in fireworks, illustrator, or whatever image editing software you prefer.
Then crop the artwork so that there is only a 1 pixel border around the artwork. Save it as a png.
Open the draw9patch.bat file in your android sdk folder on your computer C:\Program Files (x86)\Android\android-sdk\tools.
Open your png file. You can then use your mouse to click on the outer 1 pixel border which will turn the clicked pixels black. The areas that you have black pixels on both the top and bottom or on the left and right will be the area that is stretched. In your case you just want to have the middle area where there is no red stretched.
My personal preference is to just open the file above and save it as a 9 patch file. Then open it in my photo editing software to create a 1 pixel thick line in the same fashion as above. It is quicker and more precise.
Finally add the file to your drawable folder. Then set the background of your main view container to the drawable.
That should be it. Hope that helps.

Android Rounded Edges for backgrounds

I was wondering if anyone knew how to make rounded background edges for only certain corners.
For example, in the lock screen of Android 2.2 there were the two slidingDrawers to unlock the phone and take a picture or something.
The slidingDrawers had a rounded corner with an icon within it. Anyone know how to make the corners of a background rounded?
There are lots of ways in achieving that.
You could use a 9patch drawable, and I'm guessing that's what they used.
You can also use a shape drawable, with proper corners.
Other than that, your question is too ambiguous. But this should provide enough for a good answer to your problem.
you can create a xml file inside the drawable folder with some code like this ,
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#FFFFFF"/>
<corners android:radius="5px"/>
<padding android:left="0dp" android:top="0dp" android:right="0dp" android:bottom="0dp" />
</shape>
change the radius values for the amount of rounded edge you need. Apply this xml as the background of your textview or edittext or anything.

Categories

Resources