Android: Make a button with triangle shape using xml definitions (drawable)

14,258

Solution 1

If someone still has issues with this :

  1. xml:

    <item android:top="45dp">
        <shape>
            <size android:height="100dp" android:width="90dp"/>
            <solid android:color="@android:color/holo_orange_light" />
        </shape>
    </item>
    <item android:top="36dp" android:left="11dp">
        <rotate
            android:fromDegrees="45"
            android:toDegrees="0"
            android:pivotX="80%"
            android:pivotY="20%" >
            <shape>
                <size android:width="40dp"
                    android:height="30dp"/>
                <stroke android:color="@android:color/holo_orange_light" android:width="1dp"/>
                <solid android:color="@android:color/holo_orange_light" />
            </shape>
        </rotate>
    </item>
    </layer-list>
    
  2. override TextView and use it in your layout:

    public class CustomTextView extends TextView {
    
        private int mWidth;
        private int mHeight;
    
    
        public CustomTextView(Context context, AttributeSet attrs)  {
            super(context, attrs);
    
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
    
           super.onDraw(canvas);
            Paint mPaint = new Paint();
            int color = getResources().getColor(R.color.YourColor);
    
            mPaint.setColor(color);
            Path mPath = new Path();
            mPath.moveTo(.0f, this.getHeight());
            mPath.lineTo(0.8f * this.getWidth(), this.getHeight());
            mPath.lineTo(this.getWidth(), 0.5f * this.getHeight());
            mPath.lineTo(0.8f * this.getWidth(), .0f);
            mPath.lineTo(.0f, .0f);
            mPath.lineTo(.0f, this.getHeight());
    
            canvas.clipPath(mPath);
            canvas.drawPath(mPath,mPaint);
    
    
        }
    }
    

Regarding the xml example: there are two rectangles overlapping.You have to play around with the values a lot and this makes it difficult to use on different views. I think using a custom view is the best solution in this case.

Solution 2

You can achieve it also using a MaterialButton included in the Material Components library.

Add the MaterialButton in your layout then:

  • use the app:icon attribute to add an icon on the left
  • apply the style Widget.MaterialComponents.Button.Icon provided by the library
  • define a custom shape using the app:shapeAppearanceOverlay attribute (it requires v.1.1.0)

Something like:

   <com.google.android.material.button.MaterialButton
        style="@style/Widget.MaterialComponents.Button.Icon"
        app:icon="@drawable/ic_add_24px"
        android:text="..."
        app:shapeAppearanceOverlay="@style/CustomShapeAppearanceOverlay.Button"
        .../>

where the shapeAppearanceOverlay is defined in your styles.xml:

  <style name="CustomShapeAppearanceOverlay.Button" parent="">
    <item name="cornerFamily">rounded</item>
    <item name="cornerSizeTopLeft">0dp</item>
    <item name="cornerSizeBottomLeft">0dp</item>

    <item name="cornerFamilyTopRight">cut</item>
    <item name="cornerFamilyBottomRight">cut</item>
    <item name="cornerSizeTopRight">18dp</item>
    <item name="cornerSizeBottomRight">18dp</item>
  </style>

The final result:

enter image description here

Share:
14,258

Related videos on Youtube

Pepa Zapletal
Author by

Pepa Zapletal

http://mixedapps.cz/

Updated on October 02, 2022

Comments

  • Pepa Zapletal
    Pepa Zapletal about 1 year

    I want create this using button (TextView) by using XML definiton:

    my image

    In layout of the Activity I have:

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@drawable/button_arrow" <!-- I NEED IMPLEMENT THIS -->
            android:clickable="true"
            android:drawablePadding="7dp"
            android:gravity="center"
            android:drawableLeft="@drawable/music_cloud"
            android:onClick="exportSong"
            android:padding="20dp"
            android:text="@string/export_upload"
            android:textAppearance="?android:attr/textAppearanceMedium"
            android:textColor="@color/dark_yellow_text_color"
            android:textStyle="bold" />
    

    I founded several posts:

    making-a-triangle-shape-using-xml-definitions

    Android triangle (arrow) defined as an XML shape

    or Android - make an arrow shape with xml

    I tried modify several XML definition but nothing was good. Is there some easy way how to implement this shape? Also it should have a transparent background.

  • SMBiggs
    SMBiggs about 8 years
    Sometimes you just have to breakdown and make a custom View. Thanks for making a nice and simple example.
  • Oussaki
    Oussaki almost 7 years
    but seems like the text Property will be lost if we use your code !
  • Oussaki
    Oussaki almost 7 years
    Just put super.onDraw(canvas); call at the end of onDraw Method , so that will make this code work properly
  • Shivam Kumar
    Shivam Kumar about 4 years
    Where we find cornerFamily at all
  • Gabriele Mariotti
    Gabriele Mariotti about 4 years
    @ShivamKumar It requires material components v.1.1.0