Ripple-Effekt auf Android Lollipop CardView

189

Ich versuche, eine CardView dazu zu bringen, den Welligkeitseffekt anzuzeigen, wenn sie berührt wird, indem das Attribut android: backgound in der Aktivitäts-XML-Datei festgelegt wird, wie hier auf der Seite für Android-Entwickler beschrieben, aber es funktioniert nicht. Überhaupt keine Animation, aber die Methode in onClick wird aufgerufen. Ich habe auch versucht, eine ripple.xml-Datei zu erstellen, wie hier vorgeschlagen , aber das gleiche Ergebnis.

Die CardView, wie sie in der XML-Datei der Aktivität angezeigt wird:

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

Ich bin relativ neu in der Android-Entwicklung, daher habe ich möglicherweise ein paar offensichtliche Fehler gemacht.
Danke im Voraus.

AkraticCritic
quelle

Antworten:

589

Sie sollten Folgendes hinzufügen zu CardView:

android:foreground="?android:attr/selectableItemBackground"
android:clickable="true"
Jaden Gu
quelle
8
Funktioniert auf Lutschern mit Welleneffekt, liefert jedoch nur Volltonfarben, wenn sie auf älteren Plattformen ausgeführt werden. Gut genug für mich :)
mach
16
Eine kleine Bemerkung: Ich habe festgestellt, dass das anklickbare Attribut nicht notwendig ist und sogar einige Dinge beschädigen kann! Ich hatte eine GridView mit anklickbaren CardViews gefüllt und der Listener funktionierte nicht richtig. Ich habe das anklickbare Tag aus dem XML entfernt und alles funktioniert jetzt einwandfrei
Joaquin Iurchuk
2
@joaquin ohne das anklickbare, es bewirkt, dass die Welligkeit nur von der Mitte stammt
frostymarvelous
2
?android:attr/selectableItemBackgrounderfordert API Level 11
Pratik Butani
9
Arbeiten ohne android:clickable="true".
Sean
30

Fügen Sie diesen zweizeiligen Code in Ihre XML-Ansicht ein, um einen Welleneffekt auf Ihre cardView zu erzielen.

android:clickable="true"
android:foreground="?android:attr/selectableItemBackground"
Abdul Rizwan
quelle
Genial! foregroundfunktioniert mit benutzerdefinierten Hintergrundansichten wie ein Zauber! Nett!
Sud007
24

Ich habe es geschafft, den Welleneffekt auf die Kartenansicht zu bekommen, indem ich:

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

und für das custom_bg, das Sie im obigen Code sehen können, müssen Sie eine XML-Datei sowohl für Lollipop- (im drawable-v21-Paket) als auch für Pre-Lollipop-Geräte (im Drawable-Paket) definieren. Für custom_bg im drawable-v21-Paket lautet der Code:

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

Für custom_bg im Zeichenpaket lautet der Code:

<?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>

Auf Pre-Lollipop-Geräten haben Sie also einen soliden Klick-Effekt und auf Lollipop-Geräten einen Ripple-Effekt auf die Kartenansicht.

Rahul Ahuja
quelle
1
Hallo, ich stelle fest, dass durch Anwenden des Selektors (oder der Welligkeit) auf den Vordergrund von CardView Kinder in CardView selbst blockiert werden - stackoverflow.com/questions/33763403/… Darf ich wissen, dass Sie auf dasselbe Problem stoßen wie ich? Oder verpasse ich etwas? Vielen Dank.
Cheok Yan Cheng
@CheokYanCheng: Ich habe kein Problem wie das Ihre, aber ich würde aus persönlicher Erfahrung sagen, dass cardView einige Fehler für Pre-Lollipop hat. Vermeiden Sie die Verwendung von cardview: height-Eigenschaft in Pre-Lollipop. Das obige funktioniert gut für mich und andere positive Stimmen.
Rahul Ahuja
Darf ich wissen, welchen Wert Ihr colorHighlight & navigation_drawer_background hat? Wenn Sie Ihre eigene definierte Farbe ohne Transparenz verwendet haben, können Sie die Kinder Ihrer Karte trotzdem sehen?
Cheok Yan Cheng
@CheokYanCheng: Werte sind wie folgt: <color name = "navigation_drawer_background"> ​​# FFFFFF </ color> <color name = "colorHighlight"> # FF8A65 </ color>
Rahul Ahuja
Ich arbeite nicht für meinen Fall. Ich benutze Ihren Selektor als Vordergrund. Wie erwartet blockiert eine feste weiße Farbe (navigation_drawer_background), die als Vordergrund für die Kartenansicht verwendet wird, die Sichtbarkeit aller untergeordneten Elemente - i.imgur.com/CleYh5B.png So sieht es aus, ohne den Selektor als Vordergrund anzuwenden
Cheok Yan Cheng
14

Der Ripple-Effekt wurde in der von Ihnen verwendeten Appcompat-Unterstützungsbibliothek weggelassen. Wenn Sie die Welligkeit sehen möchten, verwenden Sie die Android L-Version und testen Sie sie auf einem Android L-Gerät. Auf der AppCompat v7-Site:

"Warum gibt es vor Lollipop keine Welligkeiten? RippleDrawable läuft unter anderem mit dem neuen RenderThread von Android 5.0 reibungslos. Um die Leistung in früheren Android-Versionen zu optimieren, haben wir RippleDrawable vorerst ausgelassen."

