I have a CardView defined as
<androidx.cardview.widget.CardView
android:layout_width="70dp"
android:layout_height="70dp"
app:cardCornerRadius="35dp"
app:cardElevation="10dp">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="fitXY"
android:src="#drawable/ic_user_default"/>
</androidx.cardview.widget.CardView>
But somehow I am getting this weird shadow, which I am not able to figure out why?
I wanted to have a circular CardView with a circular shadow around it, but instead I am getting a shadow in the right bottom corner.
What am I missing out?
I tried few things and this is what I concluded.
CardView is inside a RelativeLayout which has wrap_content as layout_height. Which I guess is wrapping the CardView only, without it's shadow. Take a look at below example.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center">
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<androidx.cardview.widget.CardView
android:layout_width="70dp"
android:layout_height="70dp"
app:cardCornerRadius="35dp"
app:cardElevation="10dp">
</androidx.cardview.widget.CardView>
</RelativeLayout>
<androidx.cardview.widget.CardView
android:layout_width="70dp"
android:layout_height="70dp"
app:cardCornerRadius="35dp"
app:cardElevation="10dp">
</androidx.cardview.widget.CardView>
</LinearLayout>
Which will show like
So that leads to a question why it's wrapping around the CardView but not CardView with its shadows?
And one side question. How do you center the shadow of CardView? If you look closely to the second CardView, the shadow is has a gravity to bottom.
I suggest you take a look at android documentation for shadows.
You said:
CardView is inside a RelativeLayout which has wrap_content as layout_height. Which I guess is wrapping the CardView only, without it's shadow. So that leads to a question why it's wrapping around the CardView but not CardView with its shadows?
The following answers why:
Shadows are drawn by the parent of the elevated view, and thus subject to standard view clipping, clipped by the parent by default.
Also:
The bounds of a view's background drawable determine the default shape of its shadow. Consider this view, defined with a background drawable:
<TextView
android:id="#+id/myview"
...
android:elevation="2dp"
android:background="#drawable/myrect" />
The background drawable is defined as a rectangle with rounded corners:
<!-- res/drawable/myrect.xml -->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#42000000" />
<corners android:radius="5dp" />
</shape>
The view casts a shadow with rounded corners, since the background drawable defines the view's outline. Providing a custom outline overrides the default shape of a view's shadow.
This you have already achieved with app:cardCornerRadius="35dp" rather than a custom background drawable (which is equally acceptable, although I thought adding this bit of info might be of some additional help if you need it for other views in the future).
To answer the question How do you center the shadow of CardView? you may take a look at the material design guidelines. According to Material Design, shadows should come from both ambient light (front light source) and a key light (top light source):
The elevation of these light sources are by default 90 degrees and 45 degrees respectively in the android framework, and cannot be changed because that would be inconsistent with material design. However, if you want to create a custom shadow with a custom angle, you could use a gradient drawable and set that as a shadow as described here under the head Using Shape Drawable (New way to implement shadow).
Basically, you need to use the setShadowLayer method from the android.graphics.Paint class.
Hope this helps!
The deviation of CardView's shadow depends on its location in screen. As you can see in below picture, when the CardView is placed in left or right side of the screen, its shadow is deviated to left or right side too.
However, AFAIK, we have no control on the CardView's shadow perspective since there is no attribute for it to change. If you want to have a custom direction shadow, you should do it yourself.
Related
I have a shape. I am using a random color to fill the shape.
I have an image which needs to be set for the background of this shape. (I am just thinking it should be background. May be I am using wrong words. )
Result should be something like this (note the image at the background).
I recommend you that library which you can custom corners , shape and other things and then you can put your image view inside it and then you'll have your view
here is the link
https://github.com/florent37/ShapeOfView
You can set src of your image view to those white things you have, then you will have your shape as background and this pattern on it as well.
use android:src
If you want to show an image within a shape, Try this,
shape.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#color/colorPrimaryDark"/>
<corners android:bottomLeftRadius="56dp"/>
</shape>
Now set the shape for a layout, then add the image that you want in image view then adjust the alpha value to show both shape and image,
layout.xml
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="120dp"
android:background="#drawable/shape">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="#drawable/blue_image"
android:alpha=".2"/>
</RelativeLayout>
Output will be like this
Hope this will help.
I came across with this library. RoundedImageView Github link
All I needed to do was:
<com.makeramen.roundedimageview.RoundedImageView
android:layout_width="0dp"
android:layout_height="200dp"
android:src="#drawable/add_card_head_bg"
android:scaleType="centerCrop"
app:riv_corner_radius="90dip"
app:riv_mutate_background="true"
app:riv_corner_radius_bottom_left="50dp"/>
Somewhat similar question here but answer is to just remove elevation and shadow... not what I want: Android CardView with weird border when transparent
What I want is what is shown in the Pixel Launcher search bar... namely a shape which has a semi transparent background and also a shadow, but the shadow does not overlap with the white shape (which would end up making it look grey). I basically want a shadow but with a hole in the middle of it where my shape is...
This is what I want to achieve (the search bar down the bottom):
Here is what I have tried but you can see from the attached picture, that the grey shadow is coming through the semitransparent white background.
activity_main.xml
<FrameLayout
android:layout_width="120dp"
android:layout_height="120dp"
android:background="#drawable/rectangle"
android:elevation="8dp" />
Rectangle.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners android:radius="4dp" />
<solid android:color="#aaffffff" />
</shape>
This is what my attempt looks like:
You can see that even though my shape is semi transparent white on a white background, it turns grey because of the shadow underneath which is not what I want.
I have also tried playing with View#setOutlineProvider with no success.
I have also tried playing with https://github.com/harjot-oberai/MaterialShadows
I don't want to do it with a 9patch image if I can avoid it.
One solution is to apply the transparency to the frame itself, not just the rectangle's background. This would create an effect similar to the one pictured.
For example:
<FrameLayout
android:layout_width="120dp"
android:layout_height="120dp"
android:elevation="8dp"
android:alpha="0.6" />
This of course has problems if you want non-transparent elements, to fix this you could extract out the background, and do something along the lines of:
<FrameLayout
android:layout_width="120dp"
android:layout_height="120dp">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/rectangle"
android:alpha="0.6"
android:elevation="8dp" />
</FrameLayout>
I need to create white rectangle shape with red border (width 1px) and another red rectangle attached to it from below. Like this:
White rectangle will be EditText while red border and red rectangle will appear in order to notify the user about input errors. Nothing fancy.
I have already tried several approaches, but none of them looked good due to the same reason - the color changes towards the edge of a shape (looks like the outermost pixels are the ones that change). The issue can be seen in this magnified picture:
The hierarchy on this particular snapshot is LinearLayout with red background and padding of 1px, but I observed the same effect while attempted to use other approaches as well (including drawing the border around EditText programmatically).
This effect looks like the standard of Android, and my question is how can I disable it?
Check following example, hope it will help you.
rect_shape.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<stroke
android:width="3dp"
android:color="#EF9A9A"/>
<solid android:color="#android:color/white"/>
</shape>
layout.xml
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/rectangle_shape"
android:orientation="vertical">
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#android:color/transparent"
android:lines="3"
android:padding="5dp"/>
<View
android:layout_width="match_parent"
android:layout_height="3dp"
android:background="#EF9A9A"/>
<TextView
android:layout_width="match_parent"
android:layout_height="36dp"
android:layout_marginBottom="3dp"
android:layout_marginLeft="3dp"
android:layout_marginRight="3dp"
android:background="#EF5350"/>
</LinearLayout>
Output:
Just in case anybody stumbles upon this question - the described behavior was some emulator related artifact. On real devices the colors were just fine.
I am attempting to add rounding and shadows to some views on an app and am utilizing the card view library to achieve that. It is looking good on lollipop devices but am running into compatibility issues with anything pre-lollipop.
I will preface this by saying that I have looked at the answers in the questions below have found that none of them are working for me.
Appcompat CardView and Picasso no rounded Corners
Cardview - white border around card
Unnecessary padding in CardView?
The most popular answer was to add the attribute 'cardPreventOverlap=false' but this removes the rounded corners. I have tried variations of this flag and 'cardUseCompatPadding="true"' but none of them seem to do the trick. Has anyone else run into the same problem?
My code:
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
card_view:cardCornerRadius="4dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/selector"
android:gravity="center"
android:orientation="horizontal" >
<ImageView
android:layout_width="44dp"
android:layout_height="match_parent"
android:layout_marginRight="4dp"
android:background="#color/mid_yellow"
android:padding="0dp"
android:src="#drawable/ic_add_white_24dp" />
<TextView
style="#style/Text.Primary.White"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="4dp"
android:text="Button" />
</LinearLayout>
This is how it currently looks on Android 5.0:
The exact same code on 4.4.2 displays as:
With 'cardPreventOverlap=false':
Update Unfortunately we were not able to solve the issue; given that the app only had small install base pre5.0 we decided it was not important. We ended up going with the third option 'cardPreventOverlap=false'.
Content clipping is not supported, because is quite expensive on older devices. If you wish, you can use Carbon. It has its own CardView implementation, which correctly clip content to rounded corners. Carbon also adds content clipping and elevation to all other layouts so for your purpose you can use a LinearLayout with rounded corners and shadow. See the image:
Instead of using card_view:cardCornerRadius you can set the background of the cardview with a drawable like:
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#FFFFFF"/>
<corners android:radius="4dip"/>
</shape>
You can also do this for each element in your cardview such that you have for each element the correct background color.
In that case you can specify only certain corners with:
<corners
android:topLeftRadius="4dp"
android:bottomLeftRadius="4dp"/>
For your + button for example.
Use this in combination with cardUseCompatPadding="true"
I upgraded to Android 4.2 and all of a sudden the linear gradient on my home widget isn't behaving as intended. instead of a gradient i seem to get a constant band. then if i restart the device the gradient starts "working" again, which is very puzzling. I have talked to other team members and their devices don't seem to have an issue. Here is a screen shot of the problem:
The gradient is applied over the bottom half of the image and should go from semi-transparent at the bottom to fully transparent at the top. Instead you can see a basically constant semi-transparent area at the bottom half of the image. The layout is something like:
<RelativeLayout>
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:background="#drawable/gradient"
android:orientation="vertical" >
...
while the gradient background is
<shape>
<gradient
android:angle="90"
android:startColor="#D0000000"
android:endColor= "#00000000"
android:type="linear" />
</shape>
i found that forcing s/w acceleration on the linear layout (setting android:layerType="software") fixed the issue.