Стандартная кнопка Android с другим цветом
Я хочу немного изменить цвет стандартной кнопки Android, чтобы лучше соответствовать брендингу клиента.
Лучший способ, который я нашел для этого, - изменить Button
на следующий drawable, расположенный в res/drawable/red_button.xml
:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:drawable="@drawable/red_button_pressed" />
<item android:state_focused="true" android:drawable="@drawable/red_button_focus" />
<item android:drawable="@drawable/red_button_rest" />
</selector>
Но для этого требуется, чтобы я на самом деле создавал три разных чертежа для каждой кнопки, которую я хочу настроить (один для кнопки в состоянии покоя, один при фокусировке и один при нажатии). Это кажется более сложным и не сухим, чем мне нужно.
Все, что я действительно хочу сделать, это применить к кнопке какое-то цветовое преобразование. Есть ли более простой способ изменить цвет кнопки, чем я делаю?
Ответы
Ответ 1
Я обнаружил, что все это можно сделать в одном файле довольно легко. Поместите что-то вроде следующего кода в файл с именем custom_button.xml
, а затем установите background="@drawable/custom_button"
в окне просмотра кнопок:
<?xml version="1.0" encoding="utf-8"?>
<selector
xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" >
<shape>
<gradient
android:startColor="@color/yellow1"
android:endColor="@color/yellow2"
android:angle="270" />
<stroke
android:width="3dp"
android:color="@color/grey05" />
<corners
android:radius="3dp" />
<padding
android:left="10dp"
android:top="10dp"
android:right="10dp"
android:bottom="10dp" />
</shape>
</item>
<item android:state_focused="true" >
<shape>
<gradient
android:endColor="@color/orange4"
android:startColor="@color/orange5"
android:angle="270" />
<stroke
android:width="3dp"
android:color="@color/grey05" />
<corners
android:radius="3dp" />
<padding
android:left="10dp"
android:top="10dp"
android:right="10dp"
android:bottom="10dp" />
</shape>
</item>
<item>
<shape>
<gradient
android:endColor="@color/blue2"
android:startColor="@color/blue25"
android:angle="270" />
<stroke
android:width="3dp"
android:color="@color/grey05" />
<corners
android:radius="3dp" />
<padding
android:left="10dp"
android:top="10dp"
android:right="10dp"
android:bottom="10dp" />
</shape>
</item>
</selector>
Ответ 2
Следуя ответу Томаша, вы также можете программно установить оттенок всей кнопки, используя режим умножения PorterDuff. Это изменит цвет кнопки, а не только оттенок.
Если вы начинаете со стандартной серой затененной кнопки:
button.getBackground().setColorFilter(0xFFFF0000, PorterDuff.Mode.MULTIPLY);
даст вам красную затененную кнопку,
button.getBackground().setColorFilter(0xFF00FF00, PorterDuff.Mode.MULTIPLY);
даст вам зеленую затененную кнопку и т.д., где первым значением является цвет в шестнадцатеричном формате.
Он работает, умножая текущее значение цвета кнопки на ваше значение цвета. Я уверен, что с этими режимами вы также можете многое сделать.
Ответ 3
Майк, вас могут заинтересовать цветовые фильтры.
Пример:
button.getBackground().setColorFilter(new LightingColorFilter(0xFFFFFFFF, 0xFFAA0000));
попробуйте сделать это, чтобы достичь желаемого цвета.
Ответ 4
Это мое решение, которое отлично работает с от API 15. Это решение сохраняет все эффекты нажатия кнопки по умолчанию, например материал RippleEffect
. Я не тестировал его на более низких API, но он должен работать.
Все, что вам нужно сделать, это:
1) Создайте стиль, который изменяется только colorAccent
:
<style name="Facebook.Button" parent="ThemeOverlay.AppCompat">
<item name="colorAccent">@color/com_facebook_blue</item>
</style>
Я рекомендую использовать ThemeOverlay.AppCompat
или ваш основной AppTheme
как родительский, чтобы сохранить остальные стили.
2) Добавьте эти две строки в виджет button
:
style="@style/Widget.AppCompat.Button.Colored"
android:theme="@style/Facebook.Button"
Иногда ваш новый colorAccent
не отображается в Android Studio Preview, но при запуске приложения на телефоне цвет будет изменен.
Виджет кнопки образца
<Button
android:id="@+id/sign_in_with_facebook"
style="@style/Widget.AppCompat.Button.Colored"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="@string/sign_in_facebook"
android:textColor="@android:color/white"
android:theme="@style/Facebook.Button" />
Ответ 5
Теперь вы можете также использовать appcompat-v7 AppCompatButton с атрибутом backgroundTint
:
<android.support.v7.widget.AppCompatButton
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:backgroundTint="#ffaa00"/>
Ответ 6
Мне нравится предложение цветового фильтра в предыдущих ответах @conjugatedirection и @Tomasz; Тем не менее, я обнаружил, что код, представленный до сих пор, был не так легко применен, как я ожидал.
Во-первых, не было указано , где применить и очистить цветной фильтр. Возможно, есть и другие хорошие места для этого, но то, что мне показалось, было OnTouchListener.
Из моего чтения исходного вопроса идеальным решением было бы то, что не связано с изображениями. Принятый ответ с использованием custom_button.xml из @emmby, вероятно, лучше подходит, чем цветовые фильтры, если ваша цель. В моем случае я начинаю с изображения png от дизайнера пользовательского интерфейса, из которого должна выглядеть кнопка. Если я установил фон кнопки для этого изображения, то по умолчанию обратная связь будет полностью потеряна. Этот код заменяет это поведение программным эффектом затемнения.
button.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
// 0x6D6D6D sets how much to darken - tweak as desired
setColorFilter(v, 0x6D6D6D);
break;
// remove the filter when moving off the button
// the same way a selector implementation would
case MotionEvent.ACTION_MOVE:
Rect r = new Rect();
v.getLocalVisibleRect(r);
if (!r.contains((int) event.getX(), (int) event.getY())) {
setColorFilter(v, null);
}
break;
case MotionEvent.ACTION_OUTSIDE:
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
setColorFilter(v, null);
break;
}
return false;
}
private void setColorFilter(View v, Integer filter) {
if (filter == null) v.getBackground().clearColorFilter();
else {
// To lighten instead of darken, try this:
// LightingColorFilter lighten = new LightingColorFilter(0xFFFFFF, filter);
LightingColorFilter darken = new LightingColorFilter(filter, 0x000000);
v.getBackground().setColorFilter(darken);
}
// required on Android 2.3.7 for filter change to take effect (but not on 4.0.4)
v.getBackground().invalidateSelf();
}
});
Я извлек это как отдельный класс для приложения на несколько кнопок - показан как анонимный внутренний класс, чтобы получить эту идею.
Ответ 7
Если вы создаете цветные кнопки с XML, вы можете сделать код немного более чистым, указав сфокусированное и нажатое состояние в отдельном файле и повторно используя их. Моя зеленая кнопка выглядит так:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_focused="true" android:drawable="@drawable/button_focused"/>
<item android:state_pressed="true" android:drawable="@drawable/button_pressed"/>
<item>
<shape>
<gradient android:startColor="#ff00ff00" android:endColor="#bb00ff00" android:angle="270" />
<stroke android:width="1dp" android:color="#bb00ff00" />
<corners android:radius="3dp" />
<padding android:left="10dp" android:top="10dp" android:right="10dp" android:bottom="10dp" />
</shape>
</item>
</selector>
Ответ 8
Самое короткое решение, которое работает с любой версией Android:
<Button
app:backgroundTint="@color/my_color"
Примечания/Требования:
Объяснение:
Ответ 9
Я использую этот подход
style.xml
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:colorPrimaryDark">#413152</item>
<item name="android:colorPrimary">#534364</item>
<item name="android:colorAccent">#534364</item>
<item name="android:buttonStyle">@style/MyButtonStyle</item>
</style>
<style name="MyButtonStyle" parent="Widget.AppCompat.Button.Colored">
<item name="android:colorButtonNormal">#534364</item>
<item name="android:textColor">#ffffff</item>
</style>
Как вы можете видеть выше, я использую собственный стиль для своей кнопки. Цвет кнопки соответствует цвету акцента. Я считаю, что это гораздо лучший подход, чем установка android:background
, поскольку я не потеряю эффект пульсации, который предоставляет Google.
Ответ 10
Теперь намного проще: android-holo-colors.com
Это позволит вам легко менять цвета всех головоломок (кнопок, прядильников,...). Вы выбираете цвет, а затем загружаете zip файл, содержащий чертежи для всех разрешений.
Ответ 11
Используйте его следующим образом:
buttonOBJ.getBackground().setColorFilter(Color.parseColor("#YOUR_HEX_COLOR_CODE"), PorterDuff.Mode.MULTIPLY);
Ответ 12
В <Button>
используйте android:background="#33b5e5"
. или лучше android:background="@color/navig_button"
Ответ 13
В библиотеке компонентов DroidUX есть ColorButton
, чей цвет можно легко изменить, как с помощью определения xml, так и программно во время выполнения, поэтому вы можете даже позволить пользователю установить цвет кнопки/тему, если это позволяет ваше приложение.
Ответ 14
Вы также можете использовать этот онлайн-инструмент, чтобы настроить свою кнопку http://angrytools.com/android/button/ и использовать android:background="@drawable/custom_btn"
для определения настраиваемой кнопки в макете.
Ответ 15
Вы можете настроить тему своей кнопки на
<style name="AppTheme.ButtonBlue" parent="Widget.AppCompat.Button.Colored">
<item name="colorButtonNormal">@color/HEXColor</item>
<item name="android:textColor">@color/HEXColor</item>
</style>
Ответ 16
Легкий способ - просто определить пользовательский класс Button, который принимает все свойства, которые вы хотите, такие как радиус, градиент, нажатый цвет, обычный цвет и т.д., а затем просто используйте это в своих макетах XML вместо настройки фона, используя XML. Образец здесь
Это очень полезно, если у вас много кнопок с такими же свойствами, как радиус, выбранный цвет и т.д. Вы можете настроить унаследованную кнопку для обработки этих дополнительных свойств.
Результат (не использовался селектор фона).
Нормальная кнопка
Нажмите кнопку
Ответ 17
То, как я делаю другую стилизованную кнопку, которая работает достаточно хорошо, - это подкласс объекта Button и применение цветового фильтра. Это также относится к включенным и отключенным состояниям, применяя альфа к кнопке.
import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.LightingColorFilter;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.os.Build;
import android.util.AttributeSet;
import android.widget.Button;
public class DimmableButton extends Button {
public DimmableButton(Context context) {
super(context);
}
public DimmableButton(Context context, AttributeSet attrs) {
super(context, attrs);
}
public DimmableButton(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@SuppressWarnings("deprecation")
@Override
public void setBackgroundDrawable(Drawable d) {
// Replace the original background drawable (e.g. image) with a LayerDrawable that
// contains the original drawable.
DimmableButtonBackgroundDrawable layer = new DimmableButtonBackgroundDrawable(d);
super.setBackgroundDrawable(layer);
}
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
@Override
public void setBackground(Drawable d) {
// Replace the original background drawable (e.g. image) with a LayerDrawable that
// contains the original drawable.
DimmableButtonBackgroundDrawable layer = new DimmableButtonBackgroundDrawable(d);
super.setBackground(layer);
}
/**
* The stateful LayerDrawable used by this button.
*/
protected class DimmableButtonBackgroundDrawable extends LayerDrawable {
// The color filter to apply when the button is pressed
protected ColorFilter _pressedFilter = new LightingColorFilter(Color.LTGRAY, 1);
// Alpha value when the button is disabled
protected int _disabledAlpha = 100;
// Alpha value when the button is enabled
protected int _fullAlpha = 255;
public DimmableButtonBackgroundDrawable(Drawable d) {
super(new Drawable[] { d });
}
@Override
protected boolean onStateChange(int[] states) {
boolean enabled = false;
boolean pressed = false;
for (int state : states) {
if (state == android.R.attr.state_enabled)
enabled = true;
else if (state == android.R.attr.state_pressed)
pressed = true;
}
mutate();
if (enabled && pressed) {
setColorFilter(_pressedFilter);
} else if (!enabled) {
setColorFilter(null);
setAlpha(_disabledAlpha);
} else {
setColorFilter(null);
setAlpha(_fullAlpha);
}
invalidateSelf();
return super.onStateChange(states);
}
@Override
public boolean isStateful() {
return true;
}
}
}
Ответ 18
значения\styles.xml
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
<style name="RedAccentButton" parent="ThemeOverlay.AppCompat.Light">
<item name="colorAccent">#ff0000</item>
</style>
то
<Button
style="@style/Widget.AppCompat.Button.Colored"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="text" />
<Button
style="@style/Widget.AppCompat.Button.Colored"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:enabled="false"
android:text="text" />
<Button
style="@style/Widget.AppCompat.Button.Colored"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="text"
android:theme="@style/RedAccentButton" />
<Button
style="@style/Widget.AppCompat.Button.Colored"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:enabled="false"
android:text="text"
android:theme="@style/RedAccentButton" />