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?




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>

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.


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.


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>

É 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


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.


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"


1

Experimentar:

android:background="@android:color/transparent"
android:clickable="true"
android:focusable="true"
android:foreground="?actionBarItemBackground"

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>


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
}

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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.