How to remove border only from one side of the element?

19,250

Solution 1

As far as I understand it, there isn't an easy way of doing it. but if you use layer-list with an item that has the border and then one that doesn't with an offset from all the sides for which you want a border equal to the border width, you'd achieve that.

Let me make the xml for you representing the borderless bottom..

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
    <!-- Border -->
    <item>
        <shape>
            <solid android:color="#f000"></solid>
        </shape>
    </item>
    <!-- Body -->
    <item android:left="2dip"
          android:top="2dp"
          android:right="2dp">
        <shape>
            <solid android:color="#ffafafaf"></solid>
        </shape> 
    </item>
</layer-list>

As you can see, I'm telling the second item to be inset of the first one by two dp's on all sides except bottom (hence the no-border result on the bottom), there you go:

enter image description here

So essentially this isn't a border per-se, it's the shape from below (although you could add a border if you need dashed or dotted or whatever) being covered by a second item with would be the body of the button. All in the same drawable :)

This can be applied to any border you want to remove, by changing the values that the item is inset, for example, if I change the right in the Body item to bottom, the missing border would the right one since it's the one without the inset

Solution 2

This is a bit of a hack, but its possible to remove one or more borders using an inset drawable with negative values. Wrap the shape in an inset and apply a negative android:insetTop, android:insetBottom, android:insetLeft, or android:insetRight with abs value equal to the stroke width.

enter image description here

For example, to remove the bottom border from a rectangle with a 4dp stroke, use a android:insetBottom value of -4dp.

<?xml version="1.0" encoding="utf-8"?>
<inset xmlns:android="http://schemas.android.com/apk/res/android"
    android:insetBottom="-4dp">

    <shape android:shape="rectangle">
        <solid android:color="#FFFFFF" />
        <stroke android:width="4dp" android:color="#000000" />
        <corners android:radius="4dp" />
    </shape>

</inset>

This seems to work well as long as the shape's corners have a radius that is less than equal to the stroke width. Otherwise use the larger of the two values (the radius) when applying the inset in order to completely hide the rounded portions of the adjacent borders.

Solution 3

It's an xml trick. First you have to fill the layer with a specific color (Line Color). Then you have to fill it with another color (Background Color) while to push the drawing a little bit from the side you want to draw the line. Here is my code:

<layer-list xmlns:android="http://schemas.android.com/apk/res/android">

        <!-- First we have to create the line color (Black: #000000 and
           Set position to 0 from all sides, this will allow us
           even to to determine border size in any side (top,
           right, bottom, left) -->

    <item android:top="0dp"
        android:right="0dp"
        android:left="0dp"
        android:bottom="0dp">
        <shape android:shape="rectangle">
            <solid android:color="#000000"></solid>
        </shape>
    </item>

    <!-- Here we fill the content with our color, and I will
         push 1dp from the top so this size (top = 1dp) will
         keep the previous color and it will look like the border
         -->

    <item android:top="1dp"
        android:right="0dp"
        android:left="0dp"
        android:bottom="0dp">
        <shape android:shape="rectangle">
            <solid android:color="#f4f4f4"></solid>
        </shape>
    </item>
</layer-list>

https://i.stack.imgur.com/ifak8.jpg

Here how it looks:

enter image description here

Share:
19,250
anony_root
Author by

anony_root

Updated on June 08, 2022

Comments

  • anony_root
    anony_root almost 2 years

    I have:

    <stroke android:width="1px" android:color="#A6ACB1"/>
    

    I'd like to remove this border from the bottom (for example) of the element. Is it possible? (Eclipse suggests me only: color, width, dashWidth and dashGap).

  • anony_root
    anony_root almost 12 years
    Well, where do I have to place my styles? In the first <item>, right?
  • anony_root
    anony_root almost 12 years
    By the way, I'm trying to use it to EditText.
  • Juan Cortés
    Juan Cortés almost 12 years
    It doesn't matter to what view you apply it. The first item is only for the border, so you need to divide the style between those two. If you want a green background for instance, you'd add it to the second item, the one called "body" on my code
  • Fantasy_RQG
    Fantasy_RQG over 6 years
    great, Thanks, It very helpful
  • SouravOrii
    SouravOrii over 5 years
    Awesome. Worked like charm.
  • Egor
    Egor about 5 years
    Okay, but what about transparent background, if it is necessarily?
  • masterwok
    masterwok almost 5 years
    This works great as it allows you to keep the corner radius. However, when I try to set the insetTop attribute to a dimension attribute defined in a style, the inset doesn't work. When it's hardcoded it works..not sure why.
  • ice_chrysler
    ice_chrysler over 3 years
    Thank you for your answer. Using your template, I was able to achieve a similar effect. I needed to create a rectangle that has its left edge drawn bolder than all others. Achieved it using exactly what you did with slight changes: android:top=1dp android:right=1dp android:bottom=1dp android:left=8dp