Как я могу обойти проблему Android 9161, где bottomRightRadius и bottomLeftRadius меняются местами?

Моя цель:

Figure 1: The Goal
Рисунок 1: Цель

Итак, прежде чем я узнал о проблеме, вот что я пробовал.

Во-первых, базовый макет:

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

Вывод "button_left_green":

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

И, например, "button_left_green_default":

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

Итак, после всего этого, я получил изображение на рисунке 2:
Figure 2: Take One
Рисунок 2: Take One

После двойной проверки определения нижних углов я убедился, что был сумасшедшим, пока не нашел известную проблему: http://code.google.com/p/android/issues/detail?id=9161

Я бы предпочел не просто их заменять, потому что если/когда проблема будет исправлена, кнопки будут разбиты на более новые версии.

Одна из моих идей заключалась в том, чтобы оставить фактические кнопки в виде обычных прямоугольников (т.е. без угловых радиусов) и обернуть обе кнопки округленным прямоугольником. Я добавил фона для LinearLayout с закругленными углами, но углы кнопок перекрывают край закругленного края LinearLayout (см. Рисунок 3).

Figure 3: Take Two
Рисунок 3: Take Two

Как я могу сохранить фон кнопки в пределах своего родительского фона? Или у вас есть другие предложения о том, как обойти ошибку?

Ответ 1

Это похоже на такой взлом, но он сработал.

Кнопки первоначально состояли из (1) внешней тени, (2) градиента верхней половины и (3) нижнего сплошного цвета. Вот что я сделал:

  • Сделал верхнюю и нижнюю половинки, каждая из которых закруглена на всех четырех углах. Это левое (1) зазор в середине левой и правой сторон и (2) закругленные углы справа.
  • Создал небольшой прямоугольник, чтобы заполнить промежуток в левом среднем.
  • Создал еще один маленький прямоугольник, чтобы заполнить промежуток в правой середине и сделать верхний и нижний углы на правом квадрате.

Вот пример XML для нормального состояния левой кнопки.

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

Я, однако, потерял градиент в верхней половине, но я могу жить с двухтональной кнопкой. Вот как выглядит результат:
Two Buttons Solution

Ответ 2

Другим решением является создание другой папки под названием "drawable-v12".

Здесь положите правильный радиус (так что bottomLeftRadius, topLeftRadius) и в исходной папке с возможностью переноса, помещенной в измененные значения. Затем 3.1+ будет использовать папку v12, а версии версии 3.1 будут использовать папку с возможностью переноса.

Ответ 3

Он должен работать, если мы предоставим конфигурацию с левой заменой слева; так что замена ошибок приведет к восстановлению требуемой конфигурации, как показано ниже для левой только криволинейной кнопки и кнопки с острыми краями

<corners android:radius="2dp" android:topLeftRadius="2dp" 
    android:topRightRadius="0dp" android:bottomLeftRadius="0dp" 
    android:bottomRightRadius="2dp">

Ответ 4

Это, по-видимому, было исправлено в Android 3.0. И есть комментарий по этой проблеме, в котором объясняется, как иметь обратную совместимость.

Ответ 5

Лучшее решение:

  • Создайте еще одну папку values-12
  • Создайте dimensions.xml файл под values-12.
  • Поместите 2 размерных свойства в values-12/dimensions.xml для нижнего левого и нижний правый угол.
  • Поместите 2 размерных свойства в values/dimensions.xml для нижнего левого и нижнего правого радиуса, но не забудьте перевернуть их.

Используйте значения размеров при назначении радиуса углов вместо их жесткого кодирования в ваших чертежах. Когда загружает pre 3.1, он будет использовать значения радиуса радиуса поворота в папке values. При загрузке 3.1+ он будет использовать правильные значения радиуса угла в папке values-12.

Почему это лучше? Вам не нужно дублировать код с возможностью вывода. Теперь вы можете изменить любой код, не относящийся к радиусу углов, без необходимости обновлять 2 или более места.