Überprüfen Sie diesen Link hier für weitere Informationen

Entwickler Paul
quelle
Das wäre es. Vielen Dank!
AkraticCritic
39
Aber wie würden Sie dann den Welleneffekt auf cardView für Android Lollipop setzen?
Android-Entwickler
Also muss ich mich zwischen Abwärtskompatibilität mit Appcompat oder allen neuen Effekten entscheiden, Klassen aus dem Android Core verwenden, mich aber auf API 21 beschränken?
Urs Reupke
Sie könnten 2 APKs erstellen, eine für 21+ und die andere für <21. Oder Sie teilen den Code, da 21+ nicht supportActionbar usw. verwendet. Das klingt nach viel Ärger, aber das ist Ihre Lösung, glaube ich.
Mathijs Segers
1
Aus diesem Grund ist das Schreiben von "reinen" Android L-Anwendungen derzeit nicht möglich. Ab Juli 2015 werden Sie 12% der Android-Nutzer ansprechen.
Glenn Bech
9

Wenn die App, an minSdkVersionder Sie arbeiten, Stufe 9 ist, können Sie Folgendes verwenden:

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

Ab Stufe 11 verwenden Sie stattdessen:

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

Aus der Dokumentation:

clickable - Legt fest, ob diese Ansicht auf Klickereignisse reagiert. Muss ein boolescher Wert sein, entweder "true" oder "false".

Vordergrund - Definiert das Zeichenelement, das über den Inhalt gezeichnet werden soll. Dies kann als Overlay verwendet werden. Das im Vordergrund gezeichnete Bild nimmt am Auffüllen des Inhalts teil, wenn die Schwerkraft auf Füllung eingestellt ist.

Filipe Brito
quelle
6

Für mich hat das Hinzufügen von foregroundzu CardViewnicht funktioniert (Grund unbekannt: /)

Das gleiche zum untergeordneten Layout hinzuzufügen, hat den Trick getan.

CODE:

<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
quelle
2
Das liegt daran, dass das Kind das Ereignis abfängt. Wenn Sie versuchen, der Kartenansicht eine Auffüllung hinzuzufügen (etwa 20 dp), und auf den Teil klicken, in dem sich die Auffüllung befinden würde, sehen Sie den Welleneffekt auch ohne das Kind das Vordergrundattribut gesetzt
Cruces
1
Dies funktionierte auch bei mir mit den neuen Materialkomponenten: com.google.android.material.card.MaterialCardView. Ich hatte einen Elevation stateListAnimator für die Kartenansicht, um die Höhe und die Welligkeit anzupassen, die auf das Layout der inneren Einschränkung angewendet wurden, mit einem auswählbaren Elementhintergrund im Vordergrund ohne anklickbares Attribut.
Patty P
Ich erinnere mich jetzt nicht daran, aber es gibt eine Möglichkeit, die untergeordneten Ansichten so einzustellen, dass sie nicht auf das Klickereignis reagieren
Jemand irgendwo
3

Fügen Sie diese beiden Code-ähnlichen Funktionen wie einen Zauber für jede Ansicht wie Button, Linear Layout oder CardView hinzu. Setzen Sie einfach diese beiden Zeilen und sehen Sie die Magie ...

android:foreground="?android:attr/selectableItemBackground"
android:clickable="true"
Hitesh Kushwah
quelle
2

Wenn es ein Root-Layout wie RelativeLayout oder LinearLayout gibt, das die gesamte Komponente des Adapterelements in CardView enthält, müssen Sie das Hintergrundattribut in diesem Root-Layout festlegen. mögen:

<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
quelle
2

Ripple- Ereignis für die Android- CardviewKontrolle:

<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
quelle
1

Ich war mit AppCompat nicht zufrieden, also habe ich mein eigenes CardView geschrieben und Wellen zurückportiert. Hier läuft es auf Galaxy S mit Lebkuchen, also ist es definitiv möglich.

Demo von Ripple auf Galaxy S.

Weitere Details finden Sie im Quellcode .

Zielony
quelle
Die Verbindung ist unterbrochen
Temirbek
1

Fügen Sie Ihrer XML Folgendes hinzu:

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

Und fügen Sie Ihrem Adapter hinzu (wenn es Ihr Fall ist)

    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
quelle
0

Für diejenigen, die nach einer Lösung für das Problem des Ripple-Effekts suchen, der bei einer programmgesteuert erstellten CardView (oder in meinem Fall bei einer benutzerdefinierten Ansicht, die CardView erweitert), die in einer RecyclerView angezeigt wird, nicht funktioniert, hat Folgendes für mich funktioniert. Grundsätzlich scheint das deklarative Deklarieren der XML-Attribute in den anderen Antworten in der XML-Layoutdatei für eine programmgesteuert erstellte CardView oder eine aus einem benutzerdefinierten Layout erstellte nicht zu funktionieren (selbst wenn die Stammansicht CardView ist oder ein Zusammenführungselement verwendet wird) Sie müssen programmgesteuert wie folgt eingestellt werden:

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);
        }
    }
}

Wo MadeupCardView extends CardViewKudos auf diese Antwort für den TypedArrayTeil.

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

Nur API 21 funktionieren und diese verwenden, nicht diese Listenzeilenkartenansicht verwenden

Tarun Umath
quelle