Android: Creating a Circular TextView?
Asked Answered
R

11

70

My current simple XML is below, however i would like the 3 TextViews within it to be circular, rather than rectangular.

How can I change my code to do so?

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/tvSummary1"
        android:layout_width="270dp"
        android:layout_height="60dp" >
    </TextView>

    <TextView
        android:id="@+id/tvSummary2"
        android:layout_width="270dp"
        android:layout_height="60dp" >
    </TextView>

    <TextView
        android:id="@+id/tvSummary3"
        android:layout_width="270dp"
        android:layout_height="60dp" >
    </TextView>

</LinearLayout>

Note: I want an actual circle not the curved edge rectangle shown below:

enter image description here

EDIT:

current code:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/tvSummary1"
        android:layout_width="270dp"
        android:layout_height="60dp"
        android:text=" " 
        android:gravity="left|center_vertical"
        android:background="@drawable/circle"/>

    <TextView
        android:id="@+id/tvSummary2"
        android:layout_width="270dp"
        android:layout_height="60dp"
        android:background="@drawable/circle" >
    </TextView>

    <TextView
        android:id="@+id/tvSummary3"
        android:layout_width="270dp"
        android:layout_height="60dp"
        android:background="@drawable/circle" >
    </TextView>

</LinearLayout>

Current output:

enter image description here

Rhoea answered 8/8, 2014 at 12:26 Comment(4)
Please brief your question.Modigliani
How do you want all you TextView? Post some screenshot so that one can understand your requirements.Modigliani
I just want each textview within the layout to be a circular shapeRhoea
why -2 to question???, i'm looking for same thingAnthropophagy
F
109

I was also looking for a solution to this problem and as easy and comfortable I found, was to convert the shape of a rectangular TextView to cirular. With this method will be perfect:

  1. Create a new XML file in the drawable folder called "circle.xml" (for example) and fill it with the following code:

    <shape xmlns:android="http://schemas.android.com/apk/res/android"
        android:shape="oval">
    
        <solid android:color="#9FE554" />
    
        <size
            android:height="60dp"
            android:width="60dp" />
    
    </shape>
    

With this file you will create the new form of TextView. In this case, I created a circle of green. If you want to add a border, you would have to add the following code to the previous file:

    <stroke
        android:width="2dp"
        android:color="#FFFFFF" />
  1. Create another XML file ( "rounded_textview.xml") in the drawable folder with the following code:

    <?xml version="1.0" encoding="utf-8"?>
    <selector xmlns:android="http://schemas.android.com/apk/res/android">
        <item android:drawable="@drawable/circle" />
    </selector>
    

This file will serve to change the way the TextView we eligamos.

  1. Finally, in the TextView properties we want to change the way section, we headed to the "background" and select the second XML file created ( "rounded_textview.xml").

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="H"
        android:textSize="30sp"
        android:background="@drawable/rounded_textview"
        android:textColor="@android:color/white"
        android:gravity="center"
        android:id="@+id/mark" />
    

With these steps, instead of having a TextView TextView rectagular have a circular. Just change the shape, not the functionality of the TextView. The result would be the following:

enter image description here

Also I have to say that these steps can be applied to any other component having the option to "background" in the properties.

Luck!!

Fawnfawna answered 18/5, 2016 at 11:29 Comment(3)
This works good. Can you possibly tell me how to set the color of the background at runtime? Can't seem to figure it out. Thanks.Cowgirl
This worked well for me, but I didn't need the selector file. If I wanted different states I guess it would come in handy.Whacky
what is "eligamos"? I don't understand why step 2 is needed and we can't just add the circle drawable reference directly into the layout xmlGab
D
90

The typical solution is to define the shape and use it as background but as the number of digits varies it's no more a perfect circle, it looks like a rectangle with round edges or Oval. So I have developed this solution, it's working great. Hope it will help someone.

Circular Text View

Here is the code of custom TextView

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.widget.TextView;

