gfrung4
gfrung4

Reputation: 1750

Is it possible to specify corner radius as a percentage in an Android drawable?

As an Android drawable, this represents a black rectangle with rounded corners.

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

However, the corner radius is specified as an absolute 20dp, so if this same drawable is shown at different sizes, it appears differently. The smaller shape is not just a "scaled down" version of the larger one. Instead, it's "rounder" and the larger one is "more square" because the border radius is a static 20dp regardless of the size of the drawable.

absolute border radius

I want to specify the radius relative to the size of the full drawable, so when it is drawn at different sizes each one appears as a scaled up/down version of the others.

relative border radius

I'm more familiar with CSS, where this can be done in one line:

border-radius: 20%;

I'm surprised to find Android lacking this CSS simplicity. Android does not recognize % as a unit.

<corners android:radius="20%" />

Is there some simple way to achieve my desired result in Android?

Upvotes: 11

Views: 3046

Answers (1)

Krabbe
Krabbe

Reputation: 31

You are right, there is no built in way. But you can achieve it programatically. A time ago I wrote this small class and it works for me

    public class CornerDrawable extends GradientDrawable {

    private float percent;

    @Override
    public void setBounds(int left, int top, int right, int bottom) {
        super.setBounds(left, top, right, bottom);
        setCornerRadius(getBounds().height() / percent);
    }

    @Override
    public void setBounds(@NonNull Rect bounds) {
        super.setBounds(bounds);
        setCornerRadius(getBounds().height() / percent);
    }

    /**
     * Sets the corner radius of each corner to the <code>percent</code> of the height of this drawable. For example, passing
     * <i>50</i> will result in a fully rounded side of the target view.
     *
     * @param percent The percentage of the height of the view to be rounded
     */
    public void setCornerRadiusPercent(float percent) {
        this.percent = 100 / percent;
    }
}

Then you only need to create an instance and configure it the way you want and set it on your target view. For example like this:

    //the view you want to apply the corner radius to
    View targetView = ...
    CornerDrawable cornerDrawable = new CornerDrawable();
    //pass your desired percent value
    cornerDrawable.setCornerRadiusPercent(20);
    // set the solid color from your xml above
    cornerDrawable.setColor(getResources().getColor(R.color.black, requireContext().getTheme()));
    targetView.setBackground(cornerDrawable);

The only drawback of this is, that you have to do all configuration programmatically, instead of using your drawable xml file.

Upvotes: 2

Related Questions