androidandroid-studioandroid-shapeandroid-shapedrawable

Recreate shape as in xml file by using code and set width programmatically


I already have shape code and now I need to draw the same programmatically and set its width according to the length of texts in an array. I am not able to reproduce the same using path data.

This is the code:

<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:viewportWidth="2778"
    android:viewportHeight="1250"
    android:width="250.0002dp"
    android:height="112.5dp">
    <path
        android:pathData="M2764 1250L0 1250 0 0l2256 0 4 4 513 468 4 4 0 774 -14 0 0 0zm-2737 -27l2723 0 0 -736L2245 26 27 26 27 1222Z"
        android:fillColor="#FF6E00" />
</vector>

Output shape should be this

Please help me on this..


Solution

  • Method 1: By Creating custom shape:

    import android.graphics.Canvas;
    import android.graphics.Color;
    import android.graphics.Paint;
    import android.graphics.Path;
    import android.graphics.drawable.shapes.Shape;
    
    public class RectangleCutCorner extends Shape {
        private int backgroundColor  = Color.BLACK;
        private float strokeWidth = 1.0f;
        private static final float CORNER = 35.0f;
    
        private final Paint border = new Paint();
        private final Path  path;
    
        public RectangleCutCorner() {
            path = new Path();
            border.setColor(backgroundColor);
            border.setStyle(Paint.Style.FILL);
            border.setStrokeWidth(strokeWidth);
            border.setAntiAlias(true);
            border.setDither(true);
            border.setStrokeJoin(Paint.Join.ROUND);
            border.setStrokeCap(Paint.Cap.ROUND);
        }
    
        //for setting stroke width programmatically
        public void setStrokeWidthToLayout(float strokeWidth){
            this.strokeWidth = strokeWidth;
            border.setStrokeWidth(strokeWidth);
        }
    
        //for setting background/stroke color programmatically
        public void setBackgroundColor(int backgroundColor){
            this.backgroundColor = backgroundColor;
            border.setColor(backgroundColor);
        }
    
        //for setting background filled or not programmatically
        public void setBackgroundFill(boolean isFilled){
          if(isFilled){
              border.setStyle(Paint.Style.FILL);
          }else{
              border.setStyle(Paint.Style.STROKE);
          }
        }
    
        @Override
        protected void onResize(float width, float height) {
            super.onResize(width, height);
    
            float dx = strokeWidth/2.0f;
            float dy = strokeWidth/2.0f;
            float x  = dx;
            float y  = dy;
            float w  = width  - dx;
            float h  = height - dy;
            path.reset();
            path.moveTo(x + CORNER,y);
            path.lineTo(w - CORNER,y);
            path.lineTo(w,y + CORNER);
            path.lineTo(w, h);
            path.lineTo(x + CORNER,h);
            path.lineTo(dx,h);
            path.lineTo(dx,y);
            path.close();
        }
        
        @Override
        public void draw(Canvas canvas, Paint paint) {
            // TODO Auto-generated method stub
            canvas.drawPath(path,border);
        }
    }
    

    How to use this programmatically:

        RectangleCutCorner rectangleCutCorner = new RectangleCutCorner();
        // set color
        rectangleCutCorner.setBackgroundColor(R.color.black);
        //set fill background (true/false)
        rectangleCutCorner.setBackgroundFill(false);
        // set stroke width
        rectangleCutCorner.setStrokeWidthToLayout(2.5f);
        // set background to view
        view.setBackground(new ShapeDrawable(rectangleCutCorner));
    

    Output for above code is:

    enter image description here

    Method 2: By Using Material Shape Drawable:

    Add this dependency into build.gradle(app) file:

    implementation 'com.google.android.material:material:1.3.0'

    How to use:

        ShapeAppearanceModel shapeAppearanceModel = new ShapeAppearanceModel()
                .toBuilder()
                .setTopRightCorner(CornerFamily.CUT, 20)
                .build();
        MaterialShapeDrawable shapeDrawable = new MaterialShapeDrawable(shapeAppearanceModel);
        int[][] states = new int[][] {
                new int[] { android.R.attr.state_enabled},
        };
        int[] colors = new int[] {
                Color.WHITE,
        };
        ColorStateList myList = new ColorStateList(states, colors);
        // set background to drawable
        shapeDrawable.setFillColor(myList);
        // set stroke and to view
        shapeDrawable.setStroke(1.5f, Color.BLACK);
        // set background to view
        ViewCompat.setBackground(tvUrl, shapeDrawable);
    

    Output for above code is:

    enter image description here