I'm trying to have a filled circle, with a stroke of certain color and width, and an image inside.
This can easily be done in XML, as such (this is just a sample) :
<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>
I need to have certain properties of the above to change programmatically, so I can't use the XML file, but the idea is still the same.
Thing is, I can't find an easy way to put a stroke on an OvalShape drawable, as done in XML. I can't find the function to do it.
There are solutions out there here on StackOverflow, but I couldn't find one that works well. Only one I've found is here, but its stroke line is being cut .
I have, however, partially succeeded in one way to solve this, by using an XML just for the stroke itself:
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>
code:
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);
It works, but it's not fully programmatically (stroke is defined in XML).
How to change the code to be fully programmatic ?
EDIT: I tried what was suggested here, yet instead of an additional drawable for a background, since I needed it all in one drawable, I used 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);
This works, but for some reason the drawable inside (the star) is being stretched:
You can do this programmatically as
In YourActivity.XMl
, Set-up an ImageView
as usual.
<ImageView
android:layout_width="100dp"
android:layout_height="100dp"
android:id="@+id/id1"
android:src="@mipmap/ic_launcher_round"
android:padding="15dp"/>
And in your 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
here sets the background color and setStroke
sets the stroke width and stroke color.
I have created some local variables for color, width etc to make it more easy to understand.
Result
More you increase the padding, more will the size of circle increase.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With