18

My goal:

Figure 1: The Goal
Figure 1: The Goal

So, before I knew about the issue, here's what I tried.

First, a base layout:

<LinearLayout
    android:orientation="horizontal"
    android:layout_below="@id/heading"
    android:layout_marginTop="10dp"
    android:layout_width="@dimen/horizontal_two_button_width"
    android:layout_height="@dimen/button_height_small" >

    <Button
        android:id="@+id/button_one"
        android:layout_width="0dp"
        android:layout_weight="1.0"
        android:layout_height="fill_parent"
        android:padding="10dp"
        style="@style/ButtonText"
        android:background="@drawable/button_left_green" />

    <Button
        android:id="@+id/button_two"
        android:layout_width="0dp"
        android:layout_weight="1.0"
        android:layout_height="fill_parent"
        android:padding="10dp"
        style="@style/ButtonText"
        android:background="@drawable/button_right_green" />      

</LinearLayout>

The 'button_left_green' drawable:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/button_left_green_pressed"
        android:state_pressed="true" />
    <item android:drawable="@drawable/button_left_green_focused"
        android:state_focused="true" />
    <item android:drawable="@drawable/button_left_green_default" />
</selector>

And, for example, the 'button_left_green_default' drawable:

<?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="@color/shadow" />
            <corners
                android:radius="5dp"
                android:topLeftRadius="5dp"
                android:topRightRadius="0dp"
                android:bottomLeftRadius="5dp"
                android:bottomRightRadius="0dp" />      
        </shape>
    </item>
    <item
        android:bottom="19dp"
        android:top="1dp"
        android:left="1dp"
        android:right="1dp" >

        <shape android:shape="rectangle">
            <gradient
                android:startColor="@color/button_left_green_top_gradient_start"
                android:endColor="@color/button_left_green_top_gradient_end"
                android:angle="270" />

            <corners
                android:radius="5dp"
                android:topLeftRadius="5dp"
                android:topRightRadius="0dp"
                android:bottomLeftRadius="0dp"
                android:bottomRightRadius="0dp" />
        </shape>
    </item>

    <item
        android:top="19dp"
        android:bottom="1dp"
        android:left="1dp"
        android:right="1dp" >

        <shape android:shape="rectangle" >
            <solid android:color="@color/button_left_green_bottom_gradient" />

            <corners
                android:radius="5dp"
                android:topLeftRadius="0dp"
                android:topRightRadius="0dp"
                android:bottomLeftRadius="5dp"
                android:bottomRightRadius="0dp" />
        </shape>
    </item>
</layer-list>

So, after all that, I got the image in Figure 2:
Figure 2: Take One
Figure 2: Take One

After double-checking the definition of the bottom corners, I was convinced I was crazy until I found the known issue: http://code.google.com/p/android/issues/detail?id=9161

I'd rather not just swap them, 'cause then if/when the issue is fixed, the buttons will be broken in newer versions.

One idea I had was to leave the actual buttons as regular rectangles (i.e. no corner radii) and wrapping both buttons with a rounded rectangle. I added a background drawable to the LinearLayout which had rounded corners, but the button corners overlapped the edge of the LinearLayout rounded edge (see Figure 3).

Figure 3: Take Two
Figure 3: Take Two

How can I keep the button's background within the bounds of its parent's background drawable? Or do you have any other suggestions on how to work around the bug?

Jeremy Haberman
  • 1,340
  • 1
  • 12
  • 20
  • Well, I faced the same issue. Simply went on and swapped them accordingly hoping that if it's fixed one day, my application is not the only one suffering from it :) – harism May 14 '11 at 17:04
  • @harism: i as well swapped them in one app. BUT: on devices >= Honeycomb they are now wrong (or should i say correct? :D) so swapping them is not a nice fix. – Patrick Boos Dec 20 '11 at 06:27

5 Answers5

17

Another solution is to create another folder called "drawable-v12".

In here put the correct radius (so bottomLeftRadius, topLeftRadius), and in the original drawable folder put in the swapped values. Then 3.1+ will use the v12 folder, and pre 3.1 versions will use the drawable folder.

