57

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

Cœur
  • 37,241
  • 25
  • 195
  • 267
Dory
  • 7,462
  • 7
  • 33
  • 55

7 Answers7

61

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

Sanket Kachhela
  • 10,861
  • 8
  • 50
  • 75
21

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>
Community
  • 1
  • 1
Linh
  • 57,942
  • 23
  • 262
  • 279
  • how to do with app arrow (traingle with up arrow) i tried with this code but i didn' t get, can u please tell me? – uma Jun 15 '18 at 06:22
6

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.

Jessicardo
  • 826
  • 1
  • 8
  • 12
  • 9
    I am only saying this since you emphasize on it being a clean solution, Do not create so many objects in onDraw, since the goal is to do this 60 times each second. – LostPuppy Jan 13 '16 at 00:35
  • 2
    I would go one step further and say don't create **any** objects inside `onDraw` – tir38 May 03 '16 at 20:29
  • Well those objects could be removed and replaced with primitive variables for x and y for each path . It's just to avoid having meaningless values inside the lineTo() method. – Jessicardo Aug 08 '16 at 09:54
1

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.

Aman Agnihotri
  • 2,973
  • 1
  • 18
  • 22
  • Can we change of image color dynamically? – Dory Feb 26 '14 at 13:23
  • You can use color filters to make changes to the way an image looks. If you have a single colored image, you can change it to any color you like if you use appropriate filtering on it. – Aman Agnihotri Feb 26 '14 at 13:27
  • Yes drawable would be of single color only. And I need to change it to different colors dynamically. I think you are suggesting me to use `setColorFilter()` for changing image to new color. Am I right. – Dory Feb 26 '14 at 13:30
  • Yeah. You can look for color filtering [here](http://stackoverflow.com/a/10141607/2592326). Hope it helps. :) – Aman Agnihotri Feb 26 '14 at 13:32
  • 1
    Thnks buddy for guiding :) – Dory Feb 27 '14 at 05:21
1

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

<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
Hitesh Sahu
  • 41,955
  • 17
  • 205
  • 154
0

Use Canvas in onDraw method inside custom View class.

Other way is to use Path class.

Prettygeek
  • 2,461
  • 3
  • 22
  • 44
0

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

Phantômaxx
  • 37,901
  • 21
  • 84
  • 115
Aamirkhan
  • 5,746
  • 10
  • 47
  • 74
  • I cannot use xmls for it.. as i need to change the color of drawable dynamically.. – Dory Feb 26 '14 at 13:25
  • @Jewel Your image color will change but you can give image border shape with this xml, what's wrong with that? – Aamirkhan Feb 26 '14 at 13:49