public class CircularTextView extends TextView
{
private float strokeWidth;
int strokeColor,solidColor;

public CircularTextView(Context context) {
    super(context);
}

public CircularTextView(Context context, AttributeSet attrs) {
    super(context, attrs);
}

public CircularTextView(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
}


@Override
public void draw(Canvas canvas) {

    Paint circlePaint = new Paint();
    circlePaint.setColor(solidColor);
    circlePaint.setFlags(Paint.ANTI_ALIAS_FLAG);

    Paint strokePaint = new Paint();
    strokePaint.setColor(strokeColor);
    strokePaint.setFlags(Paint.ANTI_ALIAS_FLAG);

    int  h = this.getHeight();
    int  w = this.getWidth();

    int diameter = ((h > w) ? h : w);
    int radius = diameter/2;

    this.setHeight(diameter);
    this.setWidth(diameter);

    canvas.drawCircle(diameter / 2 , diameter / 2, radius, strokePaint);

    canvas.drawCircle(diameter / 2, diameter / 2, radius-strokeWidth, circlePaint);

    super.draw(canvas);
}

public void setStrokeWidth(int dp)
{
    float scale = getContext().getResources().getDisplayMetrics().density;
    strokeWidth = dp*scale;

}

public void setStrokeColor(String color)
{
    strokeColor = Color.parseColor(color);
}

public void setSolidColor(String color)
{
    solidColor = Color.parseColor(color);

}
}

Then in your XML, give some padding and make sure its gravity is center

<com.app.tot.customtextview.CircularTextView
        android:id="@+id/circularTextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="11"
        android:gravity="center"
        android:padding="3dp"/>

And you can set the stroke width

circularTextView.setStrokeWidth(1);
circularTextView.setStrokeColor("#ffffff");
circularTextView.setSolidColor("#000000");
Daggett answered 8/1, 2016 at 20:32 Comment(9)
I am glad it helped :)Daggett
if number is < 10 then oval is not wrap_contentSisera
@Daggett this is a good solution to the problem, the only issue I have with it is that when it is displayed roughly half of the circle is not shown for a brief moment. Any suggestions for this issue?Siva
@Sisera it's always wrap_content, please remove padding if you see to much space around numberDaggett
@MarkLordan sorry i didn't get your question? "when it's displayed roughly" ?Daggett
@Sisera completely agree, facing smae issue hereSearby
@Daggett What i should do if i want to use it programmatically ? and not by XML. like CircularTextView txtQuantity = new CircularTextView(getApplicationContext());. How can i use this ?Scraper
Thanks very much! I would put all generic logic outside onDraw methodTirpitz
Why do you override draw, not onDraw? And it seems a bad practice to create objects in draw/onDraw, since it is triggered often and we have a risk of GC event, which will freeze everything.Haft
D
45

Create an texview_design.xml file and populate it with the following code. Put it in res/drawable.

<shape xmlns:android="http://schemas.android.com/apk/res/android" >

        <solid android:color="#98AFC7" />

        <stroke
            android:width="2dp"
            android:color="#98AFC7" />

        <corners
            android:bottomLeftRadius="20dp"
            android:bottomRightRadius="20dp"
            android:topLeftRadius="20dp"
            android:topRightRadius="20dp" />

    </shape>

Then in your main XML file just add the following line for each TextView:

  android:background="@drawable/texview_design"

Second way (not recommended): circle Download this circle and place it in your drawable folder and then make it your TextView's background. and then set the gravity to center.

Then it will look like this:

enter image description here

Descant answered 8/8, 2014 at 12:33 Comment(7)
I just did it with my button and dialogbox so yes I'm sure.Descant
Wait.. That line wasn't added as a code.. just edited. My bad. Now just run it and see if it does what you are looking for. And if it does then select this answer. :)Descant
Great. Now you can change the color and roundness according to your requirements (in the design xml file). :)Descant
This is not creating a circle, it is created a rectangle with curved edges?Rhoea
You just have to change dimensions according to your requirements. And wrap_content your textview.Descant
Fix for 11 in real center: android:includeFontPadding="false"Blavatsky
muchas gracias fue de mucha utilidadZygapophysis
T
33

It's a rectangle that prevents oval shape background to get circular.
Making view a square will fix everything.

I found this solution to be clean and working for varying textsize and text length.

public class EqualWidthHeightTextView extends TextView {

    public EqualWidthHeightTextView(Context context) {
        super(context);
    }

    public EqualWidthHeightTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public EqualWidthHeightTextView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        int r = Math.max(getMeasuredWidth(),getMeasuredHeight());
        setMeasuredDimension(r, r);

    }
}


Usage

<com.commons.custom.ui.EqualWidthHeightTextView
    android:id="@+id/cluster_count"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:gravity="center"
    android:text="10+"
    android:background="@drawable/oval_light_blue_bg"
    android:textColor="@color/white" />


oval_light_blue_bg.xml

