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.

AkraticCritic
fonte

Respostas:

590

Você deve adicionar o seguinte a CardView:

android:foreground="?android:attr/selectableItemBackground"
android:clickable="true"
Jaden Gu
fonte
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"
Abdul Rizwan
fonte
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.

Rahul Ahuja
fonte
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

Desenvolvedor Paul
fonte
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.

Filipe Brito
fonte
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>
Prabs
fonte
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"
Hitesh Kushwah
fonte
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>
Robert Lee
fonte
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" />
chavanNil
fonte
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 .

Zielony
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)
        }
    }
Mateus Melo
fonte
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.

Breeno
fonte
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

Tarun Umath
fonte