Добавьте закругленные углы при наличии android:drawableLeft с png

Короче говоря, вот что я хотел бы добавить пользовательскую кнопку, которая выглядит так:

Кнопка_Включить

IMG — это файл .png в моих папках mipmap, а НЕКОТОРЫЙ ТЕКСТ — просто строковое значение. Что пунктирная линия добавляется именно как разделитель в изображение, а не в кнопку. Проблема в том, что закругленные края не появляются там, где добавляется изображение. Это выглядит так:

Button_have

Мои вопросы следующие:

  1. Можно ли этого достичь?
  2. Есть ли способ переопределить атрибут <solid /> в <shape />? Мне нужно будет создать 10 таких кнопок, каждая с разными цветами, и если я добавлю android:color с другим значением, цвет не изменится.
  3. При добавлении изображения я выбираю только одно (например, mdpi). Если это будет отображаться на больших экранах, потребуется ли другое изображение .png в зависимости от размера?
  4. Есть ли определенный тип кнопки, который я должен использовать? Я хотел бы вернуть цвета при нажатии кнопки и оставаться нажатой. У меня есть смутное представление о том, как этого можно добиться, но есть ли способ сделать это и для файлов .png, или мне нужно импортировать в проект другие с уже инвертированными цветами и просто переключать их?

custom_button.xml

<shape 
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">

<corners
    android:topLeftRadius="250px"
    android:bottomLeftRadius="250px"
    android:topRightRadius="50px"
    android:bottomRightRadius="50px" />
<solid
    android:color="@color/YellowPrimary"/>
</shape>

button_styles.xml

<resources>

<style name="CategoryToggle">
    <item name="android:background">@drawable/custom_button</item>
    <item name="android:textAllCaps">true</item>
</style>

<style name="CategoryToggle.First">
    <item name="android:color">@color/bluePrimary</item> // Does not override <solid>
    <item name="android:drawableLeft">@mipmap/icon_48mdpi</item>
    <item name="android:text">@string/first_cat</item>
</style>
</resources>

button_layout.xml

<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">

<Button
    style="@style/CategoryToggle.History"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginTop="8dp"
    android:layout_marginEnd="8dp"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintTop_toTopOf="parent" />


</android.support.constraint.ConstraintLayout>

На данный момент у меня нет кода Java, так как я только начал и пытаюсь реализовать этот странный формат кнопки.

Вот как это выглядит на моем конце: my_end


person Andy    schedule 06.03.2019    source источник
comment
Без кода сложно понять, что происходит.   -  person Bryan    schedule 06.03.2019
comment
@Bryan У меня не так много кода, так как я только начал работать. Я добавил только цвета, строки, png. Ничего другого на данный момент.   -  person Andy    schedule 06.03.2019
comment
Немного кода лучше, чем его отсутствие, опубликуйте XML-код, который вы используете для создания формы, и любой код Java, который вы используете для ее отображения.   -  person Bryan    schedule 06.03.2019
comment
@Bryan Как я уже сказал, ничего особенного. Добавил то что есть. На данный момент нет java, так как я просто пытаюсь создать эту форму в данный момент.   -  person Andy    schedule 06.03.2019
comment
У MIP-карты icon_48mdpi желтый фон?   -  person Bryan    schedule 06.03.2019
comment
Да. Я должен сделать его прозрачным, верно?   -  person Andy    schedule 06.03.2019
comment
Наверное. Вот почему вы получаете квадратную форму с левой стороны кнопки. Существуют способы замаскировать рисуемый объект, но для этого требуется немного кода.   -  person Bryan    schedule 06.03.2019
comment
Что вы имеете в виду, есть ли способ сделать это и для файлов .png? Вы хотите изменить рисуемый объект в зависимости от состояния кнопки?   -  person Bryan    schedule 06.03.2019
comment
Да, дайте PNG прозрачный фон, и рисунок с закругленными углами должен выглядеть правильно (не быть закрытым).   -  person leorleor    schedule 06.03.2019
comment
@Bryan Да, я хочу изменить цвета png при нажатии кнопки. Что-то, чтобы имитировать тот факт, что он выбран   -  person Andy    schedule 06.03.2019


Ответы (4)


  1. Абсолютно. Как я уже упоминал в комментариях, либо убедитесь, что ваш рисунок имеет прозрачный фон, либо создайте пользовательскую кнопку чтобы замаскировать рисуемый объект.
  2. Вы можете использовать атрибут стиля для применения другого стиль для каждой кнопки. Под этим я подразумеваю, что цвет, определенный в вашем custom_button.xml, должен ссылаться на атрибут цвета (что-то вроде colorAccent должно работать в вашем случае) вместо статического цвета.
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <solid android:color="?attr/colorAccent"/>
</shape>

Затем измените этот цвет в стилях кнопок вместо android:color.

<style name="CategoryToggle">
    <item name="colorAccent">@color/YellowPrimary</item>
</style>

Убедитесь, что у вас есть библиотека поддержки, или colorAccent не будет доступен.

Используйте атрибут android:theme вместо атрибута style, чтобы применить тему кнопки.

