Reputation: 1359
This question was asked on SO many times, but still I didn't find a good solution for this problem.
Why do I need this to do? Well because project me and my team develops has iOS style.
What did I try?
So is there a way to change shadow color of CardView with minimum edits of all layout files and with drawing shadow outside of the view like original CardView does?
Upvotes: 51
Views: 83650
Reputation: 1
enter image description hereI know I'm late but I want to share the solution as I searched hard for this issue and solved the issue The solution is, You have to use "ComplexView" to create your custom shadow,
dependency: implementation 'com.github.BluRe-CN:ComplexView:v1.1'
XML:
<com.blure.complexview.ComplexView
android:id="@+id/shadow_card_1"
android:layout_width="@dimen/_65sdp"
android:layout_height="@dimen/_65sdp"
android:layout_centerInParent="true"
app:radius="@dimen/_30sdp"
app:shadow="true"
app:shadowAlpha="250"
app:shadowSpread="2"/>
//this will create the circular shadow for my need you can reduce the radius
Custom View
val shadow = ComplexView(context)
val radii = floatArrayOf(100f, 100f, 100f, 100f, 100f, 100f, 100f, 100f)//customise according to your requirement
val opacity = 150//customise according to your requirement
shadow.shadow =Shadow(
2,
opacity,
"#96B9BB",
GradientDrawable.RECTANGLE,
radii,
Shadow.Position.CENTER
)
val param: RelativeLayout.LayoutParams =
RelativeLayout.LayoutParams(
context.resources.getDimension(R.dimen._160sdp).toInt(),
context.resources.getDimension(R.dimen._160sdp).toInt()
)
shadow.layoutParams = param
shadow.addView(yourCustomView)
thanks :)
Upvotes: 0
Reputation: 3458
display shadow >= 28 or >= P for above Sdk level 28
use below code in your CardView
with xml
android:outlineAmbientShadowColor="<yourCoolor>"
android:outlineSpotShadowColor="<yourCoolor>"
with java and kt file
mCardView.setOutlineAmbientShadowColor(ContextCompat.getColor(getContext(), R.color.color_new_yellow));
mCardView.setOutlineSpotShadowColor(ContextCompat.getColor(getContext(), R.color.color_new_yellow));
display like this
Upvotes: 10
Reputation: 2990
Simple way to change card 's shadow color is to set android:outlineSpotShadowColor="@color/#CCCCCC"
inside your CardView
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardElevation="15dp"
android:outlineAmbientShadowColor="@color/#CCCCCC"
android:outlineSpotShadowColor="@color/#CCCCCC" />
Upvotes: -1
Reputation: 1046
Already late for the answer.
Some trick can work perfectly for me
And XML file like
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical">
<androidx.cardview.widget.CardView
android:id="@+id/cardview"
android:layout_width="@dimen/_150sdp"
android:layout_height="@dimen/_150sdp"
android:layout_marginLeft="@dimen/_10sdp"
android:layout_marginRight="@dimen/_10sdp"
app:cardBackgroundColor="@color/white"
app:cardCornerRadius="@dimen/_5sdp"
app:cardUseCompatPadding="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="@dimen/_50sdp"
android:orientation="vertical">
</LinearLayout>
<View
android:id="@+id/view_color"
android:layout_width="match_parent"
android:layout_height="@dimen/_2sdp"
android:layout_gravity="bottom"
android:background="@color/app_green" />
</androidx.cardview.widget.CardView>
</LinearLayout>
Enjoy coding
Upvotes: -1
Reputation: 1363
Use Fake Shadow.
Well, it is not possible to change the color of the shadow of cardview before API 28 but we can add a custom shadow behind a layout. You need to use a drawable background (shadow.xml
) in the parent layout which is looking like a shadow.
shadow.xml -
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape>
<padding
android:bottom="2dp"
android:left="2dp"
android:right="2dp"
android:top="2dp" />
<solid android:color="#05FF46A9" />
<corners android:radius="15dp" />
</shape>
</item>
<item>
<shape>
<padding
android:bottom="2dp"
android:left="2dp"
android:right="2dp"
android:top="2dp" />
<solid android:color="#10FF46A9" />
<corners android:radius="15dp" />
</shape>
</item>
<item>
<shape>
<padding
android:bottom="2dp"
android:left="2dp"
android:right="2dp"
android:top="2dp" />
<solid android:color="#15FF46A9" />
<corners android:radius="15dp" />
</shape>
</item>
<item>
<shape>
<padding
android:bottom="2dp"
android:left="2dp"
android:right="2dp"
android:top="2dp" />
<solid android:color="#20FF46A9" />
<corners android:radius="15dp" />
</shape>
</item>
<item>
<shape>
<padding
android:bottom="2dp"
android:left="2dp"
android:right="2dp"
android:top="2dp" />
<solid android:color="#25FF46A9" />
<corners android:radius="15dp" />
</shape>
</item>
</layer-list>
Now use the following code -
<FrameLayout
android:layout_width="match_parent"
android:background="@drawable/shadow"
android:layout_height="200dp">
<CardView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:cardCornerRadius="15dp"
app:cardElevation="0dp">
<!-- your code here -->
</CardView>
</FrameLayout>
You can replace FF46A9
in shadow.xml
to change the color of shadow.
Also android:backgroundTint="@color/colorShadow"
works but you have to adjust colors alpha in shadow.xml.
Adjust the <corners android:radius="15dp"/>
as app:cardCornerRadius="15dp"
.
Upvotes: 2
Reputation: 11
This trick is difficult to achieve in most cases , due Official Android Framework do not have any way to change the cardview shadow color. In this case you refers to ilumination light on the cardview . This library is optimized for this this trick.
Library Link:https://github.com/meetsl/SCardView-master I hope can help you! Good Luck
Upvotes: 0
Reputation: 62199
Consider this thread in twitter, where Nick Butcher talks about how to implement the feature:
See outlineAmbientShadowColor
, outlineSpotShadowColor
, spotShadowAlpha
and ambientShadowAlpha
attributes for details. Unfortunately, that's possible from API 28 onwards.
For lower APIs Nick has shared a gist. Here's the result:
Running on API 21
This technique isn't directly connected to CardView
, it can be applied to any View
.
Upvotes: 53
Reputation: 12735
Well I think of an easy solution without using a Java or Some Libraries. You should make a Drawable shape and put it in the drawable
folder and then adjust the gradient to be like a shadow.
For example, in my solution I have added two colors:
<color name="yellow_middle">#ffee58</color>
<color name="yellow_end">#7ae7de83</color>
Then I made a file and put it in drawable folder drawable\card_view_shape.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<size
android:width="10dp"
android:height="10dp" />
<corners android:radius="6dp" />
<stroke
android:width="2dp"
android:color="@color/yellow_end" />
<gradient
android:angle="-90"
android:centerColor="@color/yellow_middle"
android:endColor="@color/yellow_end"
android:startColor="#fff" />
</shape>
Then from there you need to wrap a your view(that would have been inside CardView) in a container like LinearLayout
then apply as the background to the container that you want to be seen like a cardview. To solve it well add some padding (Thats your shadow) to the Container itself. For instance check mine:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.xenolion.ritetrends.MainActivity">
<LinearLayout
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_gravity="center"
android:background="@drawable/card_view_shape"
android:orientation="vertical"
android:paddingBottom="10dp"
android:paddingLeft="3dp"
android:paddingRight="3dp"
android:paddingTop="3dp">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#fff"
android:gravity="center"
android:text="I love StackOverflow"
android:textColor="#000"
android:textSize="18sp" />
</LinearLayout>
</FrameLayout>
Then the results looks like this:
Adjusting the bottom padding it will look like this:
COMMENT
Since I am not of an artist but if you play with it you may make the whole thing look exactly like CardView
check some hints:
CardView
.Upvotes: 6
Reputation: 2177
You Can Implement this without having a cardview, and can also have all the properties of cardview
You have to Do:
Copy the two classes
Wrap your required view with the Custom View as in the example, you don't have to do much changes in your layout or anywhere else!
The below class will create a custom view, this will be wrapping your layout/View to be displayed in cardview with custom shadow color
Create a class:
import android.content.Context;
import android.support.annotation.Nullable;
import android.support.v4.content.ContextCompat;
import android.util.AttributeSet;
import android.view.Gravity;
import android.widget.LinearLayout;
import com.qzion.nfscrew.R;
public class RoundLinerLayoutNormal extends LinearLayout {
public RoundLinerLayoutNormal(Context context) {
super(context);
initBackground();
}
public RoundLinerLayoutNormal(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
initBackground();
}
public RoundLinerLayoutNormal(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initBackground();
}
private void initBackground() {
setBackground(ViewUtils.generateBackgroundWithShadow(this,R.color.white,
R.dimen.radius_corner,R.color.colorPrimaryDark,R.dimen.elevation, Gravity.BOTTOM));
}
}
Also create the class for the Shadow Settings, ViewUtils.java
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.shapes.RoundRectShape;
import android.support.annotation.ColorRes;
import android.support.annotation.DimenRes;
import android.support.v4.content.ContextCompat;
import android.view.Gravity;
import android.view.View;
import static android.support.v4.view.ViewCompat.LAYER_TYPE_SOFTWARE;
public class ViewUtils {
public static Drawable generateBackgroundWithShadow(View view, @ColorRes int backgroundColor,
@DimenRes int cornerRadius,
@ColorRes int shadowColor,
@DimenRes int elevation,
int shadowGravity) {
float cornerRadiusValue = view.getContext().getResources().getDimension(cornerRadius);
int elevationValue = (int) view.getContext().getResources().getDimension(elevation);
int shadowColorValue = ContextCompat.getColor(view.getContext(),shadowColor);
int backgroundColorValue = ContextCompat.getColor(view.getContext(),backgroundColor);
float[] outerRadius = {cornerRadiusValue, cornerRadiusValue, cornerRadiusValue,
cornerRadiusValue, cornerRadiusValue, cornerRadiusValue, cornerRadiusValue,
cornerRadiusValue};
Paint backgroundPaint = new Paint();
backgroundPaint.setStyle(Paint.Style.FILL);
backgroundPaint.setShadowLayer(cornerRadiusValue, 0, 0, 0);
Rect shapeDrawablePadding = new Rect();
shapeDrawablePadding.left = elevationValue;
shapeDrawablePadding.right = elevationValue;
int DY;
switch (shadowGravity) {
case Gravity.CENTER:
shapeDrawablePadding.top = elevationValue;
shapeDrawablePadding.bottom = elevationValue;
DY = 0;
break;
case Gravity.TOP:
shapeDrawablePadding.top = elevationValue*2;
shapeDrawablePadding.bottom = elevationValue;
DY = -1*elevationValue/3;
break;
default:
case Gravity.BOTTOM:
shapeDrawablePadding.top = elevationValue;
shapeDrawablePadding.bottom = elevationValue*2;
DY = elevationValue/3;
break;
}
ShapeDrawable shapeDrawable = new ShapeDrawable();
shapeDrawable.setPadding(shapeDrawablePadding);
shapeDrawable.getPaint().setColor(backgroundColorValue);
shapeDrawable.getPaint().setShadowLayer(cornerRadiusValue/3, 0, DY, shadowColorValue);
view.setLayerType(LAYER_TYPE_SOFTWARE, shapeDrawable.getPaint());
shapeDrawable.setShape(new RoundRectShape(outerRadius, null, null));
LayerDrawable drawable = new LayerDrawable(new Drawable[]{shapeDrawable});
drawable.setLayerInset(0, elevationValue, elevationValue*2, elevationValue, elevationValue*2);
return drawable;
}
}
and finally your XML, where you have the views required to have shadow.
<com.qzion.nfscrew.utils.RoundLinerLayoutNormal
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="This view will have shadow"/>
</com.qzion.nfscrew.utils.RoundLinerLayoutNormal>
Upvotes: 5