Efeito cascata no Android Lollipop CardView


189

Estou tentando fazer com que um CardView exiba o efeito cascata quando tocado ao definir o atributo android: backgound no arquivo XML de atividade, conforme descrito aqui na página Android Developers, mas não está funcionando. Nenhuma animação, mas o método em onClick é chamado. Eu também tentei criar um arquivo ripple.xml como sugerido aqui , mas o mesmo resultado.

O CardView como aparece no arquivo XML da atividade:

<android.support.v7.widget.CardView
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:layout_width="155dp"
    android:layout_height="230dp"
    android:elevation="4dp"
    android:translationZ="5dp"
    android:clickable="true"
    android:focusable="true"
    android:focusableInTouchMode="true"
    android:onClick="showNotices"
    android:background="?android:attr/selectableItemBackground"
    android:id="@+id/notices_card"
    card_view:cardCornerRadius="2dp">

</android.support.v7.widget.CardView> 

Eu sou relativamente novo no desenvolvimento do Android, por isso posso ter cometido alguns erros óbvios.
Desde já, obrigado.

Respostas:


590

Você deve adicionar o seguinte a CardView:

android:foreground="?android:attr/selectableItemBackground"
android:clickable="true"

8
Funciona em pirulito com efeito cascata, mas só fornece cores sólidas quando executado em plataformas mais antigas. Bom o suficiente para me :)
mach

16
Uma pequena observação: notei que o atributo clicável não é necessário e pode até quebrar algumas coisas! Eu tinha um GridView preenchido com CardViews clicáveis ​​e o ouvinte não estava funcionando corretamente. Tirei a tag clickable do XML e tudo agora funciona perfeitamente
Joaquin Iurchuk

2
@joaquin sem a clicável, que provoca o a ondulação se originar de apenas o centro
frostymarvelous

2
?android:attr/selectableItemBackgroundrequer API nível 11
Pratik Butani 14/15

9
Trabalhando sem android:clickable="true".
21318 Sean

30

Adicione esses dois códigos de linha à sua exibição xml para dar um efeito cascata no seu cardView.

android:clickable="true"
android:foreground="?android:attr/selectableItemBackground"

Impressionante! foregroundfunciona com vistas de fundo personalizadas como um encanto! Agradável!
sud007

24

Consegui obter o efeito cascata no cardview:

<android.support.v7.widget.CardView 
    xmlns:card_view="http://schemas.android.com/apk/res-auto" 
    android:clickable="true" 
    android:foreground="@drawable/custom_bg"/>

e para o custom_bg que você pode ver no código acima, é necessário definir um arquivo xml para os dispositivos pirulito (no pacote drawable-v21) e pré-pirulito (no pacote drawable). para custom_bg no pacote drawable-v21, o código é:

<ripple 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:color="?android:attr/colorControlHighlight">
<item
    android:id="@android:id/mask"
    android:drawable="@android:color/white"/>
</ripple>

para custom_bg no pacote extraível, o código é:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">

<item android:state_pressed="true">
    <shape>
        <solid android:color="@color/colorHighlight"></solid>
    </shape>
</item>
<item>
    <shape>
        <solid android:color="@color/navigation_drawer_background"></solid>
    </shape>
</item>
</selector>

portanto, nos dispositivos pré-pirulito, você terá um efeito de clique sólido e nos dispositivos pirulitos, terá um efeito cascata na visualização do cartão.


1
Olá, percebo que, ao aplicar o seletor (ou ondulação) no primeiro plano do CardView, ele bloqueará os filhos no próprio CardView - stackoverflow.com/questions/33763403/… Posso saber que você encontra o mesmo problema que eu? Ou perco alguma coisa? Obrigado.
Cheok Yan Cheng

@CheokYanCheng: Eu não estou enfrentando nenhum problema como o seu, mas eu diria por experiência pessoal que o cardView tem alguns bugs para pré-pirulito. Evite usar cardview: propriedade de elevação no pré-pirulito. O acima exposto funciona bem para mim e para outros votos positivos.
Rahul Ahuja

