113

In xml, I often do this to emulate onClick effect:

<android.support.v7.widget.CardView
    android:id="@+id/cardView"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:foreground="?selectableItemBackground">

    ...

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

Is there any way to access ?selectableItemBackground in java?

Zoe
  • 27,060
  • 21
  • 118
  • 148
Hendra Anggrian
  • 5,780
  • 13
  • 57
  • 97

9 Answers9

237

For appcompat you can use,

TypedValue outValue = new TypedValue();
getContext().getTheme().resolveAttribute(android.R.attr.selectableItemBackground, outValue, true);
cardView.setBackgroundResource(outValue.resourceId);
Amit Vaghela
  • 22,772
  • 22
  • 86
  • 142
61

For those who work with Kotlin, here are some extensions functions to add Ripple on Android View type :

private fun View.addRipple() = with(TypedValue()) {
    context.theme.resolveAttribute(android.R.attr.selectableItemBackground, this, true)
    setBackgroundResource(resourceId)
}

private fun View.addCircleRipple() = with(TypedValue()) {
    context.theme.resolveAttribute(android.R.attr.selectableItemBackgroundBorderless, this, true)
    setBackgroundResource(resourceId)
}
Luca Murra
  • 1,848
  • 14
  • 24
Nicolas Duponchel
  • 1,219
  • 10
  • 17
26

I was looking for the same solution. I slightly changed this answer to make it more suitable for the asked question. Call the following code from your constructor.

private void setClickableAnimation(Context context)
{
    TypedValue outValue = new TypedValue();
    context.getTheme().resolveAttribute( 
        android.R.attr.selectableItemBackground, outValue, true);        
    setForeground(getDrawable(context, outValue.resourceId));
}
Wirling
  • 4,810
  • 3
  • 48
  • 78
9

For Kotlin I'm using

binding.yourCoolView.apply {
    background = with(TypedValue()) {
        context.theme.resolveAttribute(
            androidx.appcompat.R.attr.selectableItemBackground, this, true)
        ContextCompat.getDrawable(context, resourceId)
    }
}
latsson
  • 630
  • 7
  • 8
8

For people using Kotlin, this is an extended version of @Nicolas answer. If you are using CardView, you need to change the foreground, not the background.

Code

fun View.addBackgroundRipple() = with(TypedValue()) {
    context.theme.resolveAttribute(android.R.attr.selectableItemBackground, this, true)
    setBackgroundResource(resourceId)
}

fun View.addBackgroundCircleRipple() = with(TypedValue()) {
    context.theme.resolveAttribute(android.R.attr.selectableItemBackgroundBorderless, this, true)
    setBackgroundResource(resourceId)
}

fun View.addForegroundRipple() = with(TypedValue()) {
    context.theme.resolveAttribute(android.R.attr.selectableItemBackground, this, true)
    foreground = ContextCompat.getDrawable(context, resourceId)
}

fun View.addForegroundCircleRipple() = with(TypedValue()) {
    context.theme.resolveAttribute(android.R.attr.selectableItemBackgroundBorderless, this, true)
    foreground = ContextCompat.getDrawable(context, resourceId)
}

Usage

// Background ripple
linearLayout.addBackgroundRipple()

// Foreground ripple
cardView.addForegroundRipple()
Wachid Susilo
  • 496
  • 4
  • 11
7

You should reference it as

android.R.attr.selectableItemBackground

vanomart
  • 1,739
  • 1
  • 18
  • 39
0

Based on @Wirling answer we can use foreground to set both the color and the ripple effect

Note: Foreground requires android API level 23(M) and above:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {  
    TypedValue outValue = new TypedValue();
    getContext().getTheme().resolveAttribute(android.R.attr.selectableItemBackground, outValue, true);
    view.setForeground(getDrawable(getContext(), outValue.resourceId));
}
-1

Try below code.

int[] attrs = new int[]{R.attr.selectableItemBackground};
TypedArray typedArray = context.obtainStyledAttributes(attrs);
int backgroundResource = typedArray.getResourceId(0, 0);
cardView.setBackgroundResource(backgroundResource);
cardView.setClickable(true);
typedArray.recycle();
Hardik Trivedi
  • 5,677
  • 5
  • 31
  • 51
  • 1
    I'm sorry but this code doesn't make sense to me, what's the point of obtaining `TypedArray` if you're not getting any resource from it? – Hendra Anggrian Jun 23 '16 at 09:47
-1

From a fragment:

TypedValue outValue = new TypedValue();
requireContext().getTheme().resolveAttribute(android.R.attr.selectableItemBackground, outValue, true);
cardView.setBackgroundResource(outValue.resourceId);

From an adapter declaring in its constructor the context or the same fragment:

TypedValue outValue = new TypedValue();
fragment.requireContext().getTheme().resolveAttribute(android.R.attr.selectableItemBackground, outValue, true);
holder.cardView.setBackgroundResource(outValue.resourceId);