<Button
    android:width="wrap_content"
    android:height="wrap_content"
    android:theme="@style/CategoryToggle"/>
  1. Похоже, ваши чертежи не используют квалификаторы ресурсов. Вам необходимо убедиться, что каждый альтернативный ресурс имеет то же имя, что и исходный (т. е. ваш icon_48mdpi.png вместо этого должен называться icon_48dp.png для всех конфигураций) и помещен в соответствующую папку для рисования из-за его плотности. Ваши ресурсы для рисования должны выглядеть следующим образом (в Project структуре представления, а не Android структуру просмотра).
res/
|-- drawable/
|   +-- custom_button.xml
|-- drawable-hdpi/
|   +-- icon_48dp.png
|-- drawable-mdpi/
|   +-- icon_48dp.png
|-- drawable-xhdpi/
|   +-- icon_48dp.png
|-- drawable-xxhdpi/
|   +-- icon_48dp.png
|-- drawable-xxxhpdi/
|   +-- icon_48dp.png
~
  1. Чтобы изменить цвет чертежа в зависимости от состояния, вам нужно сделать еще один шаг абстрагирования цвета и создать список состояний цветов.

res/color/button_color_selector.xml

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:color="@color/pressed_color" android:state_pressed="true"/>
    <item android:color="@color/focused_color" android:state_focused="true"/>
    <item android:color="@color/state_hovered" android:state_hovered="true"/>
    <item android:color="?attr/colorAccent"/>
</selector>

Затем вы можете использовать этот цветовой ресурс в своей форме вместо colorAccent.

<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <solid android:color="@color/button_color_selector"/>
</shape>

Вы также можете сделать каждый из цветов в списке состояний цвета атрибутом с возможностью изменения стиля с помощью определение пользовательских атрибутов и ссылка на эти атрибуты в ваших стилях. Однако я не буду вдаваться в подробности для краткости.

Вы можете сделать это для рисунков аналогичным образом, создав выводимый список состояний.


Наконец, вы должны привыкнуть использовать dp вместо px, если только вы не абсолютно уверены, что хотите использовать px. Это предотвратит странные появления при различной плотности экрана.

person Bryan    schedule 06.03.2019
comment
Хороший совет. Я постараюсь и дам вам знать, как все прошло. Несколько небольших вопросов и уточнений: 1. Я предполагаю, что кодирование займет меньше места, чем импорт нового набора png? 2. Могу ли я использовать любой атрибут? Например, один менее актуальный здесь, например, colorEdgeEffect? 3. Вспомнил из предыдущего проекта, но забыл обновить вопрос. 4. Я использовал px, чтобы проверить, есть ли разница. Забыл вернуть обратно перед вставкой кода. - person Andy; 07.03.2019
comment
@ Энди 1. Это правда. Вы даже можете использовать векторные ресурсы вместо файлов png и примените атрибут цвета к цвету вектора, чтобы занимать еще меньше места. 2. Да, подойдет любой атрибут. Я бы постарался придерживаться тех, которые имеют смысл для варианта использования. - person Bryan; 07.03.2019
comment
После долгих проб и ошибок мне удалось сделать номер 1, но я застрял на № 2. Переопределение цвета атрибута ?attr не происходит, несмотря на то, что я выполнил точные шаги. Не могли бы вы указать библиотеку? Я добавил около 7 в градиенте, который показался актуальным, но не может переопределить цвет. - person Andy; 11.03.2019
comment
@ Энди ?attr/colorAccent выделено как ошибка? (Он должен стать красным, и когда вы наведете на него курсор, появится диалоговое окно с сообщением о чем-то вроде «Не удается разрешить символ '?attr/colorAccent') - person Bryan; 11.03.2019
comment
Нет ошибки. В моей форме у меня есть <solid android:color="?attr/colorAccent"/>, который задает правильный цвет, а в моем стиле, примененном к моей кнопке, у меня есть <item name="colorAccent">@color/histYellowPrimary</item>, который не меняет его на желтый. Я все еще получаю тот, который изначально был установлен для акцента (розововатый цвет). У меня есть последняя зависимость совместимости приложений, а также другие, добавленные из списка, включая implementation 'com.android.support:palette-v7:28.0.0', который связан с цветами. - person Andy; 11.03.2019
comment
Я также пробовал с селектором из # 4, и он все еще не переопределяет colorAccent - person Andy; 11.03.2019
comment
@Andy Тогда у вас есть правильная библиотека (библиотека Palette, хотя и полезная, не имеет ничего общего с colorAccent). Прошу прощения, не упомянул в ответе; убедитесь, что вы устанавливаете стиль, используя android:theme="@style/CategoryToggle" (а не style="..."). Кроме того, изменение цвета не будет отображаться в предварительном просмотре XML, поэтому вам придется создать приложение, чтобы увидеть любые изменения. - person Bryan; 11.03.2019
comment
Если я настрою его как android:theme, моя фигура исчезнет. Я получаю серую кнопку с изображением и текстом. Ничего из моей нестандартной формы и цвета. Если я установлю его как style=, я получу форму, но цвет не переопределит - person Andy; 11.03.2019
comment
@Энди Хм, в моем тестировании форма сохранялась при использовании android:theme. Добавьте свой текущий код к вопросу, чтобы я мог видеть, что может быть не так? - person Bryan; 11.03.2019
comment
Удалось решить ситуацию, создав <selector> в папке с возможностью рисования и элемент для каждого состояния, который содержит форму и цвета, которые мне нужны. Таким образом я также избавляюсь от файла для форм, необходимых для каждой кнопки. - person Andy; 11.03.2019
comment
@Andy Энди Звучит как много повторяющегося кода, я бы все равно попытался посмотреть, смогу ли я его разделить. Но пока работает. - person Bryan; 12.03.2019
comment
Я знаю, что это много повторяющегося кода, но если я добавлю цвет текста в раздел фона, он просто проигнорирует форму. Пока я буду использовать это, так как оно работает, и, возможно, я наткнусь на что-нибудь при дальнейшей реализации приложения. - person Andy; 12.03.2019