Posso saber, qual é o valor do seu colorHighlight & navigation_drawer_background. Se você usou sua própria cor definida sem transparência, ainda pode ver os filhos do seu cartão?
Cheok Yan Cheng

@CheokYanCheng: valores são tão, <nome do color = "navigation_drawer_background"> # FFFFFF </ color> <nome do color = "colorHighlight"> # FF8A65 </ color>
Rahul Ahuja

Eu não trabalho para o meu caso. Eu uso o seu seletor como primeiro plano. Como esperado, a cor branca sólida (navigation_drawer_background), usada como primeiro plano da exibição de cartão, bloqueará a visibilidade de todos os filhos - i.imgur.com/CleYh5B.png É assim que parece sem aplicar o seletor como primeiro plano - i.imgur. com / ZXk5Aoq.png
Cheok Yan Cheng

14

O efeito cascata foi omitido na biblioteca de suporte do appcompat, que é o que você está usando. Se você quiser ver a ondulação, use a versão Android L e teste-a em um dispositivo Android L. De acordo com o site AppCompat v7:

"Por que não existem ondulações no pré-pirulito? Muito do que permite que o RippleDrawable funcione sem problemas é o novo RenderThread do Android 5.0. Para otimizar o desempenho nas versões anteriores do Android, deixamos o RippleDrawable de fora por enquanto."

Confira este link aqui para mais informações


Seria isso. Obrigado!
AkraticCritic

39
Mas como você aplicaria o efeito cascata no cardView for Android Lollipop?
desenvolvedor android

Então, eu tenho que decidir entre a compatibilidade com versões anteriores usando appcompat ou com todos os novos efeitos, usando classes do núcleo do Android, mas me limitando à API 21?
precisa saber é o seguinte

Você pode criar 2 APKs para 21+ e outro para <21. Ou dividir o código, já que 21+ não usará o supportActionbar etc. Pode parecer um monte de problemas, mas acredito que seja sua solução.
Mathijs Segers

1
É por isso que escrever aplicativos Android L "puros" não é viável no momento. Em julho de 2015, você estará segmentando 12% da base de usuários do Android.
amigos estão dizendo sobre glenn

10

Se o aplicativo em minSdkVersionque você está trabalhando for do nível 9, você poderá usar:

android:foreground="?selectableItemBackground"
android:clickable="true"

Em vez disso, a partir do nível 11, você usa:

android:foreground="?android:attr/selectableItemBackground"
android:clickable="true"

Da documentação:

clickable - Define se essa exibição reage a eventos de clique. Deve ser um valor booleano, "true" ou "false".

primeiro plano - Define o desenho para desenhar sobre o conteúdo. Isso pode ser usado como uma sobreposição. O drawable do primeiro plano participa do preenchimento do conteúdo se a gravidade estiver definida para preencher.


Usando android: foreground = "? Android: attr / selectableItemBackground" funcionou para compatibilidade com AndroidX, obrigado!
dianakarenms

6

Para mim, acrescentando que o foregroundque CardViewfez não trabalho (razão desconhecida: /)

Adicionar o mesmo ao layout filho fez o truque.

CÓDIGO:

<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:id="@+id/card_view"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:focusable="true"
    android:clickable="true"
    card_view:cardCornerRadius="@dimen/card_corner_radius"
    card_view:cardUseCompatPadding="true">

    <LinearLayout
        android:id="@+id/card_item"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:foreground="?android:attr/selectableItemBackground"
        android:padding="@dimen/card_padding">

    </LinearLayout>
</android.support.v7.widget.CardView>

2
Isso ocorre porque a criança intercepta o evento, se você tentar algo como adicionar preenchimento à visualização do cartão (algo como 20dp) e clicar na parte em que o preenchimento seria, você verá o efeito cascata mesmo sem a criança ter o conjunto de atributos em primeiro plano
Cruces

