Как программно сделать круговой рисунок с обводкой?

Задний план

Я пытаюсь получить заполненный круг с обводкой определенного цвета и ширины и изображением внутри.

Это можно легко сделать в 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, как это делается в 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);

Это работает, но по какой-то причине растягивается внутренняя часть (звезда):

введите описание изображения здесь


person android developer    schedule 10.08.2017    source источник
comment
stroke_drawable.xml не потребуется для ответа, который я дал ниже.   -  person Lalit Fauzdar    schedule 10.08.2017
comment
@LalitSinghFauzdar Я хотел установить один рисунок. Фон используется для чего-то другого (например, эффект нажатия)   -  person android developer    schedule 27.11.2018


Ответы (1)


Вы можете сделать это программно, как
В 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 устанавливает ширину и цвет обводки.
Я создал несколько локальных переменных для цвета, ширины и т. д., чтобы упростить понимание.
Результат
введите здесь описание изображения
Чем больше вы увеличиваете отступ, тем больше будет увеличиваться размер круга.

person Lalit Fauzdar    schedule 10.08.2017
comment
Где та часть, которая делает его овальным? Почему у него есть getBackground ? - person android developer; 10.08.2017
comment
Не могли бы вы показать, как это сделать на овальной форме, а не на виде? Так же, как показывает XML? - person android developer; 10.08.2017
comment
ImageView уже может иметь фон. Я хочу создать рисунок для установки в качестве содержимого, включая то, что находится внутри круга (ic_launcher_round в вашем случае), как я показал в вопросе. Это круг, контур и содержание вместе. Я хочу, чтобы все они были внутри одного чертежа, а не в XML. Вы поместили часть этого в XML. Однако я думаю, что это можно исправить с помощью LayerDrawable, не так ли? - person android developer; 13.08.2017
comment
Я хочу иметь то же содержимое, что и в отображаемом XML-коде, который я показал, но программно. Drawable должен содержать все, что есть в XML. Однако я думаю, что это можно сделать с помощью LayerDrawable. Я думаю, что ваше решение могло бы работать, если бы оно было установлено вместо src в XML. - person android developer; 13.08.2017
comment
Я попробовал LayerDrawable, который написал, но он растягивается. Обновленный вопрос для хранения этого решения - person android developer; 13.08.2017
comment
Опять же, мне нужно использовать один рисунок, как полное преобразование того, что у меня было в XML. - person android developer; 13.08.2017
comment
лучший ответ, который я видел за весь день... Спасибо - person TacB0sS; 30.09.2017