Am trying to make a custom drawable using xml, like the attached image
Below are two approach i have done,
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="30dp" />
<solid android:color="@color/colorAccent" />
<stroke
android:width="2dp"
android:color="@color/colorAccent" />
<gradient
android:angle="135"
android:endColor="#000"
android:startColor="#ffff"
android:type="linear" />
</shape>
By doing like this i can get the effect right, but the colors seems to be merged, I want two colors without any merge effect, then i tried like this,
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@color/white">
<shape android:shape="oval">
<corners android:radius="@dimen/size_30dp" />
</shape>
</item>
<item>
<rotate
android:fromDegrees="35"
android:pivotX="0%"
android:pivotY="100%">
<shape android:shape="rectangle">
<solid android:color="@color/textColorGreyExtraLight" />
</shape>
</rotate>
</item>
</layer-list>
This approach actually messed up the UI, also i have compromise on the rounded edges,
So i there any way i can draw this effect using XML?
Any kind of help will be greatly appreciated.
FYI The width and height of drawable will vary, so the diagonal should be always left bottom edge to right top edge.
Thanks
Try this:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<stroke android:color="#0a0909"
android:width="2dp"/>
<corners android:radius="20dp"/>
<gradient android:angle="45"
android:type="linear"
android:startColor="#d61a1a"
android:endColor="#19f269"
android:useLevel="false"/>
<size android:height="250dp"
android:width="250dp"/>
</shape>
While you asked for an XML based solution, I was intrigued to build a custom Drawable
to solve your issue. It basically just draws two shapes using custom paths and a border around them. If you add setters for the colors or make them constructor parameters, you'll get the flexibility you need for when the applications theme changes. Feel free to ignore this if XML is the way to go for you, I had fun building it. :)
It looks like this:
public class CustomDrawable extends Drawable {
private final int mBorderWidth;
private final int mCornerRadius;
private final Paint mBorderPaint = new Paint();
private final Paint mTopLeftShapePaint = new Paint();
private final Paint mBottomRightShapePaint = new Paint();
private final RectF mBorderRect = new RectF();
private final Path mTopLeftShapePath = new Path();
private final Path mBottomRightShapePath = new Path();
public CustomDrawable() {
mBorderWidth = 8;
mCornerRadius = 64;
mTopLeftShapePaint.setColor(Color.parseColor("#00a2e8"));
mTopLeftShapePaint.setStyle(Paint.Style.FILL);
mTopLeftShapePaint.setAntiAlias(true);
mBottomRightShapePaint.setColor(Color.parseColor("#3f48cc"));
mBottomRightShapePaint.setStyle(Paint.Style.FILL);
mBottomRightShapePaint.setAntiAlias(true);
mBorderPaint.setColor(Color.parseColor("#3f48cc"));
mBorderPaint.setStyle(Paint.Style.STROKE);
mBorderPaint.setStrokeWidth(mBorderWidth);
mBorderPaint.setAntiAlias(true);
}
@Override
protected void onBoundsChange(Rect bounds) {
super.onBoundsChange(bounds);
mBorderRect.set(bounds);
mBorderRect.inset(mBorderWidth / 2, mBorderWidth / 2);
calculatePaths();
}
private void calculatePaths() {
// Calculate position of the four corners
RectF topLeftCorner = new RectF(mBorderRect.left, mBorderRect.top, mBorderRect.left + 2 * mCornerRadius, mBorderRect.top + 2 * mCornerRadius);
RectF topRightCorner = new RectF(mBorderRect.right - 2 * mCornerRadius, mBorderRect.top, mBorderRect.right, mBorderRect.top + 2 * mCornerRadius);
RectF bottomLeftCorner = new RectF(mBorderRect.left, mBorderRect.bottom - 2 * mCornerRadius, mBorderRect.left + 2 * mCornerRadius, mBorderRect.bottom);
RectF bottomRightCorner = new RectF(mBorderRect.right - 2 * mCornerRadius, mBorderRect.bottom - 2 * mCornerRadius, mBorderRect.right, mBorderRect.bottom);
// Calculate position of intersections of diagonal line and top-right / bottom-left corner
PointF topRightCornerIntersection = calculateCircleCoordinate(topRightCorner.centerX(), topRightCorner.centerY(), 315);
PointF bottomLeftCornerIntersection = calculateCircleCoordinate(bottomLeftCorner.centerX(), bottomLeftCorner.centerY(), 135);
// Build top left shape
mTopLeftShapePath.reset();
mTopLeftShapePath.moveTo(topLeftCorner.left, topLeftCorner.centerY());
mTopLeftShapePath.lineTo(bottomLeftCorner.left, bottomLeftCorner.centerY());
mTopLeftShapePath.arcTo(bottomLeftCorner, -180, -45, false);
mTopLeftShapePath.lineTo(topRightCornerIntersection.x, topRightCornerIntersection.y);
mTopLeftShapePath.arcTo(topRightCorner, -45, -45, false);
mTopLeftShapePath.lineTo(topLeftCorner.centerX(), topLeftCorner.top);
mTopLeftShapePath.arcTo(topLeftCorner, -90, -90, false);
// Build bottom right shape
mBottomRightShapePath.reset();
mBottomRightShapePath.moveTo(bottomLeftCorner.centerX(), bottomLeftCorner.bottom);
mBottomRightShapePath.lineTo(bottomRightCorner.centerX(), bottomRightCorner.bottom);
mBottomRightShapePath.arcTo(bottomRightCorner, 90, -90, false);
mBottomRightShapePath.lineTo(topRightCorner.right, topRightCorner.centerY());
mBottomRightShapePath.arcTo(topRightCorner, 0, -45, false);
mBottomRightShapePath.lineTo(bottomLeftCornerIntersection.x, bottomLeftCornerIntersection.y);
mBottomRightShapePath.arcTo(bottomLeftCorner, 135, -45, false);
}
private PointF calculateCircleCoordinate(float centerX, float centerY, double angdeg) {
double angle = Math.toRadians(angdeg);
double x = centerX + mCornerRadius * Math.cos(angle);
double y = centerY + mCornerRadius * Math.sin(angle);
return new PointF((float) x, (float) y);
}
@Override
public void draw(@NonNull Canvas canvas) {
canvas.drawPath(mTopLeftShapePath, mTopLeftShapePaint);
canvas.drawPath(mBottomRightShapePath, mBottomRightShapePaint);
canvas.drawRoundRect(mBorderRect, mCornerRadius, mCornerRadius, mBorderPaint);
}
@Override
public void setAlpha(int alpha) {
}
@Override
public void setColorFilter(@Nullable ColorFilter colorFilter) {
}
@Override
public int getOpacity() {
return PixelFormat.UNKNOWN;
}
}
Disclaimer: this quick draft doesn't cover edge-cases, e.g. a corner radius that is too large for the given view bounds.
I have a library to do that. Basicilly I draw 2 Triangles and you can specify the direction left corner to right corner or right corner to left corner.
Library
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