Como posso modificar a cor da ondulação ao usar? Attr / selectableItemBackground como plano de fundo?

103

Eu vi algumas perguntas do SO e eles deram alguns métodos possíveis para alcançar o que desejo. Por exemplo:

  1. Use o colorControlHighlightatributo em styles.xml.

    Aqui está meu styles-v21.xml:

    <style name="SelectableItemBackground">
        <item name="android:colorControlHighlight">#5677FC</item>
        <item name="android:background">?attr/selectableItemBackground</item>
    </style>

    E meu widget:

    <TextView
        android:id="@+id/tv_take_photo_as_bt"
        android:layout_width="280dp"
        android:layout_height="48dp"
        android:text="@string/act_take_photo"
        style="@style/SelectableItemBackground"/>

    E não funciona. Eu também tentei adicionar parent="Theme.AppCompatao estilo "SelectableItemBackground", ou mudar para colorControlHighlight(no android: prefix)", ou mudar para ?android:attr/selectableItemBackground, nenhum dos dois é útil.

  2. Use o backgroundTintatributo no layout.

    Então eu adiciono android:backgroundTint="#5677FC"ao meu TextView. Ainda inútil. Então tentei mudar android:backgroundTintModepara src_ine src_atop, e eles nunca fizeram diferença.

Então, como posso alterar a cor da ondulação quando uso ?attr/selectableItemBackgroundcomo plano de fundo. Eu me concentro apenas no Lollipop e acima. Agradeço antecipadamente!

ywwynm
fonte

Respostas:

154

Finalmente encontro a solução: em vez de usar android:colorControlHighlightdiretamente no tema SelectableItemBackground, devo escrever outro estilo:

<style name="SelectableItemTheme">
    <item name="colorControlHighlight">@color/ripple_color</item>
</style>

Então:

<style name="SelectableItemBackground">
    <item name="android:theme">@style/SelectableItemTheme</item>
    <item name="android:background">?attr/selectableItemBackground</item>
</style>

Por fim, adicione style="@style/SelectableItemBackground"a Viewem layout.xml.

ATUALIZADO EM 26/08/2016 Após o lançamento de N, descobri que às vezes não podemos usar esse método para definir a cor da ondulação para algum tipo de View(por exemplo, o CardView). Agora eu recomendo fortemente que os desenvolvedores usem RippleDrawable, que também pode ser declarado em xml. Aqui está um exemplo:

Quero mostrar um efeito cascata quando o usuário toca / clica em uma CardViewAPI21 acima e, claro, deve haver outro tipo de feedback antes do Lollipop. Portanto, devo escrever:

<android.support.v7.widget.CardView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:foreground="@drawable/selectable_item_background"/>

e selectable_item_backgroundna drawablepasta:

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="false" android:drawable="@android:color/transparent" />
    <item android:drawable="@color/color_clicked" />
</selector>

selectable_item_backgroundna drawable-v21pasta:

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/ripple_black" />
</selector>

finalmente, a pasta ripple_blackin drawable(ou drawable-v21):

<ripple
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:color="@color/color_clicked"
    tools:ignore="NewApi" /> <!--you can remove this line if it's in v21 folder-->

É isso aí. Para outras visualizações, talvez você deva usar android:background="@drawable/selectable_item_background". Não se esqueça de definir um OnClickListener, OnTouchListenerou algo como aqueles para eles, caso contrário ondulação não será exibido.

ywwynm
fonte
14
Use em colorControlHighlightvez de android:colorControlHighlightfunciona melhor para mim, caso contrário, é apenas para v21 +
Liuting
1
Esta não é a resposta certa, consulte a resposta de @harrane abaixo.
Jin
2
Caso você não tenha definido um ClickListener, apenas torne a visualização clicável clickable="true"e o efeito cascata funcionará
hedisam
58

Efeito ondulação em dispositivos pré e Lollipop +

Harrane e Liuting estão certos. A resposta aceita não é a melhor maneira. Deixe-me mostrar no código como alterar a cor ondulada para versões pré-Lollipop e superiores

  1. Seu AppTheme deve herdar de qualquer tema AppCompat e conter o atributo colorControlHighlight (sem o prefixo 'android:')

    <!-- Application theme. -->
    <style name="AppTheme" parent="@style/Theme.AppCompat.Light.NoActionBar">
    <item name="colorControlHighlight">#40ffffff</item>
    </style>
  2. Sua visualização deve conter clickable = "true" (ou deve ter um listener de cliques definido de forma programática) e o fundo deve ser "? Attr / selectableItemBackgroundBorderless" ou "? Attr / selectableItemBackground":

    <LinearLayout
    ...
    android:clickable="true"
    android:background="?attr/selectableItemBackgroundBorderless"/>

Observação: se sua visualização pai tiver fundo branco, você não verá o efeito cascata, pois é branco. Altere o valor colorControlHighlight para uma cor diferente

Além disso, se você deseja cores onduladas diferentes em atividades diferentes, pode definir o tema pessoal para cada atividade no arquivo Manifest, por exemplo:

       <activity
        android:name="com.myapp.GalleryActivity"
        android:theme="@style/RedRippleTheme"
        />

Cores onduladas diferentes para fragmentos diferentes na mesma atividade?

