3

I want to draw something like in android, to use it as a button. How to do that? any links or suggestion? Is it a bezier curve?

enter image description here

Rohit5k2
  • 17,948
  • 8
  • 45
  • 57
joe fayyaz
  • 61
  • 6

1 Answers1

3

As stated in the comments, you can create a PNG and use it directly. If you want the sides to scale independently from the curve, you can 9-patch your image.

According to this post, you now have the option to define a path drawable in xml. But only for Lollipop and up.

Finally, you can create a base button and use the Path object to draw a quadratic curve. Example. I haven't tried it myself, but you should be able to fill the area below the bath Example 1, Example 2.

Edit:

I had a bit a time available to create an example of a Path implementation. In order to fill the section below the path, clipping needs to be used. This isn't an exact solution for you, but you should be able to get what you want by tweaking a few of the variables (x1, y1, x2, y2, x3, y3).

In my implementation I made use of a gradient instead of a solid colour, since it doesn't make a difference to the implementation, and it serves as a more general example.

public class PathView extends View
{
    private Paint paintFill;
    private Paint paintLine;
    private Paint paintClear;
    private Path  path;
    private int   colour;

    private float x0;
    private float y0;
    private float x1;
    private float y1;
    private float x2;
    private float y2;
    private float x3;
    private float y3;

    public PathView(Context context)
    {
        super(context);
    }

    public PathView(Context context, AttributeSet attrs)
    {
        super(context, attrs);
    }

    public PathView(Context context, AttributeSet attrs, int defStyleAttr)
    {
        super(context, attrs, defStyleAttr);
    }

    public PathView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes)
    {
        super(context, attrs, defStyleAttr, defStyleRes);
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom)
    {
        super.onLayout(changed, left, top, right, bottom);

        initialize();
    }

    private void initialize()
    {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2 && Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
        {
            // Path clipping uses hardware acceleration which is unavailable from 11 to 18
            // https://stackoverflow.com/questions/8895677/work-around-canvas-clippath-that-is-not-supported-in-android-any-more
            setLayerType(LAYER_TYPE_SOFTWARE, null);
        }

        paintFill = new Paint();
        paintFill.setAntiAlias(true);
        LinearGradient gradient = new LinearGradient(0, getHeight(), 0, 0, Color.WHITE, colour, Shader.TileMode.CLAMP); // Vertical gradient
        paintFill.setShader(gradient);

        paintLine = new Paint();
        paintLine.setColor(colour);
        paintLine.setStrokeWidth(1.5f);
        paintLine.setStrokeCap(Paint.Cap.ROUND);
        paintLine.setStyle(Paint.Style.STROKE);
        paintLine.setAntiAlias(true);

        paintClear = new Paint();
        paintClear.setColor(Color.WHITE);
        paintClear.setAntiAlias(true);
    }

    public int getColour()
    {
        return colour;
    }

    public void setColour(int colour)
    {
        this.colour = colour;

        initialize();
        invalidate();
    }

    public void setVars(float x1, float y1, float x2, float y2)
    {
        // When the vars changes, the path needs to be updated. 
        // In order to make clipping easier, we draw lines from [x0, y0] to 
        // [x0, getHeight] and [x3, y3] to [x3, getHeight].
        // This makes the fill section of the path everything below the path.

        path = new Path();

        float cx = getWidth() / 2;
        float cy = getHeight() / 2;

        this.x0 = 0;
        this.y0 = cy + y1;
        this.x1 = x1;
        this.y1 = cy + y1;
        this.x2 = x2;
        this.y2 = cy + y2;
        this.x3 = getWidth();
        this.y3 = cy + y2;

        // Move to bottom, draw up
        path.moveTo(this.x0, getHeight());
        path.lineTo(this.x0 - paintLine.getStrokeMiter(), this.y0);

        path.cubicTo(this.x1, this.y1, this.x2, this.y2, this.x3, this.y3);

        // Draw down
        path.lineTo(this.x3 + paintLine.getStrokeMiter(), getHeight());

        invalidate();
    }

    @Override
    public void draw(Canvas canvas)
    {
        super.draw(canvas);

        if (path != null && paintFill != null)
        {
            // Draw gradient background first, and then clip the irrelevant section away. 
            // This will let our gradient be uniform irrespective of the vars used.
            canvas.drawRect(x0, 0, x3, getHeight(), paintFill);

            canvas.save();
            canvas.clipPath(path, Region.Op.DIFFERENCE);
            canvas.drawRect(x0, 0, x3, getHeight(), paintClear);
            canvas.restore();

            canvas.drawPath(path, paintLine);
        }
    }
}

enter image description here

Community
  • 1
  • 1
Kevin
  • 1,626
  • 16
  • 30