Android: 如何创建一个圆形的TextView?

70

以下是我的简单XML代码,但我想让其中的三个TextView变成圆形,而不是矩形。

我该如何修改代码呢?

<?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>
注意:我需要一个实际的圆形,而不是下面显示的有曲边的矩形:

enter image description here

编辑:

当前代码:

<?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>

当前输出:

在这里输入图片描述


请简要说明您的问题。 - GrIsHu
你想要所有的TextView怎么样?发一些截图,以便人们了解你的需求。 - GrIsHu
我只想让布局中的每个文本视图都成为圆形。 - codeme2020
1
为什么问题要减去2?我正在寻找相同的东西。 - Shirish Herwade
11个回答

109

我也在寻找解决这个问题的方法,最简单舒适的方法是将矩形TextView的形状转换为圆形。使用以下方法将完美解决此问题:

  1. 在drawable文件夹中创建一个名为"circle.xml"(例如)的新XML文件,并填写以下代码:

    <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>
    

使用此文件,您将创建新的TextView形式。在本例中,我创建了一个绿色的圆形。如果您想添加边框,则需要在上一个文件中添加以下代码:

    <stroke
        android:width="2dp"
        android:color="#FFFFFF" />
  1. 在drawable文件夹中创建另一个名为"rounded_textview.xml"的XML文件,并使用以下代码:

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

这个文件将会改变我们所选的TextView的样式。

  1. 最后,在TextView的属性中,我们想要更改方式的部分,我们前往“背景”并选择第二个创建的XML文件(“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" />

通过这些步骤,可以将一个矩形的TextView变成一个圆形的TextView。只需改变形状,而不改变TextView的功能。结果如下图所示:

enter image description here

另外我要说的是,这些步骤也可应用于任何具有“background”选项的其他组件。

祝好运!


3
这很有效。你能告诉我如何在运行时设置背景颜色吗?似乎无法弄清楚。谢谢。 - drod
这对我很有效,但我不需要选择器文件。如果我想要不同的状态,我猜它会派上用场。 - Casey Perkins
什么是“eligamos”?我不明白为什么需要第二步,我们不能直接将圆形可绘制引用添加到布局xml中吗? - Adam Burley

89

典型的解决方案是定义形状并将其用作背景,但由于数字数量的变化,它不再是一个完美的圆形,看起来更像是一个具有圆角或椭圆形的矩形。因此,我开发了这个解决方案,它运行良好。希望能帮助到某些人。

Circular Text View

这是自定义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);

}
}

然后在你的XML中,给一些padding并确保它的gravity属性是居中的

<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"/>

你可以设置描边的宽度

circularTextView.setStrokeWidth(1);
circularTextView.setStrokeColor("#ffffff");
circularTextView.setSolidColor("#000000");

4
如果数字小于10,则椭圆形不是"wrap_content"。 - NickUnuchek
1
@umerk44 这是一个很好的解决方案,我唯一对它有意见的是当它显示时,大约一半的圆在短暂的时刻内没有显示出来。对于这个问题有什么建议吗? - Mark
@NickUnuchek,它总是wrap_content,请在数字周围看到太多空间时删除填充。 - umerk44
1
@NickUnuchek 完全同意,我这里也面临着相同的问题。 - Ahesanali Suthar
3
为什么要重写 draw 方法,而不是 onDraw 方法? 在 draw/onDraw 方法中创建对象似乎是一种不好的做法,因为这些方法会经常被触发,并且存在垃圾回收事件的风险,这会导致所有操作都会被冻结。 - Artur Dumchev
显示剩余4条评论

45

创建一个texview_design.xml文件,并将以下代码添加到其中。将其放在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>

然后在您的主要XML文件中,对于每个TextView,请添加以下行:

  android:background="@drawable/texview_design"

第二种方法(不建议使用): circle 下载这个圆形图并将其放置在drawable文件夹中,然后将其设置为TextView的背景,再将gravity设置为center

然后它看起来像这样:

enter image description here


我刚刚用我的按钮和对话框完成了它,所以我很确定。 - Tushar Gogna
等一下..那行代码并没有被添加..只是被编辑了。我的错。现在运行它,看看它是否做你想要的事情。如果是的话,就选择这个答案。 :) - Tushar Gogna
8
这并不是在创建一个圆形,而是创建了一个带有曲边的矩形? - codeme2020
修复实际中心的 11android:includeFontPadding="false" - user5698345
1
非常感谢,这非常有用。 - Bruno Sosa Fast Tag
显示剩余2条评论

32

这是一个矩形,防止椭圆形背景变成圆形。
将视图设为正方形将解决所有问题。

我发现这个解决方案干净且适用于不同文本大小和长度。

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);

    }
}


用法

<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>

这是我能找到的唯一正确的答案。 - Oliver Dixon
2
运行得很好。 - Amar Ilindra
9
即使我们设置了android:gravity="center",少于10个字符的文本也会向右对齐。添加android:inputType="number"将使文本居中对齐,即使文本少于十个字符。 - Edijae Crusar
它非常棒,是最干净和高效的解决方案! - anni
1
要使用AppCompat支持,请使用AppCompatTextView - Mohammed Sufian
显示剩余2条评论

