Botão padrão Android com uma cor diferente
-
19-09-2019 - |
Pergunta
Eu gostaria de mudar a cor de um botão Android padrão ligeiramente, a fim de melhor corresponder a marca de um cliente.
A melhor maneira que eu encontrei para fazer isso até agora é mudar drawable do Button
ao drawable localizado na 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>
Mas fazer isso exige que eu realmente criar três drawables diferentes para cada botão que pretende personalizar (um para o botão em repouso, um quando focado, e um quando pressionado). Isso parece mais complicado e não-seca do que eu preciso.
Tudo o que eu realmente quero fazer é aplicar algum tipo de transformação de cor para o botão. Existe uma maneira mais fácil de ir sobre como alterar a cor de um botão do que eu estou fazendo?
Solução
Eu descobri que tudo isso pode ser feito em um arquivo com bastante facilidade. Coloque algo como o seguinte código em um arquivo chamado custom_button.xml
e depois background="@drawable/custom_button"
conjunto na sua opinião botão:
<?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>
Outras dicas
Na sequência da resposta de Tomasz, você pode também definir programaticamente a sombra do botão inteiro usando o modo de multiplicar PorterDuff. Isso vai mudar a cor do botão em vez de apenas o matiz.
Se você começar com um botão sombreado cinza padrão:
button.getBackground().setColorFilter(0xFFFF0000, PorterDuff.Mode.MULTIPLY);
lhe dará um botão sombreado vermelho,
button.getBackground().setColorFilter(0xFF00FF00, PorterDuff.Mode.MULTIPLY);
lhe dará um botão com sombra verde etc., onde o primeiro valor é a cor em formato hexadecimal.
Ele funciona através da multiplicação do valor de cor botão atual pelo seu valor de cor. Eu tenho certeza que há também muito mais você pode fazer com estes modos.
Mike, você pode estar interessado em filtros de cor.
Um exemplo:
button.getBackground().setColorFilter(new LightingColorFilter(0xFFFFFFFF, 0xFFAA0000));
tentar isso para conseguir a cor desejada.
Esta é a minha solução que funciona perfeitamente começando a partir de API 15 . Esta solução mantém todos os efeitos Clique no botão padrão, como RippleEffect
material. Eu não testei-o em APIs mais baixos, mas deve funcionar.
Tudo que você precisa fazer, é:
1) Criar um estilo que só muda colorAccent
:
<style name="Facebook.Button" parent="ThemeOverlay.AppCompat">
<item name="colorAccent">@color/com_facebook_blue</item>
</style>
Eu recomendo usar
ThemeOverlay.AppCompat
ou o seu principalAppTheme
como pai, para manter o resto de seus estilos.
2) Adicionar estas duas linhas para seu widget button
:
style="@style/Widget.AppCompat.Button.Colored"
android:theme="@style/Facebook.Button"
Às vezes o seu novo
colorAccent
não está mostrando no Android Estúdio Preview, mas quando você iniciar o seu aplicativo no telefone, a cor será alterado.
Button Amostra Widget
<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" />
Agora também é possível usar appcompat-v7 é AppCompatButton com o atributo 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"/>
Eu gosto da sugestão filtro de cor nas respostas anteriores de @conjugatedirection e @Tomasz; No entanto, descobri que o código fornecido até agora não foi tão facilmente aplicado como eu esperava.
Em primeiro lugar, não foi mencionado onde para aplicar e limpar o filtro de cor. É possível que haja outros bons lugares para fazer isso, mas o que me veio à mente para mim foi um OnTouchListener .
De minha leitura da pergunta inicial, a solução ideal seria aquela que não envolve quaisquer imagens. A resposta aceita usando custom_button.xml de @emmby é provavelmente um ajuste melhor do que os filtros de cor, se esse é o seu objetivo. No meu caso, eu estou começando uma imagem png de um designer de interface do usuário do que o botão é suposto a aparência com. Se eu definir o fundo botão para esta imagem, o feedback destaque padrão é perdida completamente. Este código substitui esse comportamento com um efeito escurecimento programático.
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();
}
});
Eu extraí isto como uma classe separada para aplicação em vários botões -. Como classe interna anônima apenas para obter a ideia
Se você está fazendo botões coloridos com XML pode tornar o código um pouco mais limpo, especificando o focado e estado pressionado em um arquivo separado e reutilizá-los. Meu botão olhares verdes como este:
<?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>
Eu estou usando esta abordagem
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>
Como você pode ver acima, eu estou usando um estilo personalizado para o meu botão. A cor do botão corresponde à cor de destaque. Acho isso uma abordagem muito melhor do que a criação android:background
como eu não perderá o efeito cascata Google fornece.
Há uma maneira muito mais fácil agora: android-holo-colors.com
Ele permitirá que você alterar as cores de todos os drawables holo (botões, spinners, ...) facilmente. Você seleciona a cor e, em seguida, baixar um arquivo zip contendo drawables para todas as resoluções.
Use-o desta forma:
buttonOBJ.getBackground().setColorFilter(Color.parseColor("#YOUR_HEX_COLOR_CODE"), PorterDuff.Mode.MULTIPLY);
Em uso <Button>
android:background="#33b5e5"
. ou melhor android:background="@color/navig_button"
O DroidUX biblioteca componente tem um ColorButton
Widget cuja cor pode ser alterado facilmente, tanto por meio de definição de XML e programaticamente em tempo de execução, assim você pode até mesmo permitir que o usuário para definir o botão de cor / tema se seu aplicativo permite que ele.
Você também pode usar esta ferramenta online para personalizar o botão http://angrytools.com/android/button/ e uso android:background="@drawable/custom_btn"
para definir o botão personalizado em seu layout.
Você pode definir tema do seu botão para este
<style name="AppTheme.ButtonBlue" parent="Widget.AppCompat.Button.Colored">
<item name="colorButtonNormal">@color/HEXColor</item>
<item name="android:textColor">@color/HEXColor</item>
</style>
Uma maneira fácil é apenas para definir uma classe de botão personalizado que aceita todas as propriedades que você deseja, como raio, inclinação, cor pressionado, cor normal etc. e depois é só usar isso em seus layouts XML em vez de criar o fundo usando XML. Uma amostra é aqui
Isto é extremamente útil se você tem um monte de botões com as mesmas propriedades como o raio, selecionado cor etc. Você pode personalizar seu botão herdado para lidar com essas propriedades adicionais.
Resultado (Sem seletor de fundo foi usado).
Button normal
botão pressionado
O que eu faço um botão com estilo diferente, que funciona muito bem é a subclasse do objeto Button e aplicar um filtro de cor. Isso também alças habilitado e estados com deficiência através da aplicação de um alfa para o botão.
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;
}
}
}
Os valores \ 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>
então:
<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" />
Por diretrizes de design de material, você precisa usar o estilo como o código abaixo
<style name="MyButton" parent="Theme.AppCompat.Light>
<item name="colorControlHighlight">#F36F21</item>
<item name="colorControlHighlight">#FF8D00</item>
</style>
e no layout adicionar essa propriedade para o botão
android:theme="@style/MyButton"
É simples .. adicionar esta dependência em seu projeto e criar um botão com 1. Qualquer forma 2. Qualquer cor 3. Qualquer fronteira 4. Com efeitos relevantes
https://github.com/manojbhadane/QButton
<com.manojbhadane.QButton
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="OK"
app:qb_backgroundColor="@color/green"
app:qb_radius="100"
app:qb_strokeColor="@color/darkGreen"
app:qb_strokeWidth="5" />