如何使用编程方式制作带描边的圆形可绘制对象?

9

背景

我想要一个填充的圆形,带有特定颜色和宽度的描边,并且内部有一张图像。

这在XML中很容易实现,例如(这只是一个示例):

<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <shape android:shape="oval">
            <size
                android:width="120dp" android:height="120dp"/>
            <solid android:color="#ffff0000"/>
            <stroke
                android:width="3dp" android:color="#ff00ff00"/>
        </shape>
    </item>
    <item
        android:width="60dp" android:height="60dp" android:drawable="@android:drawable/btn_star"
        android:gravity="center"/>
</layer-list>

在此输入图片描述

问题

我需要以编程的方式更改上述内容的某些属性,因此无法使用XML文件,但是思路仍然相同。

问题在于,我找不到一种简单的方法来在OvalShape drawable上绘制描边,就像在XML中一样。我找不到可以实现此功能的函数。

我尝试过的

有一些解决方案在StackOverflow上,但我找不到一个有效的解决方案。我只发现了这里的一个,但它的描边线被切断了。

但是,我已经在某种程度上成功地解决了这个问题,通过仅使用XML本身进行描边:

stroke_drawable.xml

<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval">
    <stroke
        android:width="4dp" android:color="@android:color/white"/>
</shape>

代码:

    final int strokeDrawableResId = R.drawable.stroke_drawable;
    Drawable innerDrawable = ResourcesCompat.getDrawable(getResources(), ..., null);
    final Drawable strokeDrawable = ResourcesCompat.getDrawable(getResources(), strokeDrawableResId, null);
    ShapeDrawable biggerCircle = new ShapeDrawable(new OvalShape());
    int size = ...;
    biggerCircle.setIntrinsicHeight(size);
    biggerCircle.setIntrinsicWidth(size);
    biggerCircle.getPaint().setColor(0xffff0000);
    biggerCircle.setBounds(new Rect(0, 0, size, size));
    LayerDrawable layerDrawable = new LayerDrawable(new Drawable[]{biggerCircle, strokeDrawable, innerDrawable});

    ImageView imageView = findViewById(R.id.imageView);
    imageView.setImageDrawable(layerDrawable);

它可以工作,但它不完全是程序化的(笔画在XML中定义)。

问题

如何更改代码以完全编程化?


编辑:我尝试了这里建议的内容,但是我需要将所有内容放在一个可绘制对象中,而不是为背景添加额外的可绘制对象,因此我使用了LayerDrawable:

    Drawable innerDrawable = ResourcesCompat.getDrawable(getResources(), android.R.drawable.btn_star, null);
    int strokeWidth = 5;
    int strokeColor = Color.parseColor("#ff0000ff");
    int fillColor = Color.parseColor("#ffff0000");
    GradientDrawable gD = new GradientDrawable();
    gD.setColor(fillColor);
    gD.setShape(GradientDrawable.OVAL);
    gD.setStroke(strokeWidth, strokeColor);
    LayerDrawable layerDrawable = new LayerDrawable(new Drawable[]{gD, innerDrawable});
    ImageView imageView = findViewById(R.id.imageView);
    imageView.setImageDrawable(layerDrawable);

这种方法可以实现,但是内部的可绘制对象(即星号)似乎被拉伸了:

enter image description here


下面我给出的答案不需要stroke_drawable.xml文件。 - Lalit Fauzdar
@LalitSinghFauzdar 我想要一个单一的可绘制对象进行设置。背景用于其他目的(如按压效果)。 - android developer
1个回答

17

您可以通过编程方式实现此操作。
YourActivity.XMl中,像往常一样设置一个ImageView

<ImageView
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:id="@+id/id1"
            android:src="@mipmap/ic_launcher_round"                                
            android:padding="15dp"/>

在您的MainActivity.java文件中

    ImageView iV = (ImageView) findViewById(R.id.id1);
    int strokeWidth = 5;
    int strokeColor = Color.parseColor("#03dc13");
    int fillColor = Color.parseColor("#ff0000");
    GradientDrawable gD = new GradientDrawable();
    gD.setColor(fillColor);
    gD.setShape(GradientDrawable.OVAL);
    gD.setStroke(strokeWidth, strokeColor);
    iV.setBackground(gD);

setColor函数用于设置背景颜色,setStroke函数用于设置描边宽度和描边颜色。
我创建了一些本地变量来表示颜色、宽度等,以使其更易于理解。
结果:
enter image description here
增加填充值会使圆形的大小增加。


它的椭圆形在哪里?为什么要用“getBackground”? - android developer
请问您能否演示如何在椭圆形上进行操作,而不是在视图上进行操作?就像 XML 中所显示的那样。 - android developer
我想以编程方式实现与我所展示的drawable XML 相同的内容。Drawable 应该包含与 XML 相同的所有内容。然而,我认为这可以使用 LayerDrawable 来完成。如果您在 XML 中设置了 "src",那么我认为您的解决方案可能有效。 - android developer
我尝试了我写的LayerDrawable,但它被拉伸了。更新问题以保存此解决方案。 - android developer
1
今天看到的最佳答案...谢谢 - TacB0sS
显示剩余2条评论

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