На 4 «есть ли способ (возвратить цвета при нажатии) для файлов .png».. да, есть способы.

Опция по книге заключается в использовании стилей xml для указания разных рисунков для разных состояний кнопок. Рассмотрим ImageButton, в документах которого есть пример: https://developer.android.com/reference/android/widget/ImageButton.html

Другой вариант — применить оттенки или другие фильтры к рисунку в вашем собственном коде в обратных вызовах взаимодействия кнопок. По сравнению с использованием различных рисунков, в этом подходе вы добавляете собственный код вместо использования встроенных ресурсов, поэтому вы можете больше тестировать и отлаживать на разных устройствах, и вы получаете полный контроль, чтобы вы могли делать собственные анимации и другие сложные вещи, которые могут не хорошо вписывается в инструментарий ресурсов Android. Можно проверить setColorFilter для начала: https://developer.android.com/reference/android/widget/ImageView.html#setColorFilter(int,%20android.graphics.PorterDuff.Mode)

Спасибо за добавление кода и изображений или вашей проблемы, помогает понять ее.

person leorleor    schedule 06.03.2019

Большое спасибо Брайану за его понимание этого вопроса. Это привело меня к пути, которым я должен был следовать, чтобы решить эту проблему. Я отправляю этот ответ, чтобы другие люди с похожими случаями знали шаги. Хотя у меня довольно много файлов, эта процедура отлично сработала.

  1. У меня есть собственная кнопка, как описано в ссылке, предоставленной Брайаном.

В остальном у меня следующее:

Изменить цвет текста: button_text_color.xml

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:color="@color/redPrimary" android:state_pressed="true"/>
    <item android:color="@color/redDark"/>
</selector>

Изменить фон: button_background.xml

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true">
        <shape android:shape="rectangle">
            <corners android:bottomLeftRadius="400dp" android:radius="100dp" android:topLeftRadius="400dp" />
            <solid android:color="@color/redDark" />
        </shape>
    </item>
    <item android:state_enabled="true">
        <shape android:shape="rectangle">
            <corners android:bottomLeftRadius="400dp" android:radius="100dp" android:topLeftRadius="400dp" />
            <solid android:color="@color/redPrimary" />
        </shape>
    </item>
</selector>

Изменить рисуемый объект: button_drawable.xml

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/ic_button_inverted" android:state_pressed="true" />
    <item android:drawable="@drawable/ic_button"/>
</selector>

button_style.xml

<style name="MyButtonStyle">
        <item name="android:background">@drawable/button_background</item>
        <item name="android:drawableLeft">@drawable/button_drawable</item>
    <item name="android:text">@string/button_text</item>
    <item name="android:textColor">@color/button_text_color</item>
</style>

Реализация в main_layout.xml

<packagename.MyCustomButton xmlns:app="http://schemas.android.com/apk/res-auto"
            android:id="@+id/myButton"
            style="@style/MyBUttonStyle"
            android:layout_marginBottom="8dp" />
person Andy    schedule 12.03.2019

Просто используйте официальную библиотеку.
Добавьте MaterialButton, используя следующие атрибуты:

  • app:icon чтобы добавить значок
  • app:iconGravity определить положение значка
  • app:iconPadding увеличить/уменьшить расстояние между иконкой и текстом
  • android:paddingLeft отступ между краем и значком
<com.google.android.material.button.MaterialButton
    android:paddingLeft="2dp"
    app:icon="@drawable/ic_add_24px"
    app:iconGravity="start"
    app:iconPadding="4dp"
    app:shapeAppearanceOverlay="@style/ShapeAppearanceOverlay.Button.RoundedRight"
    .../>

С app:shapeAppearanceOverlay вы можете настроить форму компонента.

  <style name="ShapeAppearanceOverlay.Button.RoundedRight" parent="">
    <item name="cornerFamily">rounded</item>
    <item name="cornerSizeTopRight">4dp</item>
    <item name="cornerSizeBottomRight">4dp</item>
    <item name="cornerSizeTopLeft">16dp</item>
    <item name="cornerSizeBottomLeft">16dp</item>
  </style>

Вы можете получить тот же результат, используя стиль.

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

person Gabriele Mariotti    schedule 04.09.2019