Programmatically set '?selectableItemBackground' on Android view
AndroidXmlAndroid LayoutAndroid CardviewAndroid Problem Overview
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?
Android Solutions
Solution 1 - Android
For appcompat you can use,
TypedValue outValue = new TypedValue();
getContext().getTheme().resolveAttribute(android.R.attr.selectableItemBackground, outValue, true);
cardView.setBackgroundResource(outValue.resourceId);
Solution 2 - Android
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)
}
Solution 3 - Android
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));
}
Solution 4 - Android
You should reference it as
android.R.attr.selectableItemBackground
Solution 5 - Android
For Kotlin I'm using
binding.yourCoolView.apply {
background = with(TypedValue()) {
context.theme.resolveAttribute(
R.attr.selectableItemBackground, this, true)
ContextCompat.getDrawable(context, resourceId)
}
}
Solution 6 - Android
For people using Kotlin, this is an extended version of @Nicholas 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()
Solution 7 - Android
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));
}
Solution 8 - Android
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();
Solution 9 - Android
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);