Como fazer uma ondulação circular em um botão quando ele está sendo clicado?

121

fundo

No aplicativo discador do Android, quando você começa a pesquisar algo e clica no botão de seta à esquerda do EditText, obtém um efeito de ondulação circular sobre ele:

insira a descrição da imagem aqui

O problema

Eu tentei ter também, mas consegui um retangular:

    <ImageButton
        android:id="@+id/navButton"
        android:layout_width="40dp"
        android:layout_height="40dp"
        android:layout_gravity="center_vertical"
        android:layout_marginLeft="8dp"
        android:background="?android:attr/selectableItemBackground"
        android:src="@drawable/search_ic_back_arrow"/>

A questão

Como faço para que o botão tenha um efeito de ondulação circular ao ser clicado? Tenho de criar um novo drawable ou existe uma forma incorporada para isso?

desenvolvedor android
fonte
2
github.com/traex/RippleEffect experimente isto
rápido
a resposta possível está aqui stackoverflow.com/questions/33477025/…
Amrish Kakadiya,
1
Considere alterar sua resposta selecionada para aquela com mais votos positivos, pois ela realmente resolve o problema
Jeff Barger,
@JeffBarger Por quê? Ambos funcionam bem. Não há ninguém melhor entre eles.
desenvolvedor Android

Respostas:

17

Se você já tem uma imagem de plano de fundo, aqui está um exemplo de ondulação que se parece com selectableItemBackgroundBorderless:

            <ImageButton
                android:id="@+id/btn_show_filter_dialog"
                android:layout_width="24dp"
                android:layout_height="24dp"
                android:background="@drawable/ic_filter_state"/>

ic_filter_state.xml:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:state_pressed="true"
        android:state_enabled="true"
        android:drawable="@drawable/state_pressed_ripple"/>
    <item
        android:state_enabled="true"
        android:drawable="@drawable/ic_filter" />
</selector>

state_pressed_ripple.xml: (opacidade definida para 10% no fundo branco) 1AFFFFFF

 <?xml version="1.0" encoding="UTF-8"?>    
    <ripple xmlns:android="http://schemas.android.com/apk/res/android">
        <item>
            <shape android:shape="oval">
                <solid android:color="#1AFFFFFF"/>
            </shape>
            <color android:color="#FFF"/>
        </item>
    </ripple>
amor ao vivo
fonte
285

Se você estiver usando o tema AppCompat, poderá definir o plano de fundo da visualização como:

android:background="?selectableItemBackgroundBorderless"

Isso adicionará ondulação circular em 21 e acima e fundo quadrado abaixo de 21.

vinculo
fonte
Agradável. Também posso definir a cor dele de alguma forma?
desenvolvedor Android
4
na API 23, o fundo 'up' parece ter metade do tamanho em comparação com selectbleItemBackgroundBorderless
snodnipper
3
Boa, melhor resposta. ty
Skywalker
1
@androiddeveloper, a cor pode ser definida configurando colorControlHighlight como abaixo em seu styles.xml <item name = "colorControlHighlight"> # F00 </item>
bond de
3
Se você estiver usando-o dentro de outros layouts, pode ser necessário android:clipChildren="false"nos layouts também para permitir que a animação se propague.
Tanasis
82

Outro atributo com efeito de ondulação redondo, especialmente para barra de ação:

android:background="?actionBarItemBackground"

UPD : a cor ondulada pode ser alterada por este atributo:

<!--somewhere in styles-->
<item name="colorControlHighlight">your_color_here</item>

Mas lembre-se de que esse atributo se aplica a todos os efeitos de propagação padrão.

Anrimian
fonte
Alguma maneira de personalizá-lo? Por exemplo, a cor? Talvez algo em estilos? Ou ainda mais especificamente na própria tag XML de exibição?
desenvolvedor Android de
Não sei, hoje resolvi esse problema e as respostas acima não funcionaram como eu precisava. Presumo que a cor pode ser personalizada em estilos, mas definitivamente não na visualização.
Anrimian
1
Este é exatamente o efeito certo que estou procurando. A propósito, você pode mencionar onde encontrar este atributo, ele parece não estar documentado.
Jack Wang
2
Responde à pergunta do OP. Deve ser marcado como a melhor resposta. +1
Corbella
2
@MeysamHadigheh ?é um atalho para?attr/
musooff
47

Crie e defina um drawable ondulado como plano de fundo. Algo assim.

<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    android:color="@color/grey_15">
    <item android:id="@android:id/mask">
        <shape android:shape="oval">
            <solid android:color="?android:colorPrimary"/>
        </shape>
        <color android:color="@color/white"/>
    </item>
