My activity should look like this:
I'm not sure what's the best way to show the segment of the circle between top and bottom views.
I'd like to avoid saving the segment as image.
Is there a way to show it using drawable
xml (I've tried to achieve this using oval
, but I don't know how to make is so "flat")?
Maybe drawing on canvas
?
I think option 3 is the best, you can control exactly what you're drawing but you don't loose OOP karma points
OPTION 1
You can create a custom View
for your top View
and implement the drawing yourself like this, I'm subclassing RelativeLayout
here but you can subclass whatever View
you want
public class CurveBgRelativeLayout extends RelativeLayout {
public CurveBgRelativeLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
private Path path;
private Paint paint;
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setStyle(Paint.Style.FILL);
paint.setColor(0xffff0000);
path = new Path();
float horizontalOffset = w * .8f;
float top = -h * .8f;
float bottom = h;
RectF ovalRect = new RectF(-horizontalOffset, top, w + horizontalOffset, bottom);
path.lineTo(ovalRect.left, top);
path.arcTo(ovalRect, 0, 180, false);
path.setFillType(Path.FillType.INVERSE_EVEN_ODD);
}
@Override
protected void onDraw(Canvas canvas) {
if (path != null)
canvas.drawPath(path, paint);
super.onDraw(canvas);
}
}
and then in your xml layout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.example.CurveBgRelativeLayout
android:layout_width="match_parent"
android:background="#ffffffff"
android:layout_height="0dp"
android:layout_weight="1"/>
<View
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="#ffff0000"
/>
</LinearLayout>
OPTION 2
You can create an xml drawable as a background for your top View
, the only problem here is that the horizontal stretch of the circle is given with a size in dp, so it's not relative to the View
's size
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:height="40dp"
android:gravity="bottom">
<shape android:shape="rectangle">
<solid android:color="#ffff0000" />
</shape>
</item>
<item
android:width="500dp"
android:height="60dp"
android:gravity="bottom|center_horizontal"
android:top="-40dp">
<shape android:shape="oval">
<solid android:color="#ffffffff" />
</shape>
</item>
<item
android:height="30dp"
android:bottom="30dp"
android:gravity="bottom">
<shape android:shape="rectangle">
<solid android:color="#ffffffff" />
</shape>
</item>
</layer-list>
OPTION 3
public class CurveBottomDrawable extends Drawable {
private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
private Path path = new Path();
public CurveBottomDrawable(int color) {
paint.setStyle(Paint.Style.FILL);
paint.setColor(color);
}
@Override
public void draw(@NonNull Canvas canvas) {
paint.setStyle(Paint.Style.FILL);
paint.setColor(0xffff0000);
path.reset();
Rect bounds = getBounds();
float horizontalOffset = bounds.width() * .8f;
float top = -bounds.height() * .8f;
float bottom = bounds.height();
RectF ovalRect = new RectF(-horizontalOffset, top, bounds.width() + horizontalOffset, bottom);
path.lineTo(ovalRect.left, top);
path.arcTo(ovalRect, 0, 180, false);
path.setFillType(Path.FillType.INVERSE_EVEN_ODD);
canvas.drawPath(path, paint);
}
@Override
public void setAlpha(@IntRange(from = 0, to = 255) int alpha) {
paint.setAlpha(alpha);
}
@Override
public void setColorFilter(@Nullable ColorFilter colorFilter) {
paint.setColorFilter(colorFilter);
}
@Override
public int getOpacity() {
return PixelFormat.TRANSPARENT;
}
}
and then set it programmatically
myView.setBackground(new CurveBottomDrawable(0xffff0000));
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