1
Isso funcionou para mim também, usando os novos Componentes de material: com.google.android.material.card.MaterialCardView. Eu tinha um stateListAnimator de elevação para a visualização do cartão para ajustar a elevação e a ondulação aplicada ao layout da restrição interna com o fundo do item selecionável em primeiro plano sem atributo clicável.
Patty P

Não me lembro agora, mas há uma maneira de definir os pontos de vista da criança não reagir ao evento clique
alguém em algum lugar

3

Adicione esses dois tipos de código como um encanto para qualquer visualização como Button, Linear Layout ou CardView Basta colocar essas duas linhas e ver a mágica ...

android:foreground="?android:attr/selectableItemBackground"
android:clickable="true"

2

Se houver um layout raiz, como RelativeLayout ou LinearLayout, que contenha todo o componente do item do adaptador no CardView, será necessário definir o atributo de plano de fundo nesse layout raiz. gostar:

<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="122dp"
android:layout_marginBottom="6dp"
android:layout_marginLeft="6dp"
android:layout_marginRight="6dp"
card_view:cardCornerRadius="4dp">

<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/touch_bg"/>
</android.support.v7.widget.CardView>

2

Evento Ripple para Cardviewcontrole do Android :

<android.support.v7.widget.CardView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:foreground="?android:attr/selectableItemBackground"
    android:clickable="true"
    android:layout_marginBottom="4dp"
    android:layout_marginTop="4dp" />

1

Eu não estava feliz com o AppCompat, então escrevi meu próprio CardView e modifiquei as ondulações. Aqui está rodando no Galaxy S com Gingerbread, então é definitivamente possível.

Demonstração de Ripple no Galaxy S

Para mais detalhes, verifique o código fonte .


o link está quebrado
temirbek

1

Adicione o seguinte ao seu xml:

android:clickable="true"
android:focusable="true"
android:background="?android:attr/selectableItemBackground"

E adicione ao seu adaptador (se for o seu caso)

    override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            val attrs = intArrayOf(R.attr.selectableItemBackground)
            val typedArray = holder.itemView.context.obtainStyledAttributes(attrs)
            val selectableItemBackground = typedArray.getResourceId(0, 0)
            typedArray.recycle()

            holder.itemView.isClickable = true
            holder.itemView.isFocusable = true
            holder.itemView.foreground = holder.itemView.context.getDrawable(selectableItemBackground)
        }
    }

0

Para aqueles que procuram uma solução para o problema do efeito cascata que não funciona em um CardView criado por programação (ou, no meu caso, exibição personalizada que estende o CardView) sendo mostrado em um RecyclerView, o seguinte funcionou para mim. Basicamente, declarar os atributos XML mencionados nas outras respostas declarativamente no arquivo de layout XML parece não funcionar para um CardView criado por programação ou para um criado a partir de um layout personalizado (mesmo que a exibição raiz seja CardView ou o elemento de mesclagem seja usado), portanto eles devem ser definidos programaticamente da seguinte maneira:

private class MadeUpCardViewHolder extends RecyclerView.ViewHolder {
    private MadeUpCardView cardView;

    public MadeUpCardViewHolder(View v){
        super(v);

        this.cardView = (MadeUpCardView)v;

        // Declaring in XML Layout doesn't seem to work in RecyclerViews
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            int[] attrs = new int[]{R.attr.selectableItemBackground};
            TypedArray typedArray = context.obtainStyledAttributes(attrs);
            int selectableItemBackground = typedArray.getResourceId(0, 0);
            typedArray.recycle();

            this.cardView.setForeground(context.getDrawable(selectableItemBackground));
            this.cardView.setClickable(true);
        }
    }
}

Onde MadeupCardView extends CardViewKudos para esta resposta para a TypedArrayparte.


0
  android:foreground="?android:attr/selectableItemBackgroundBorderless"
   android:clickable="true"
   android:focusable="true"

Apenas trabalhando na api 21 e usar isso, não use esta exibição de cartão de linha da lista

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.