Você pode alterar os atributos do Tema de atividade para cada fragmento em tempo de execução. Basta substituí-los antes que o fragmento seja inflado com seu estilo personalizado e aplique a um Tema atual:

em valores / estilos.xml

    <style name="colorControlHighlight_blue">
       <item name="colorControlHighlight">@color/main_blue_alpha26</item>
    </style>

Então, em seu fragmento antes da inflação em onCreateView():

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
       getContext().getTheme().applyStyle(R.style.colorControlHighlight_blue, true); //blue ripple color
       View view = inflater.inflate(R.layout.my_fragment_layout, container, false);
       return view;
    }

Este estilo funcionará apenas para este fragmento


Cor ondulada diferente para visualizações diferentes? (Lollipop +)

Você pode alterar a cor da ondulação para cada visualização separadamente usando o colorControlHighlightatributo. Não funcionará se você aplicá-los diretamente a uma visualização:

    <TextView
     ...
     colorControlHighlight="#40ffffff"/> <!-- DOESN'T WORK -->

você deve aplicá-lo como um tema:

<TextView
  ...
  android:theme="@style/colorControlHighlight_blue"/>

PS Além disso, às vezes essa abordagem ajuda se você tiver problemas desconhecidos com o ripple e não conseguir descobrir. No meu caso, usei a biblioteca deslizante de terceiros, que bagunçou os efeitos de ondulação para todo o layout e adicionei explicitamente esse tema a todas as visualizações clicáveis ​​que funcionou para mim.

Kirill Karmazin
fonte
10

Ele está mostrando um efeito cascata com cores na API +21 e um fundo cinza simples na impressora para API -21. Adicione este estilo:

<style name="AppTheme.MyRipple">
   <item name="colorControlHighlight">@color/your_color</item>
   <item name="android:background">?selectableItemBackgroundBorderless</item>
</style>

E configure-o para a vista:

<Button
   ...
   android:theme="@style/AppTheme.MyRipple" />
Mahdi Khansari
fonte
3
É importante notar que realmente é como você escreveu android:themee não o que as pessoas costumam usar style.
desenvolvedor Android de
5

Use as etapas abaixo:

1. Make changes to button view in your layout.xml
2. Add new styles in styles.xml

your_layout.xml

<Button
                        android:id="@+id/setup_submit_button"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:layout_marginTop="16dp"
                        android:text="@string/action_sign_in"
                        android:textStyle="bold"
                        android:background="@color/colorPrimary"
                        android:textColor="@color/white"
                        style="@style/SelectableItemBackground"
                        android:foreground="?android:attr/selectableItemBackground"/>

-O atributo de estilo chama o estilo que criamos.

-O atributo de primeiro plano chama o atributo selecionável padrão do andorid.

styles.xml

 <style name="SelectableItemTheme">
        <item name="colorControlHighlight">@color/white</item>
    </style>


    <style name="SelectableItemBackground">
        <item name="android:theme">@style/SelectableItemTheme</item>
        <item name="android:background">?attr/selectableItemBackground</item>
    </style>
Prajwal W
fonte
0

Este código funciona para mim para criar uma ondulação:

public static void setRippleDrawable(View view, int normalColor, int touchColor) {
    try {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            RippleDrawable rippleDrawable = new RippleDrawable(ColorStateList.valueOf(touchColor), view.getBackground(), null);
            view.setBackground(rippleDrawable);
        } else {
            StateListDrawable stateListDrawable = new StateListDrawable();
            stateListDrawable.addState(new int[]{android.R.attr.state_pressed}, new ColorDrawable(touchColor));
            stateListDrawable.addState(new int[]{android.R.attr.state_focused}, new ColorDrawable(touchColor));
            stateListDrawable.addState(new int[]{}, new ColorDrawable(normalColor));
            view.setBackground(stateListDrawable);
            }
    } catch (Exception e) {
        Log.e(LOG_TAG, "" + e);
    }
}

Não encontrei nenhuma maneira de modificar o atributo selectableItemBackground. É por isso que fiz como acima.

Mika
fonte
0

Em tema preto escuro (ou qualquer outro), tente usar como abaixo, primeiro crie ripple_effect.xmlna drawablepasta e adicione o código como

<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    android:color="#f5f5f5">
    <item android:id="@android:id/mask">
        <shape android:shape="rectangle">
            <solid android:color="#f5f5f5" />

        </shape>
    </item>

</ripple>

em seguida, defina o plano de fundo para sua visualização Qualquer, Linear layout, Button, TextViewetc.

 <TextView
                    android:id="@+id/tvApply"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:background="@drawable/ripple_effect"
                    android:clickable="true"
                    android:text="APPLY"
                    android:textColor="#FFFFFF"
                    android:gravity="center"
                    android:textSize="@dimen/_8sdp"
                    android:padding="@dimen/_8sdp"
                    android:focusable="true" />
OmiK
fonte
-1

Use o atributo foreground como selectableItemBackground e o atributo background como a cor desejada.

android:foreground="?attr/selectableItemBackground"
    android:layout_height="wrap_content"
    android:layout_width="match_parent"
    android:background="@color/white"
Titto jose
fonte
1
Fazendo assim, você não terá a opção de alterar a cor do efeito cascata. A questão -How can I modify ripple color when using ?attr/selectableItemBackground as background?
HB.