4

How can a achieve a curve like this:

curve background shape

mrid
  • 5,782
  • 5
  • 28
  • 71
Wale
  • 1,644
  • 15
  • 31
  • @Which curve sir, there is multiple i see in there. – CodeDaily Sep 28 '17 at 01:09
  • @TonnyBaya the dimyellow curver except the round white cardview on the curve. so what i realy want to get is the yellow curve with out the round stuff on it, i could have use image but i think the app will become heavier cause i have to use it on many pages. – Wale Sep 28 '17 at 03:05
  • Try this [library](https://github.com/developer-shivam/Crescento) and add two imageviews from it with different height. – Lalit Fauzdar Sep 28 '17 at 03:31

2 Answers2

10

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

enter image description here

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.

enter image description here

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

enter image description here

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

enter image description here

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

enter image description here

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

enter image description here

That's about all the info you need to figure out how I've written the path data for the curve in the question.

Ajil O.
  • 6,562
  • 5
  • 40
  • 72
  • 1
    This is the solution i have been looking for, but i have a little bonus question to ask, if i am permitted to? @Ajil O. please can you give me a tutorial link or maybe explain how you go the pathData values? am really interested on how you got that. Thank you. – Wale Sep 28 '17 at 18:46
  • No good tutorials AFAIK @W.Seun . I have edited the post to give some more details. It should help now. I'll keep editing it and add more details when I have time. – Ajil O. Sep 29 '17 at 04:16
  • 1
    Thanks @AjilO. for sharing the knowledge, now i have the knowledge. – Wale Sep 29 '17 at 20:39
  • @W.Seun If this answer helped, do upvote and mark as answer – Ajil O. Sep 30 '17 at 07:21
2

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

enter image description here

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>

enter image description here

Place Orange shape under the first layout having background in white with some negative MarginTop.

Ajil O.
  • 6,562
  • 5
  • 40
  • 72
Sai Jayant
  • 366
  • 2
  • 14
  • While I agree that this might be a good solution, this will not work on devices of different screen sizes. For the shape to correctly render a curve, as asked in the question, the screen width should be (almost) equal to 300dp which usually won't be the case. – Ajil O. Sep 28 '17 at 05:43
  • 1
    I Appreciate your method but like @AjilO. said, setting the margin will only make the design look good on the current screen, if you use another screen with bigger or smaller size, it will give different result because i have tried it already. Thanks. – Wale Sep 28 '17 at 18:43
  • well appreciated i will work along with some modification – Sai Jayant Sep 29 '17 at 09:51