</ripple>
Thomas R.
fonte
É algo no meu código. Você pode usar suas cores :)
Thomas R.
Como eu usaria o seletor padrão no caso de ser pré-Lollipop? Além disso, ele usa as mesmas cores do discador?
desenvolvedor Android de
2
Você pode colocar o drawable ondulado em sua pasta drawables-v21. E para pre L use um drawable de estado simples. Use o mesmo nome de arquivo e coloque-o na pasta drawable (padrão).
Thomas R.
2
Você também pode criar um estilo. Na pasta values-v21, crie um novo estilo e defina o drawable ondulado como plano de fundo. E para pre L, ou seja, em sua pasta de valores styles.xml coloque como background o atributo "selectableItemBackground" para o mesmo estilo.
Thomas R.
1
Se você quiser a mesma cor de ondulação dos outros efeitos de ondulação padrão usados ​​no aplicativo, use "? Attr / colorControlHighlight" como a cor.
alexbchr de
27

Basta adicionar este fundo à sua visualização

android:background=?android:attr/actionBarItemBackground

Dipakk Sharma
fonte
18

Você pode criar drawable de ondulação de círculo usando o android:radiusatributo em xml.

Exemplo:

<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    android:color="your_color"
    android:radius="your_radius" />

Preste atenção para que sua your_radiuslargura e altura de visão sejam menores. Por exemplo: se você tem visão com o tamanho 60dp x 60dp your_radiusdeve ser próximo 30dp(largura / 2 ou altura / 2).

Trabalhe no Android 5.0 e superior.

Volodymyr Yatsykiv
fonte
3

Se você quiser arquivos XML mais genéricos, tenho dois arquivos:

1) btn_ripple_background com código:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
    android:state_pressed="true"
    android:state_enabled="true"
    android:drawable="@drawable/ripple_circular_shape"/>
</selector>

2) ripple_circuler_shape com código:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:color="@color/btn_state_pressed_text_color"
    android:shape="oval">
    <solid android:color="@color/btn_state_pressed_text_color" />
</shape>

finalmente o uso:android:foreground="@drawable/ripple_btn_background"

100RaBH
fonte
1

Experimentar:

android:background="@android:color/transparent"
android:clickable="true"
android:focusable="true"
android:foreground="?actionBarItemBackground"
duduCMT
fonte
1
Por favor, não poste apenas código como uma resposta, mas inclua uma explicação sobre o que seu código faz e como ele resolve o problema da questão. As respostas com uma explicação geralmente são de qualidade superior e têm maior probabilidade de atrair votos positivos.
Mark Rotteveel
Mais suave do que definir actionBarItemBackground como plano de fundo. Mas ainda não é exatamente o mesmo que a própria animação da barra de ação.
coolcool1994
1

Se você deseja um efeito cascata que não ultrapasse o limite do círculo, pode verificar este código. Funciona perfeitamente para mim. Apenas lembre-se, você deve fornecer id = @ android: id / mask em ripple_blue.xml

<ImageButton
    android:id="@+id/send_password_to_mail_image_view"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@drawable/ripple_blue"
    android:src="@drawable/ic_filter" />

ripple_blue.xml

<ripple
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:color="@color/colorRipple">

    <item android:id="@android:id/mask">

        <shape android:shape="oval">
            <solid android:color="@color/colorWindowBackground"/>
        </shape>

    </item>

    <item android:id="@android:id/background">

        <shape android:shape="oval">
            <solid android:color="@color/colorWindowBackground"/>
        </shape>

    </item>

</ripple>

color.xml

<resources xmlns:tools="http://schemas.android.com/tools">
    <color name="colorWindowBackground">#F2F5FC</color>
    <color name="colorRipple">#0288d1</color>
</resources>
Aminul Haque Aome
fonte
0

apenas adicione este item no seu

           <ImageButton
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:background="?android:attr/actionBarItemBackground"
                app:srcCompat="@drawable/ic_arrow_drop_down_black_24dp" />
Ali Eslami
fonte
1
Parece idêntico a este: stackoverflow.com/a/54440773/878126 .
desenvolvedor de Android
0

Em Kotlin / Java, você pode fazer o seguinte

fun View.applyCircularRippleEffect() {
    val backgroundResId = context.getResource(android.R.attr.actionBarItemBackground)

    if (backgroundResId != 0) {
        setBackgroundResource(backgroundResId)
        isClickable = true
        isFocusable = true
    }
}

// getResource extension
fun Context.getResource(resourceId: Int): Int {
    val out = TypedValue()
    theme.resolveAttribute(resourceId, out, true)

    return out.resourceId
}
mihails.kuzmins
fonte
context.getResource não encontrado
Rahul Mandaliya
@RahulMandaliya obrigado pelo comentário. Que pena, era meu método de extensão customizada. Adicionado à resposta
mihails.kuzmins