<shape xmlns:android="http://schemas.android.com/apk/res/android"<br>
       android:shape="oval">
   <solid android:color="@color/light_blue"/>
   <stroke android:color="@color/white" android:width="1dp" />
</shape>
Tewell answered 20/2, 2016 at 16:37 Comment(7)
This is the only true answer I could find.Randa
it should be the accepted answer. Worked like a charmMalamud
Any text that is less than 10 is aligned to the right even when we set android:gravity="center" adding android:inputType="number" will make the text to be aligned at the center even if text is less than ten.Reliant
plus for great and straightforward answerKetron
It just rox, the cleanest and most efficient solution!Pfeffer
The only one that works across varying text lengths. Also @EdijaeCrusar - you sir, are a life saver!Ritzy
for appcompat support use AppCompatTextViewEsparto
B
13

1.Create an xml circle_text_bg.xml in your res/drawable folder with the code below

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
     <solid android:color="#fff" />

    <stroke
        android:width="1dp"
        android:color="#98AFC7" />
    <corners
         android:bottomLeftRadius="50dp"
         android:bottomRightRadius="50dp"
         android:topLeftRadius="50dp"
         android:topRightRadius="50dp" />
    <size
         android:height="20dp"
         android:width="20dp" />
</shape>

2.Use circle_text_bg as the background for your textview. NB: In order to get a perfect circle your textview height and width should be the same.Preview of what your textview with text 1, 2, 3 with this background should look like this

Barehanded answered 6/9, 2016 at 9:49 Comment(2)
When using this option,remember to add android:gravity="center" to your TextViewEvitaevitable
Fixing TextView height and width is not a great idea if you are using sp for your text size (as you should be) as the text will be different proportion to the view based on user preferences and may even overflow the view.Gab
I
8

This my actually working solution

<?xml version="1.0" encoding="utf-8"?>
<shape
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="oval"
    >
    <!-- The fill color -->
    <solid android:color="#ffff" />
    <!-- Just to add a border -->
    <stroke
        android:color="#8000"
        android:width="2dp"
    />
</shape>

Make sure your TextView width and height match (be the same in dp), if you want a perfect (unstretched) circle.

Make sure that the text fits into a circle, by either shortening your text OR enlarging your circle OR making your text size smaller OR reduce your padding/s, if any. OR a combination of the above suggestions.

[EDIT]

For what I can see in your pictures, you want to add too much text on a line, for pure circles.
Consider that the text should have a square aspect, so you can either wrap it (use \n) or just put the numbers inside the circles and put the writings above or uder the corresponding circle.

Ineffectual answered 8/8, 2014 at 12:40 Comment(6)
Is this code in my next comment correct for the TextView? Note I have called your code "circle 2". This code is not making a circle is it making a rectangle with curved edges?Rhoea
<TextView android:id="@+id/tvSummary1" android:layout_width="200dp" android:layout_height="200dp" android:background="@drawable/circle2" android:shadowColor="#A8A8A8" android:shadowDx="0" android:shadowDy="0" android:shadowRadius="5" android:text="Date" android:textColor="#FFFFFF" android:textSize="30sp"> </TextView>Rhoea
It's making perfect circles for me. I set the width and height to 32 dp and the text to 16sp. But it should do no difference, by changing the sizes.Byrne
Make sure that the text fits into a circle, by either shortening your text OR enlarging your circle OR making your text size smaller.Byrne
For what I can see in your pictures, you want to add too much text for pure circles. Consider that the text should have a "square" aspect, so you can either wrap it (use \n) or just put the numbers inside it and the writings above or uder the circle.Byrne
sp and dp are not the same, if the user changes their text size preferences then you will get text that doesn't fit in the circle.Gab
P
6

You can try this in round_tv.xml in drawable folder:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >

    <stroke android:color="#22ff55" android:width="3dip"/>

    <corners
        android:bottomLeftRadius="30dp"
        android:bottomRightRadius="30dp"
        android:topLeftRadius="30dp"
        android:topRightRadius="30dp" />

    <size
        android:height="60dp"
        android:width="60dp" />

</shape>

Apply that drawable in your textviews as:

<TextView
    android:id="@+id/tv"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@drawable/round_tv"
    android:gravity="center_vertical|center_horizontal"
    android:text="ddd"
    android:textColor="#000"
    android:textSize="20sp" />

Output:

enter image description here

Hope this helps.

