How to make a pill shaped button in android? - android

I am not sure what to call this... pill shaped maybe. Googling for rounded corners turns up lots of posts of people wanting a rectangular button with rounded corners. This is a little different but more like 2 circles and a rectangle which I tried to draw it as.
I would like to make a button shaped something like the first image below but with text and an icon image in it by using an xml drawable background on an android :
I have tried this which looks ok but if the button length varies it does not scale and you end up with a rectangle and some other strange stuff.
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:left="40dp" android:top="0dp" android:bottom="0dp">
<shape android:shape="oval" >
<solid android:color="#666666"/>
<size android:width="40dp" android:height="40dp"></size>
</shape>
</item>
<item android:left="20dp" android:right="20dp">
<shape android:shape="rectangle" >
<solid android:color="#666666"/>
<size android:width="20dp" android:height="20dp"></size>
</shape>
</item>
<item android:right="40dp">
<shape android:shape="oval" >
<solid android:color="#666666"/>
<size android:width="40dp" android:height="40dp"></size>
</shape>
</item>
</layer-list>
I have tried to create my xml drawable like this also:
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<solid android:color="#666666" />
<corners android:radius="20dp"/>
<size android:height="20dp" android:width="60dp"></size>
</shape>
which looks like this:
I have looked at this persons example but when I do what he does my results are not completely rounded at the corners. They are more like the second image above.

You can try to save the following code to a drawable(e.g. pill_bg.xml):
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:dither="true"
android:shape="rectangle">
<corners android:radius="120dp" />
<solid android:color="#color/white" />
<stroke
android:width="1dp"
android:color="#efefef" />
<size
android:width="300dp"
android:height="120dp" />
</shape>
Take a look at size part and radius. Then apply the drawable to your view, for example:
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="250dp"
android:layout_height="60dp"
android:background="#drawable/pill_bg" />
As you can see, your view can have different sizes, the background will be scaled.

As of v1.1.0-beta01 of the Material Components Android library you can use MaterialButton and a shapeAppearance style to easily define a pill button that doesn't require you to know the height of the button beforehand or rely on guessing a radius value high enough to go halfway down the side of the button.
Simply define a style like this:
<style name="PillShapeAppearance">
<item name="cornerFamily">rounded</item>
<item name="cornerSize">50%</item>
</style>
and set it on your MaterialButton like this:
<com.google.android.material.button.MaterialButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
...
app:shapeAppearanceOverlay="#style/PillShapeAppearance"
/>
The key that every other answer I've looked at leaves out is to set cornerSize with a percent value so that the fraction value it supports is properly applied.

This resizes correctly for any view background.
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="1000dp" />
<solid android:color="#android:color/holo_red_dark" />
</shape>

Well you can make that button in any design program, also make one similar make it look like it is pressed then you make a selector drawable and assign it to the button background. That´s the way i do pretty awesome buttons

Related

Android - why does the background image make the buttons look so strange?

I am trying to use the Android Holo.Light theme and for some reason when I add a background image, it makes the buttons look very strange and see-through. Here is a screen shot:
Would anyone know why this happens? It looks very strange. Is it meant to be like that? Or am I doing something incorrectly?
When I had just Light as my theme, the same image was not see-through.
Thank you!
The default for Holo buttons are slightly opaque. Just set a background drawable for them!
Here's an example of a gray button with a 1px outline. Includes the pressed state. You will set this on the button with "android:background="#drawable/gray_btn":
#drawable/gray_btn.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" >
<shape>
<solid
android:color="#ffffff"
/>
<stroke
android:width="1dp"
android:color="#E3E3E3" />
<corners
android:radius="4dip" />
</shape>
</item>
<item>
<shape>
<solid
android:color="#edeff1"
/>
<stroke
android:width="1dp"
android:color="#E3E3E3" />
<corners
android:radius="4dip" />
</shape>
</item>

Drawing two strokes for Android ListView divider?

Is it possible to draw two strokes (one after another) for ListView divider?
I've tried the following drawable, but it only shows the first stroke:
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="line">
<stroke
android:color="#eeeeee"
/>
<size
android:height="1px"
/>
<stroke
android:color="#c1c1c1"
/>
<size
android:height="1px"
/>
</shape>
Yes, it is possible. If you want to create it with shape drawables, you have to do it differently. A shape drawable can contain just one shape, one line in your case. You can combine two shapes in layer list drawable. Drawable in the layer list are drawn one above another, the last one at the top. To create two lines you just have to set the proper padding for each of the lines, so that both the lines are visible. The resulting drawable will be something like this (I made the lines thicker in the example):
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:bottom="2dp">
<shape android:shape="line">
<stroke
android:color="#eeeeee"
android:width="2dp"
/>
<size
android:height="4dp"
/>
</shape>
</item>
<item android:top="2dp">
<shape android:shape="line">
<stroke
android:color="#c1c1c1"
android:width="2dp"
/>
<size
android:height="4dp"
/>
</shape>
</item>
</layer-list>
If you want the 2 strokes to be really thin, let's say 1px height each, I tried the solution above and I could't make it.
I found it much easier painting a litte image (1x2) with the 2 pixels with the desired colors, and then define the image in the divider doing:
android:divider="#drawable/myTinyDivider"
Hope this helps someone.

