简体   繁体   中英

Android how to create triangle and rectangle shape programmatically?

How can we create ballon drawable shape as below. where we can change the color of it dynamically. 在此输入图像描述

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" />

在此输入图像描述

set margin according you required.

Source

If you want a border for your layout

在此输入图像描述

<?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>

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.

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.

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

在此输入图像描述

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

Use Canvas in onDraw method inside custom View class.

Other way is to use Path class.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM