Android how to create triangle and rectangle shape programmatically?

AndroidShapedrawable

Android Problem Overview


How can we create ballon drawable shape as below. where we can change the color of it dynamically. enter image description here

Android Solutions


Solution 1 - Android

Here it is XML for triangle and rectangle. save it inside drawable folder.

triangle.xml

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
    <item >
        <rotate
            android:fromDegrees="45"
            android:toDegrees="45"
            android:pivotX="-40%"
            android:pivotY="87%" >
            <shape
                android:shape="rectangle"  >
                <stroke android:color="@android:color/transparent" android:width="10dp"/>
                <solid
                    android:color="#000000"  />
            </shape>
        </rotate>
    </item>
</layer-list>

rectangle.xml

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
    <item> 
    <shape android:shape="rectangle">
      <solid android:color="#B2E3FA" /> 
    </shape>
  </item>
</layer-list>

and layout for shape you require.

<RelativeLayout
        android:id="@+id/rlv1"
        android:layout_width="150dp"
        android:layout_height="50dp"
        android:background="@drawable/rectangle" />
    
    <RelativeLayout
        android:id="@+id/rlv2"
        android:layout_width="50dp"
        android:layout_height="50dp"  
        android:layout_below="@+id/rlv1"
        android:background="@drawable/triangle"
        android:rotation="180" />

enter image description here

set margin according you required.

Source

Solution 2 - Android

If you want a border for your layout

enter image description here

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/linear_root"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    >

    <TextView
        android:id="@+id/text_message"
        android:layout_width="100dp"
        android:layout_height="wrap_content"
        android:background="@drawable/bg_rectangle"
        android:layout_marginLeft="20dp"
        android:layout_marginRight="20dp"
        android:layout_marginTop="20dp"
        android:padding="8dp"
        android:text="Abc"
        />

    <ImageView
        android:id="@+id/image_arrow"
        android:layout_marginTop="-1.5dp"
        android:layout_width="16dp"
        android:layout_height="16dp"
        android:layout_gravity="center_horizontal"
        android:background="@drawable/icon_arrow_down"
        />
</LinearLayout>

bg_rectangle

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <solid android:color="#eaeaea" />
    <stroke
        android:width="1dp"
        android:color="#f00" />
    <corners android:radius="8dp" />

</shape>

icon_arrow_down, or you can create triangle by vector like here

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">

    <item>
        <rotate
            android:fromDegrees="45"
            android:pivotX="135%"
            android:pivotY="15%"
            android:toDegrees="45"
            >
            <shape android:shape="rectangle">
                <solid android:color="#eaeaea"/>
                <stroke
                    android:width="1dp"
                    android:color="#f00" />
            </shape>
        </rotate>
    </item>
</layer-list>

Solution 3 - Android

The clean and right way to do this whilst keeping it dynamic is to extend the View class.

Then in the onDraw you would do something like this:

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);

    drawBackground(canvas);
}

private void drawBackground(Canvas canvas) {
    int width = (int) mWidth;
    int height = (int) mHeight;

    Point a = new Point(0, 0);
    Point b = new Point(width, 0);
    Point c = new Point(width, height - mPointHeight);//mPointedHeight is the length of the triangle... in this case we have it dynamic and can be changed.
    Point d = new Point((width/2)+(mPointedHeight/2), height - mPointHeight);
    Point e = new Point((width/2), height);// this is the sharp point of the triangle
    Point f = new Point((width/2)-(mPointedHeight/2), height - mPointHeight);
    Point g = new Point(0, height - mPointHeight);

    Path path = new Path();
    path.moveTo(a.x, a.y);
    path.lineTo(b.x, b.y);
    path.lineTo(c.x, c.y);
    path.lineTo(d.x, d.y);
    path.lineTo(e.x, e.y);
    path.lineTo(f.x, f.y);
    path.lineTo(g.x, g.y);

    canvas.drawPath(path, mPointedBackgroundPaint);// mPointedBackgroundPaint is whatever color you want as the fill.
}

There you go, no unnecessary layering or code that isn't dynamic or clean. You could also add the text in the box too.

Solution 4 - Android

Use a triangle image and a rectangular image and mathematically align them in the above mentioned format. Use color filtering to dynamically change its color.

You can even draw them on a custom view, using vector graphics, using custom colors, and that would be another way of solving this problem.

Solution 5 - Android

Create custom view and draw traingle with canvas

package com.example.dickbutt;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.view.View;

public class TriangleShapeView extends View {

	public int colorCode = Color.MAGENTA;

	public int getColorCode() {
		return colorCode;
	}

	public void setColorCode(int colorCode) {
		this.colorCode = colorCode;
	}

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

	public TriangleShapeView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
	}

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

	protected void onDraw(Canvas canvas) {
		super.onDraw(canvas);

		int w = getWidth() / 2;
		int h = getHeight() / 2;

		Path path = new Path();
		path.moveTo(0, 0);
		path.lineTo(w, 2 * h);
		path.lineTo(2 * w, 0);
		path.lineTo(0, 0);

		path.close();

		Paint p = new Paint();
		p.setColor(colorCode);
		p.setAntiAlias(true);

		canvas.drawPath(path, p);
	}
}

Result

enter image description here

Usage

http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" tools:context="com.example.dickbutt.MainActivity" >

<TextView
    android:id="@+id/progress_value"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentTop="true"
    android:layout_centerHorizontal="true"
    android:background="@android:color/holo_purple"
    android:gravity="center_horizontal"
    android:text="200,0000000"
    android:textColor="#fff" />

<com.example.dickbutt.TriangleShapeView
    android:id="@+id/textView1"
    android:layout_width="10dp"
    android:layout_height="20dp"
    android:layout_below="@+id/progress_value"
    android:layout_centerHorizontal="true"
    android:background="@drawable/rectangle"
    android:gravity="center_horizontal"
    android:textSize="10sp" />

Advantages

  • Change shape according to width and height of view .
  • Highly customization possible.
  • Look cleaner

Solution 6 - Android

Use Canvas in onDraw method inside custom View class.

Other way is to use [Path] 2 class.

Solution 7 - Android

First you can create one xml inside drawable folder

That xml will be responsible for the border color of rectangle shape

You can create such border shape with below code

<?xml version="1.0" encoding="utf-8"?>
 <layer-list xmlns:android="http://schemas.android.com/apk/res/android">
  <item> 
    <shape android:shape="rectangle">
      <solid android:color="#B2E3FA" /> 
    </shape>
  </item>   
    <item android:left="5dp" android:bottom="5dp"  android:top="5dp" >  
     <shape android:shape="rectangle"> 
      <solid android:color="#D8D8D8" />
    </shape>
   </item>    
 </layer-list> 

well this will create a required border to rectangle shape, you need to assign background of that rectangle shape with this drawable like this

android:background="@drawable/bg"

where bg is xml file name which has been saved on drawable folder

After that you need to put that triangle exactly below to rectangle object.

I hope you understood my logic

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionDoryView Question on Stackoverflow
Solution 1 - AndroidSanket KachhelaView Answer on Stackoverflow
Solution 2 - AndroidLinhView Answer on Stackoverflow
Solution 3 - AndroidJessicardoView Answer on Stackoverflow
Solution 4 - AndroidAman AgnihotriView Answer on Stackoverflow
Solution 5 - AndroidHitesh SahuView Answer on Stackoverflow
Solution 6 - AndroidPrettygeekView Answer on Stackoverflow
Solution 7 - AndroidAamirkhanView Answer on Stackoverflow