Advanced Custom Widget

I googled a lot and spent many hours trying to figure out how to create custom Android UI widgets (in code and xml). But there are some limitations I don't know how to bypass. Therefore I mocked up an imaginary button and would like to know how to implement it.
This would help me a lot and I'm sure that I'm not the only one that has problems creating custom Android widgets.
About the multi-colored background, I was successful at these using shape drawables.
For example to define a grey solid zone, then a gradient transitioning to black, and a black solid zone:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="rectangle">
<corners android:radius="10px" />
<solid android:color="#FF444444"/>
</shape>
</item>
<item
android:left="45dp">
<shape android:shape="rectangle">
<gradient
android:angle="0"
android:centerX="15%"
android:startColor="#FF444444"
android:centerColor="#FF000000"
android:endColor="#FF000000"
android:type="linear"/>
</shape>
</item>
<item>
<shape android:shape="rectangle">
<corners android:radius="10px" />
<stroke
android:width="2px"
android:color="#FF444444" />
<solid android:color="#00000000"/>
</shape>
</item>
</layer-list>
The cool thing here is the layered shapes (items). It should allow you to define a yellow triangle, a red triangle, and a green rectangle.
The above layout renders into the following:
(the icons and text not being rendered by the above layout)
If you choose to create a custom widget I recommend to check out a most similar standard widget from the android sources and modify them
Create a shape for background:
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#color/GREEN"/>
<stroke
android:width="2dp"
android:color="#color/GREEN"/>
</shape>
Then Create a shape with layer-list that show your image:
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="rectangle">
<solid android:color="#color/GREEN"/>
</shape>
</item>
<item
android:left="15dp"
android:top="15dp"
android:right="15dp"
android:bottom="15dp"
android:drawable="#drawable/ic_image" />
</layer-list>
Finally, you can use above shapes in a button:
<Button
android:id="#+id/btnFavorite"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="15dp"
android:layout_below="#id/btnWorkout"
android:background="#drawable/selector_main_button"
android:drawableRight="#drawable/shape_favorite"
android:gravity="center"
android:text="#string/favorite"
android:textSize="#dimen/font_7"
android:textColor="#color/ORANGE"
android:textStyle="bold"
android:onClick="onClick"/>
Even, it should mentioned that you can use first shape as a selector.

How can I build such button?

I need to implement such button for my Android app. It would be great to do this without using full image as button.
I've done almost the same button using <shape> with <gradient>. The only thing I need is to add bottom blue button shadow and include image.
Is it possible?
Thanks in advance.
You can do this by combining Shape Drawables inside a Layered Drawable. To do so, you'll have 3 xml files as below:
button.xml (the one you already have i guess)
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<corners android:radius="16dp" />
<gradient
android:angle="270"
android:centerColor="#FFFFFF"
android:endColor="#CAEBF8"
android:startColor="#FFFFFF"
android:type="linear" />
<padding
android:bottom="8dp"
android:left="8dp"
android:right="8dp"
android:top="8dp" />
<stroke
android:width="2dp"
android:color="#FFFFFF" />
</shape>
button_bg.xml (to add the blue border below the button)
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<corners android:radius="16dp" />
<solid android:color="#6FC8F1" />
</shape>
layered_button.xml (to combine the previous xml, and the drawable to use as background on your button)
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:drawable="#drawable/button_bg"/>
<item
android:bottom="2dp"
android:drawable="#drawable/button"/>
</layer-list>
You'll find more information on the Layer List in the Drawables Documentation
Make your button's android:background attribute to point your desired image. Create your image with the text and the little person icon. It's not possible to put a text and an image at the same time inside a button.
For the blue shadow, you can either include it in your image or achieve the same result with the gradient attribute as you already said in your question.
For the image, you should use
android:drawableRight
As for the shadow I'm not sure how this is achieved.

Android shape within a shape

I want to have a shape element with a two color border outline. I can do a single color outline using the solid element, but this only allows me to draw a single line. I tried using two stroke elements within my shape, but that didn't work either.
Is there a way to either draw a shape within a shape or draw two lines around my shape (which has rounded corners, BTW).
I found that the <layer-list> is the best approach. Like this:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:left="6dp"
android:right="6dp">
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<stroke
android:width="3dp"
android:color="#000000" />
</shape>
</item>
<item
android:bottom="1dp"
android:left="8dp"
android:right="8dp"
android:top="1dp">
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners
android:bottomLeftRadius="2dp"
android:bottomRightRadius="2dp"
android:topLeftRadius="2dp"
android:topRightRadius="2dp" />
<solid android:color="#android:color/white" />
<stroke
android:width="1dp"
android:color="#BDBDBD" />
</shape>
</item>
</layer-list>
You then need to put the proper margins on your listView row layout, but it works quite nicely.
so i have a work around but its ugly. the work around is to wrap my element inside another container element. i.e.
<RelativeLayout ... android:background="#drawable/outer">
<ListView ... android:background="#drawable/inner" />
</RelativeLayout>

Categories

Resources