Android XML: Пользовательская кнопка, которую можно нарисовать без дублирования xml для каждого состояния кнопки?

#android #xml #android-layout #android-drawable

Вопрос:

Я пытаюсь создать custom_button, и до сих пор у меня есть вот что: два состояния (нажато и включено) имеют свою собственную форму с границей:

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

    <!-- Pressed -->
    <item android:state_pressed='true'>
        <layer-list>
            <item> <!-- Border -->
                <shape
                    android:shape='rectangle'>

                    <solid android:color='@color/Foreground'/>
                </shape>
            </item>

            <item android:bottom='2dp' android:top='2dp' android:left='2dp' android:right='2dp'> <!-- Color -->
                <shape
                    android:shape='rectangle'>

                    <solid android:color='@color/WidgetSoft'/>
                </shape>
            </item>
        </layer-list>
    </item>

    <!-- Enabled -->
    <item>
        <layer-list>
            <item> <!-- Border -->
                <shape
                    android:shape='rectangle'>

                    <solid android:color='@color/Foreground'/>
                </shape>
            </item> <!-- Color -->

            <item android:bottom='2dp' android:top='2dp' android:left='2dp' android:right='2dp'> <!-- Base Color -->
                <shape
                    android:shape='rectangle'>

                    <solid android:color='@color/Widget'/>
                </shape>
            </item>
        </layer-list>
    </item>

</selector>
 

Это работает, но в нем указаны две одинаковые кнопки, где различаются только цвета. Когда я добавлю другие состояния кнопок и больше внешнего вида, я почувствую, что это будет все больше и больше дублироваться. Есть ли способ иметь base_button.xml рисование, в котором могут быть установлены базовые атрибуты «одинаково для каждой кнопки» и custom_button.xml где атрибуты, относящиеся к состоянию кнопки, могут быть заданы в соответствующем теге?

Ниже приведен псевдо-пример того, что я имею в виду, но я не знаю, как воплотить это в реальность. custom_button.xml обрабатывает состояния кнопок и base_button.xml определяет основные характеристики кнопки.

custom_button.xml:

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

    <!-- Pressed -->
    <item android:state_pressed='true' android:drawable='@drawable/base_button'>

        <!-- SET GLOBAL_BORDER_COLOR TO '@color/btnPressedBorder' -->
        <!-- SET GLOBAL_BASE_COLOR TO '@color/btnPressedBase' -->

    </item>

    <!-- Enabled -->
    <item  android:drawable='@drawable/base_button'>

        <!-- SET GLOBAL_BORDER_COLOR TO '@color/btnEnabledBorder' -->
        <!-- SET GLOBAL_BASE_COLOR TO '@color/btnEnabledBase' -->

    </item>
    
</selector>
 

base_button.xml:

 <?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= GLOBAL_BORDER_COLOR />
        </shape>
    </item>

    <item android:bottom='2dp' android:top='2dp' android:left='2dp' android:right='2dp'>
        <shape
            android:shape='rectangle'>

            <solid android:color= GLOBAL_BASE_COLOR />
        </shape>
    </item>
</layer-list>
 

Возможно ли это вообще в XML? Я наткнулся на xsl:переменную в Интернете, но не смог заставить ее работать. Любые предложения о том, как это сделать или альтернативные способы достижения того же результата, будут высоко оценены!

Комментарии:

1. Xsl является частью xslt. xml, используемый drawables, не поддерживает это.

Ответ №1:

Вы можете использовать цветовой каталог для цветов. Определите список цветов для границы виджета и один для его заливки. Состояние виджета будет перенесено в список цветов, где будет выбран цвет. Затем вы можете определить рисоваемый объект следующим образом:

base_button.xml

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

    <item
        android:bottom='2dp'
        android:left='2dp'
        android:right='2dp'
        android:top='2dp'>
        <shape android:shape='rectangle'>
            <solid android:color="@color/widget_fill" />
        </shape>
    </item>
</layer-list>
 

КолорСтатеЛисты будут выглядеть так. (Простите за выбор цвета.)

widget_fill.xml

 <selector>
    <item android:color="@android:color/holo_red_light" android:state_pressed="true" />
    <item android:color="@android:color/holo_blue_light" android:state_enabled="true" />
</selector>
 

widget_border.xml

 <selector>
    <item android:color="@android:color/black" android:state_pressed="true" />
    <item android:color="@android:color/holo_red_light" android:state_enabled="true" />
</selector>
 

И, наконец, файл макета образца:

activity_main.xml

 <androidx.constraintlayout.widget.ConstraintLayout 
    android:layout_width="match_parent"
    android:layout_height="match_parent">


    <androidx.appcompat.widget.AppCompatButton
        android:id="@ id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="24dp"
        android:background="@drawable/base_button"
        android:text="Button"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>
 

Собрав все это вместе, это будет выглядеть так:

введите описание изображения здесь