13

1. 在您的res/drawable文件夹中创建一个名为circle_text_bg.xml的xml文件,并使用以下代码:

<?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. 使用 circle_text_bg 作为您的 TextView 的背景。注意:为了获得完美的圆形,您的 TextView 高度和宽度应该相等。预览使用此背景的文本视图显示为 1、2、3 的效果


1
当使用此选项时,请记得在您的TextView中添加android:gravity="center" - Ojonugwa Jude Ochalifu
如果您正在使用 sp 作为文本大小(正如您应该这样做),那么固定 TextView 的高度和宽度并不是一个好主意,因为根据用户的偏好,文本与视图的比例会有所不同,甚至可能会溢出视图。 - Adam Burley

8
这是我实际工作的解决方案。
<?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>

确保您的TextView宽度和高度匹配(以dp为单位),如果您想要一个完美(不拉伸)的圆形。
确保文本适合圆形,可以通过缩短文本或扩大圆形或减小文本大小或减少填充(如果有的话)来实现。 或者以上建议的组合。
[编辑]
从您的图片中可以看出,您想在一行上添加太多文本,用于纯圆形。 请注意,文本应具有方形外观,因此您可以将其换行(使用\n)或仅将数字放在圆圈内,并将写作放在相应圆圈的上方或下方。

我下面的评论中提到的 TextView 的代码是否正确?请注意,我将您的代码称为“圆形2”。这段代码不是在制作圆形,而是在制作带有曲边的矩形吗? - codeme2020
<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"> - codeme2020
它为我制作了完美的圆形。我将宽度和高度设置为32 dp,文本设置为16sp。但是更改大小不应该有任何区别。 - Phantômaxx
请确保文本适合圆形区域,可以通过缩短文本、扩大圆形区域或减小文本字体大小来实现。 - Phantômaxx
从您的图片中我所看到的,您想要在纯圆形上添加过多的文本。请注意,文本应该具有“正方形”方面,因此您可以将其包装(使用\n),或者只需将数字放在圆形内部,然后在圆形上方或下方书写。 - Phantômaxx
spdp不同,如果用户更改其文本大小偏好,则会出现不适合圆形的文本。 - Adam Burley

6
您可以在drawable文件夹的round_tv.xml中尝试以下内容:
<?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>

将该可绘制物应用于您的TextView中:

<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" />

输出结果:

这里输入图片描述

希望这可以帮助你。

编辑:如果你的文本太长,椭圆形更为适用。

<?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>

输出:

在此输入图片描述

如果您仍需要一个合适的圆形,那么我想您需要在设置文本后动态设置其高度,新高度应该与其新宽度一样,以使其成为一个合适的圆形。


这不是创建一个圆形,而是创建了一个带有圆角的矩形? - codeme2020
@codeme2020 可能是文本大小和宽度的问题。请参见更新答案中的屏幕截图。 - MysticMagicϡ
谢谢,我该如何更改文本大小和宽度以确保它是一个圆形。 - codeme2020
@codeme2020 的文本是固定的吗?还是会动态决定? - MysticMagicϡ
我需要它成为一个圆形吗? - codeme2020
显示剩余2条评论

5

在你的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>

将TextView的背景设置为以下样式:


为什么要使用矩形形状? - Phantômaxx
为什么不使用正确的形状(椭圆形)? - Phantômaxx
即使使用椭圆形,除非你的TextView也有固定大小,否则这个固定大小将没有任何效果。另外,它不会灵活地匹配用户的文本大小设置(假设您按照最佳实践使用sp作为文本大小)。 - Adam Burley

3
这里的很多答案似乎是对形状可绘制对象的修改,而 Android 本身支持使用形状功能实现此目的。这对我来说非常有效。你可以通过以下两种方式实现:

使用固定的高度和宽度,无论你放置什么文本,它都会保持不变,如下所示:

<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>

使用Padding可以重新调整textview的形状,而不受文本影响,如下所示:
<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"/>

半标准边距 = 4dp


这会得到一个椭圆形,而不是圆形。例如,如果它只包含一个数字并且您使用答案的底部部分,则该形状的高度将比其宽度大得多。当然,您可以根据答案的顶部部分修复高度和宽度,但这样做就无法灵活地匹配用户的文本大小设置(假设您按照最佳实践使用sp作为文本大小)。此外,除非您还有一个固定大小的TextView,否则固定大小将没有任何效果。 - Adam Burley

2
我使用:/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>

然后我把它用在我的TextView中:

android:background="@drawable/circulo"

不需要把它复杂化。


很棒的解决方案! - Federico Navarrete
直接回答,谢谢! - Rucha Bhatt Joshi
这会得到一个椭圆形,而不是一个圆形。例如,如果它只包含一个数字,那么形状的高度将比宽度大得多。 - Adam Burley

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接