Android ScrollView clipping child elevation shadow [duplicate] - android

This question already has answers here:
Android "elevation" not showing a shadow
(23 answers)
Closed 5 years ago.
As the title states, I'm trying to put a CardView inside a ScrollView, but the CardView elevation shadow is being but off by it's parent...
This is the Layout XML:
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".TestScrollViewActivity">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="128dp"
android:background="?colorPrimary"
android:gravity="bottom"
android:minHeight="?actionBarSize"/>
<ScrollView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="center_horizontal"
android:clipToPadding="false"
android:paddingBottom="40dp"
android:paddingTop="60dp">
<android.support.v7.widget.CardView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:elevation="4dp"
app:cardBackgroundColor="#android:color/white"
app:cardCornerRadius="0dp">
<LinearLayout
android:layout_width="400dp"
android:layout_height="600dp"
android:orientation="vertical">
</LinearLayout>
</android.support.v7.widget.CardView>
</ScrollView>
</FrameLayout>
The only workaround that I found is to add a padding to the parent ScrollView or add a margin to the child CardView...
Is there any option to prevent this from happening without using a padding/margin?
Thanks.
Edit:
This is how the layout looks like without setting a padding on the parent scroll view, as it can be seen, the left and right shadows are being cut off:
Now, if a padding is added to the parent scrollview sides, the shadows are being drawn correctly as it can be seen here:
So, my main question here is this the only way to achieve that?, or there is a tag or a configuration on the parent view that allow to correctly draw it's children views?

this just worked for me in a similar problem:
the right way to get a child view to show shadow is to set padding on the parent and set android:clipToPadding="false" on that parent.
as found here: Android "elevation" not showing a shadow

I was facing the same problem, I solved it by adding cardUseCompatPadding attribute to the card view:
app:cardUseCompatPadding="true"
The shadow will not be cut out or cropped after using this solution.

This work for me adding cardUseCompatPadding attribute to the card view:
set android:clipToPadding="false" on that parent.

Related

Nested layout inside CardView overlaps parent end

I have no idea how this can happen, but I have a ConstraintLayout with a CardView inside. Inside said CardView is a LinearLayout. That LinearLayout overlaps the parent on the end. Check the screenshot for more info. If I remove the android:layout_margin from the cardView, the inner layout looks good again, but adding margin to start seems to just push the entire layout to and over the end of the parent. It doesnt matter what sort of layout is used inside the CardView. The issue affects them all.
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:animateLayoutChanges="true"
android:background="#color/colorWhite">
..
<androidx.cardview.widget.CardView
android:id="#+id/wakeuptimer_status_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="#dimen/md_keylines"
app:layout_constraintTop_toTopOf="parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
.....
You need to change the Linearlayout height to match-parent instead of wrap_content. With wrap_content you aren't restricting the size of the Linearlayout view to the size of the CardView.
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

Cardview shadow looks different when inside a ScrollView