Edit: If your text is too long, Oval shape is more preferred.

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval">

    <stroke android:color="#55ff55" android:width="3dip"/>

    <corners
        android:bottomLeftRadius="30dp"
        android:bottomRightRadius="30dp"
        android:topLeftRadius="30dp"
        android:topRightRadius="30dp" />

    <size
        android:height="60dp"
        android:width="60dp" />

</shape>

Output:

enter image description here

If you still need it a proper circle, then I guess you will need to set its height dynamically after setting text in it, new height should be as much as its new width so as to make a proper circle.

Panocha answered 8/8, 2014 at 12:41 Comment(7)
This is not creating a circle, it is created a rectangle with curved edges?Rhoea
@Rhoea may be issue of text size, and width. See screenshot in updated answer.Lester
Thanks, how do I change my text size and width to ensure it is a circleRhoea
@Rhoea text is fixed? or will be decided dynamically?Lester
The text is added dynamicallyRhoea
@Rhoea this text is rather too long. ou need oval shape or only circle?Lester
I need it to be a circle?Rhoea
M
5

use this in your drawable

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" 
    android:shape="oval">


    <solid android:color="#55ff55"/>


    <size android:height="60dp"
        android:width="60dp"/>

</shape>

Set background for the textview as this

Marlysmarmaduke answered 8/8, 2014 at 12:35 Comment(3)
why do you use a rectangular shape?Byrne
why not using the proper shape (oval)?Byrne
Even using oval, this fixed size won't have any effect unless you also have a fixed size for your TextView. Also it won't be flexible to match the user's text size setting (assuming you are using sp for text size as per best practice).Gab
T
3

Much of the Answer here seems to be hacks to the shape drawable, while android in itself supports this with the shapes functionality. This is something that worked perfectly for me.You can do this in two ways

Using a fixed height and width, that would stay the same regardless of the text that you put it as shown below

<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">

<solid android:color="@color/alpha_white" />

    <size android:width="25dp" android:height="25dp"/>

<stroke android:color="@color/color_primary" android:width="1dp"/>

</shape>

Using Padding which re-adjusts the shape regardless of the text in the textview it as shown below

<solid android:color="@color/alpha_white" />

<padding
    android:bottom="@dimen/semi_standard_margin"
    android:left="@dimen/semi_standard_margin"
    android:right="@dimen/semi_standard_margin"
    android:top="@dimen/semi_standard_margin" />

<stroke android:color="@color/color_primary" android:width="2dp"/>

semi_standard_margin = 4dp

Tomasatomasina answered 17/6, 2015 at 15:28 Comment(1)
This gives an oval, not a circle. For example if it just contains a single digit and you use the bottom part of your answer, the height of the shape will be much greater than its width. Of course you can fix the height and width as per the top part of your answer, but then it won't be flexible to match the user's text size setting (assuming you are using sp for text size as per best practice). Also, the fixed size won't have any effect unless you also have a fixed size for your TextView.Gab
M
2

I use: /drawable/circulo.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval">
    <solid android:angle="270"
        android:color="@color/your_color" />

</shape>

And then I use it in my TextView as:

android:background="@drawable/circulo"

no need to complicated it.

Missilery answered 19/4, 2016 at 12:0 Comment(3)
Great solution!Castano
straight answer, thanx!!Maharaja
This gives an oval, not a circle. For example if it just contains a single digit, the height of the shape will be much greater than its width.Gab
M
0

Try out below drawable file. Create file named "circle" in your res/drawable folder and copy below code:

   <?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="oval" >

    <solid android:color="#FFFFFF" />

    <stroke
        android:width="1dp"
        android:color="#4a6176" />

    <padding
        android:left="10dp"
        android:right="10dp"
        android:top="10dp"
        android:bottom="10dp"
         />

    <corners android:radius="10dp" />

</shape>

Apply it in your TextView as below:

<TextView
        android:id="@+id/tvSummary1"
        android:layout_width="270dp"
        android:layout_height="60dp"
        android:text="Hello World" 
        android:gravity="left|center_vertical"
        android:background="@drawable/round_bg">

    </TextView>

enter image description here

Modigliani answered 8/8, 2014 at 12:39 Comment(3)
This isnt creating a circle, its creating a rectangle with curved edges?Rhoea
@Rhoea Try out with the oval check out i have updated my selector. Is this what you want?Modigliani
(1) Update your screenshot if you updated your answer (2) Why do you need fixed height and width, as a solution should avoid this, (3) You defined your shape name as "circle" but in your layout it's called "round_bg" (4) No need to put open and close tags for a TextViewGab

© 2022 - 2024 — McMap. All rights reserved.