Joss Stuart
  • 1,856
  • 1
  • 17
  • 19
  • works great i tried it with 2.3.3 and 4.0.2 - its great! Thanks – Informatic0re Jan 27 '12 at 08:22
  • I've been messing with a number of the "solutions" out there and your suggestion is the best I've come across so far. It's the most logical way to approach it given the illogical nature of the radius problem. Thanks! – Art Geigel May 20 '13 at 08:32
  • Surely this is the correct solution. One note, if you have different versions of the drawable for different densities, you'll have to have drawable-v12-hdpi, etc.. or factor out the density-dependent aspects into density-dependent dimensions (@dimen resources in dimens-hdpi for example). – JulianSymes Aug 10 '13 at 09:57
15

This feels like such a hack, but it worked.

The buttons were originally made up of (1) an outer shadow, (2) a top-half gradient and (3) a bottom solid color. Here's what I did:

  1. Made the top and bottom halves each rounded on all four corners. This left (1) a gap in the middle of the left and right sides and (2) rounded corners on the right.
  2. Created a small rectangle to fill in the gap in the left middle.
  3. Created another small rectangle to both fill in the gap in the right middle and make the top and bottom corners on the right side square.

Here's an example of the XML for the normal state of the left button.

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">

    <!-- Main part of button -->
    <item
        android:bottom="20dp"
        android:right="5dp" >

        <shape android:shape="rectangle">
            <solid android:color="@color/button_normal_green_top" />
            <corners android:radius="5dp" />
        </shape>
    </item>

    <item
        android:top="20dp"
        android:right="5dp" >

        <shape
            android:shape="rectangle" >
            <solid android:color="@color/button_normal_green_bottom" />
            <corners android:radius="5dp" />
        </shape>
    </item>

    <!-- Patch left middle part of button, which was left empty due to rounded 
    corners on top and bottom halves of button -->
    <item
        android:top="5dp"
        android:bottom="20dp"
        android:right="5dp" >

        <shape android:shape="rectangle">
            <solid android:color="@color/button_normal_green_top" />
        </shape>
    </item>

    <item
        android:top="20dp"
        android:bottom="5dp"
        android:right="5dp" >

        <shape
            android:shape="rectangle" >
            <solid android:color="@color/button_normal_green_bottom" />
        </shape>
    </item>

    <!-- Patch right middle and make right side corners square -->
    <item
        android:bottom="20dp"
        android:left="15dp" >

        <shape android:shape="rectangle">
            <solid android:color="@color/button_normal_green_top" />
        </shape>
    </item>

    <item
        android:top="20dp"
        android:left="15dp" >

        <shape android:shape="rectangle" >
            <solid android:color="@color/button_normal_green_bottom" />
        </shape>
    </item>
</layer-list>

I did, however, lose the gradient on the top half, but I can live with the two-tone button. Here's what the result looks like:
Two Buttons Solution

Francisco Alvarado
  • 2,815
  • 2
  • 26
  • 51
Jeremy Haberman
  • 1,340
  • 1
  • 12
  • 20
1

A better solution:

  • Create another folder values-12
  • Create dimensions.xml file under values-12.
  • Put 2 dimension properties in values-12/dimensions.xml for the bottom left, and bottom right corner radius.
  • Put 2 dimension properties in values/dimensions.xml for bottom left, and bottom right corner radius values, but remember to flip them.

Use the dimension values when assigning corner radius instead of hardcoding them in your drawables. When a pre 3.1 loads, it will use the reversed corner radius values under folder values. When 3.1+ loads, it will use correct corner radius values under folder values-12.

Why is this better? You don't need to duplicate drawable code. Now you can change any code not related to corner radiuses without having to update 2 or more places.

William Morrison
  • 10,953
  • 2
  • 31
  • 48
1

It should work if we provide already left right swapped configuration; so that bug swap will restore the configuration required, as below for left only curved, and righ sharp edged button

<corners android:radius="2dp" android:topLeftRadius="2dp" 
    android:topRightRadius="0dp" android:bottomLeftRadius="0dp" 
    android:bottomRightRadius="2dp">
Praveenkumar
  • 24,084
  • 23
  • 95
  • 173
Sonia
  • 11
  • 1
1

This appears to have been fixed in Android 3.0. And there's a comment on the issue that explains how to have backwards compatibility.

Jeremy Haberman
  • 1,340
  • 1
  • 12
  • 20