I stumbled upon something weird. I am using the same CardView component in more than one place in my app, all with the same elevation (3dp), and they all looks the same. However, for one scenario I need to embed the CardView inside a ScrollView. I didn't change anything in the CardView configuration, but the shadow now looks different.
This is my layout:
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipChildren="false"
android:clipToPadding="false"
android:padding="16dp"
android:scrollbars="none">
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipChildren="false"
android:clipToPadding="false"
app:cardCornerRadius="8dp"
app:cardElevation="3dp"
app:cardUseCompatPadding="true">
<!-- some other views-->
</androidx.cardview.widget.CardView>
</ScrollView>
In the picture below you can see on the right the CardView and on the left the two shadows: on the top the shadow generated by the CardView alone, on the bottom the one generated when the CardView is inside a ScrollView. As you can see the second one appears darker and thicker.
NOTE: The background color (#FAFAFA) is the same in both scenario.
For both cases, I would check the following properties as it could contribute to the difference you're seeing:
getTranslationZ()
getElevation()
getOutlineAmbientShadowColor() (this is only valid in API 28+)
getOutlineSpotShadowColor() (this is only valid in API 28+)
Plus, checking Layout inspector to see if there's any view that could affect to the rendering.
Also, this article from Sebastiano Poggi could be of help.

Shadow on CardView within ConstraintLayout not showing

I have a CardView within a ConstraintLayout.
This view is then inflated and added to a LinearLayout.
I would like the CardView to cast a shadow on the next CardView, but it seems to be clipped by the ConstraintLayout. How can I get the elevation shadow to show on the CardView without providing more padding or margins for it?
i.e. How can I cast the shadow on an adjacent item?
<LinearLayout>
<ConstraintLayout>
<CardView> <-- This view's shadow is cut
...
</CardView>
</ConstraintLayout>
<ConstraintLayout>
<CardView>
...
</CardView>
</ConstraintLayout>
<LinearLayout>
Try adding this comment inside your card view that's enough
card_view:cardUseCompatPadding="true"
How can I get the elevation shadow to show on the CardView without providing more padding or margins for it?
i.e. How can I cast the shadow on an adjacent item?
You can't, for both a practical reason and a conceptual one.
The practical reason comes down to how the Android framework draws CardView shadows. On older API levels, the card is inset within its own bounds and that extra space is used to draw the shadow. So even if you had two cards immediately next to each other, they'd still have "space" between them due to these insets. From the documentation:
Before Lollipop, CardView adds padding to its content and draws shadows to that area.
On Lollipop and higher, shadows are drawn within the parent's bounds, not within the CardView's bounds. Still, the parent will clip the shadow if there isn't enough space between the card's edges and the parent's edges to draw the whole shadow. In your example, each CardView is in a separate parent, so even if you put those parents immediately next to each other, each parent would still clip its card's shadow.
As for the conceptual reason, that's just not how shadows work (in nature). If you have two cards at the same elevation, even if they're right next to each other, the top card wouldn't cast a shadow on the bottom card.
Try to add
app:cardElevation="10dp"
In order to use app:cardElevation you have to add to your LinearLayout:
xmlns:app="http://schemas.android.com/apk/res-auto"
I tried this in a test project and the elevation should work this way. Below is my code:
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="ro.helpproject.funcode.help.MainActivity">
<android.support.constraint.ConstraintLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center">
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="50dp"
app:cardElevation="10dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TEST TEST" />
</android.support.v7.widget.CardView>
</android.support.constraint.ConstraintLayout>
<android.support.constraint.ConstraintLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center">
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="50dp"
app:cardElevation="10dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TEST TEST" />
</android.support.v7.widget.CardView>
</android.support.constraint.ConstraintLayout>
</LinearLayout>
CardView needs padding around it for shadow to appear.
If app:cardUseCompatPadding="true" adds the shadow for you but you don't want the extra padding from 4 directions (LRTB), you need to add margin to the CardView yourself.
Enable Developer options -> Show layout boundaries and if you see that there is no empty space around your CardView. Then that's probably the reason shadow not appearing.

Incorrect overlay behavior in FrameLayout

According to the docs, child views in FrameLayout are drawn on top of each other with the most recently added view on top. I have notice though, that this seems to not be accurate in Lollipop or later. For example, in the following xml, the button is still visible even though it should be covered by my custom view.
It is worth mentioning that although my custom view extends FrameLayout, I do inflate a child view, so my FrameLayout isn't empty.
<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=".MainActivity">
<Button
android:id="#+id/some_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_gravity="center"
android:text="button"/>
<mycustomframelayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#000000"/>
</FrameLayout>
Any idea what I am missing here?
Buttons in Lollipop and higher have a default elevation to them which causes them to always draw on top. You can change this by overriding the default StateListAnimator.
Try putting this into your button XML:
android:stateListAnimator="#null"
The FrameLayout should now cover the button.
Try putting an elevation to the FrameCustom:
<mycustomframelayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#000000"
android:elevation="100dp"/>

Can't get clipChildren=false attribute to work [duplicate]

This question already has answers here:
clipChildren is not working even though set to false?
(6 answers)
Closed 1 year ago.
I have a yellow RelativeLayout containing a taller red LinearLayout.
In order to make the whole LinearLayout visible, I set android:clipChildren="false", but this does not work as expected:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="44dp"
android:background="#FFFF00"
android:clipChildren="false" >
<LinearLayout
android:layout_width="50dp"
android:layout_height="100dp"
android:background="#FF0000"
android:orientation="vertical" >
</LinearLayout>
</RelativeLayout>
with android:clipChildren="true":
with the red LinearLayout clipped as expected
with android:clipChildren="false":
where the LinearLayout height is clipped, and the width set in the layout is not respected.
What's wrong?
EDIT
If I wrap the container in a LinearLayout with both dimensions matching its parent, I get the same result (I checked that the LinearLayout container's container fill the whole screen).
<LinearLayout 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">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="44dp"
android:background="#FFFF00"
android:clipChildren="false" >
<LinearLayout
android:layout_width="50dp"
android:layout_height="100dp"
android:background="#FF0000"
android:orientation="vertical" >
</LinearLayout>
</RelativeLayout>
</LinearLayout>
EDIT 2
If I put the android:clipChildren="false" attribute in the parent LinearLayout, I get the following:
android:clipChildren="false" allows each child to draw outside of its own bounds, within the parent. It doesn't allow children to draw outside of the parent itself. For that you would need to set android:clipChildren="false" on the grandparent (as well).
I think what you're seeing with the colors is just because colors have no inherent bounds. If there is nothing clipping them, colors go forever. My theory is that if you used, say, a stretched 1x1 px image instead of a color, things would be different.
Also set
android:clipToPadding="false"
Beside:
android:clipChildren="false"
A trick which can solve your problem is to add some placeholder view
<View
android:layout_width="wrap_content"
android:layout_height="1dp"
android:background="?android:attr/listDivider"
android:layout_alignParentBottom="true"/>
in the relative layout and boom!
Explanation
For me the boundary of relative layout seems to be different than the height.
The boundary seems to be where the content ends or where the parent ends. Adding some view to the bottom sets the boudary at the bottom so everything works fine.

Categories

Resources