Android CardView Drop shadow gets clipped [duplicate] - android

This question already has answers here:
Elevation shadow is clipped
(4 answers)
Closed 1 year ago.
I am trying to show drop shadow on CardView. The shadow cannot be shown correctly if I put the CardView into a container (like LinearLayout).
My code:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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:background="#FFFFF8"
android:clipToPadding="false"
tools:context=".MainActivity">
<androidx.cardview.widget.CardView
android:layout_width="150dp"
android:layout_height="150dp"
android:translationZ="16dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
/>
<LinearLayout
android:id="#+id/card1"
android:layout_width="match_parent"
android:layout_height="330dp"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:background="#FFFFF8"
android:clipToPadding="false"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent">
<androidx.cardview.widget.CardView
android:layout_width="150dp"
android:layout_height="150dp"
android:translationZ="16dp"
/>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
It looks like:
I have two CardViews, I put the one below into a LinearLayout, as you can see, it has no shadow at top and left. But the upper one looks well.
Is there any way to fix for the scenario when CardView in a LinearLayout?
P.S.:
I don't want to introduce either extra margins on the CardView or extra paddings to the container LinearLayout
I've tried adding android:clipToPadding="false" to the container LinearLayout, but it doesn't help.
I've read this Elevation shadow is clipped, and tried both android:clipToPadding="false" && android:clipChildren="false", it doesn't work.
More context about why I don't want to have extra margins or paddings, my app is data-driven, and same to the drop shadows on CardViews, CardViews can be laid out vertically or horizontally one by one, with or with no drop shadows on them, if I have to take extra margins into account, for displaying the CardViews with shadow, then the logic would be too complex.
Assume such a scenario, say one shadowed CardView, another one shadowed to the right; but one not shadowed to the bottom etc. I have to set margin left to the 1st but no to the right because the 2nd (at right) also has shadow, and for the 2nd one, I have right margin for shadow; same logic to the one below, but logic gets complex here, that why I am asking for a solution here, if the drop shadow can be visible without depending on the margins/paddings, that'd be wonderful for me.
EDIT: Closed because: https://stackoverflow.com/a/57741227/853191, this comment helped me out.
Thanks!

To show drop shadow you should use
android:translationX="16dp", android:translationY="16dp", android:translationZ="16dp" like below.
<LinearLayout
android:id="#+id/card1"
android:layout_width="match_parent"
android:layout_height="330dp"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:background="#FFFFF8"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent">
<androidx.cardview.widget.CardView
android:layout_width="150dp"
android:layout_height="150dp"
android:translationX="16dp"
android:translationY="16dp"
android:translationZ="16dp" />
</LinearLayout>
Output:
Output Image click here!

Related

Can't center button in constraint layout

This question may have been asked a million times and seem trivial but i still do not understand the logic behind it after reading about 100 of answers.
I have this ultra simple layout XML
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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=".MainActivity">
<Button
android:id="#+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0" />
</androidx.constraintlayout.widget.ConstraintLayout>
From my understanding if i set opposing constraints the render engine interprets them automatically as percentage... i mean right ?
If no specific margin or anything is set then it evens out the distances. This would clearly mean that the button should tae a centered position inside the view. But it doesnt....
I dont understand it. i want to center with WITHOUT SETTING A MARGIN since a margin, from my understanding, is something independent of the constraint. It works within a constraint. but nevertheless i set a margin of 50 on each side. once a margin is set on opposing sides the engine should automatically render it as percentage.... right ?
So this XML:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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=".MainActivity">
<Button
android:id="#+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="50dp"
android:layout_marginLeft="50dp"
android:layout_marginTop="50dp"
android:layout_marginEnd="50dp"
android:layout_marginRight="50dp"
android:layout_marginBottom="50dp"
android:text="Button"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0" />
</androidx.constraintlayout.widget.ConstraintLayout>
should say something like "the constraint is 50% to left right top and bottom" which essentially again is exactly the middle. Of course this is again not working. The engine interprets it as absolute value and the button is in another awkward position:
So how to do this ??
What I DON'T WANT TO DO:
Adjust it with some kind of Guideline or Bias.
I want the plain thing.
Just 4 constraints (4 lines inside the xml) and a button that is in the middle of the screen on any device.
Maybe someone can share some insight ?
You should delete these two attributes:
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintVertical_bias="0.0"
As you can see the official reference, default bias is fifty-fifty (50% = 0.5).
For example the following will make the left side with a 30% bias
instead of the default 50%, such that the left side will be shorter,
with the widget leaning more toward the left side (Fig. 5):

Align two views in opposites sides (one at the top and one at the bottom) and be able to push the bottom view when the top view grows?

I basically have an EditText aligned at the top of the view and there's a RecyclerView on the bottom of the view that can also grow (with the newest item on the bottom)
That's easily doable with a constraint layout but my problem is that when the EditText grows it should start pushing down the list. But the list was initially aligned at the bottom of the parent. (and everything should be scrollable)
I hope this image makes things more clear
The trick here is to avoid forming a vertical chain (so that the EditText at the top always stays in place) and also to leverage the app:layout_constrainedHeight attribute on the RecyclerView in order to make it shrink when the EditText grows.
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
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">
<EditText
android:id="#+id/text"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/list"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constrainedHeight="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/text"
app:layout_constraintVertical_bias="1"/>
</androidx.constraintlayout.widget.ConstraintLayout>
The combination of android:layout_height="wrap_content" and app:layout_constrainedHeight="true", along with both top and bottom constraints, means that the RecyclerView will always be only as tall as its items or the available space below the EditText, whichever is smaller.
The app:layout_constraintVertical_bias="1" attribute ensures that, when the list doesn't fill the screen, it sits at the bottom.
I would add to the previous answer and if you want to be able to scroll your layout you can use sth like this:
<androidx.core.widget.NestedScrollView 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:fillViewport="true">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:id="#+id/edit_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent" />
<androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="#id/edit_text"
app:layout_constraintVertical_bias="1.0" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>
This will make everything align as you want to and you are able to scroll down to see your full recyclerView. NestedScrollView will make sure that everything runs smoothly.

Constraintlayout and View Rotation not resizing Views

Im using a Constraintlayout with bias to fill the screen with multiple views. When I rotate the views they dont get resized to to fill the screen. My layout is more complicated but I created an example to show my problem.
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:id="#+id/one"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="#android:color/holo_orange_dark"
app:layout_constraintBottom_toTopOf="#+id/two"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:rotation="90"
android:background="#android:color/holo_green_light"/>
</FrameLayout>
<FrameLayout
android:id="#+id/two"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="#android:color/holo_red_light"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/one">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/holo_green_light" />
</FrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
It doesn't really matter if I rotate the outer or the inner FrameLayout. I don't think I had this problem with LinearLayouts maybe the constraints are getting messed up by the rotation?
EDIT: Hmm looks like the same is happening when using a Linearlayout with weight as parent, so Im probably just doing something wrong here.
The view properties of rotation, translationX and translationY all take effect post-layout. I think that this is true for all view groups. In other words, the views are laid out as if rotation was not specified. Then, after layout, the rotation is applied. This is what you are seeing.
I don't have a reference for this but this problem comes up a lot on Stack Overflow.
Here is an example of this using translationY. Look at the "clarification" section at the top. See how the bottom view does not move even though it is constrained top-to-bottom with the view above? That is because it is positioned to the top view before the top view moves. translationY happens post-layout as does rotation.
This problem can be solved with (probably) a little coding. The exact solution depends on what you are trying to do.

What can I do to shrink the space between my CardViews within a RecyclerView?

So I'm learning app development for Android, and I'm a bit stuck. I'm trying to make a RecyclerView with CardViews, but there is just too much space between CardViews. This is what it looks like.
I'm going for more of the look that the Google app has with the feed.
This is more like what I'm shooting for.
Anyways, I've searched and searched on this website for a solution to my problem and nothing seems to be working for me. I'm hoping that someone can give me something that will actually work.
Here's the xml for my cardview:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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="wrap_content"
android:orientation="vertical"
android:paddingBottom="10dp">
<android.support.v7.widget.CardView
android:id="#+id/cv"
android:layout_width="match_parent"
android:layout_height="120dp"
app:cardCornerRadius="10dp"
app:cardElevation="5dp"
app:cardUseCompatPadding="true"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp">
<TextView
android:id="#+id/note_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="false"
android:layout_below="#+id/event_time"
android:textSize="24sp" />
<TextView
android:id="#+id/note_content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/note_title" />
</RelativeLayout>
</android.support.v7.widget.CardView>
The top and bottom spaces is caused by your padding
android:paddingBottom="10dp", remove this or reduce it
Decrease the PadingBotom of the root constraintLayout
you could put 3 or 4 dp instead of 10dp.
android:paddingBottom="10dp"
Also I do not know if the copy of your code was not good ... the constraintLayout must close at the end:
after this:
</android.support.v7.widget.CardView>
you must have this:
</android.support.constraint.ConstraintLayout>
From the documentation for CardView:
Before Lollipop, CardView adds padding to its content and draws shadows to that area. ... If you want CardView to add inner padding on platforms Lollipop and after as well, you can call setUseCompatPadding(boolean) and pass true.
In your layout, you have this attribute on your CardView tag:
app:cardUseCompatPadding="true"
This does the same thing as the method in the quote above.
As a result, even if you had zero margin on all sides of your cards, users would still see space in between them because of the inner padding behavior. If you want really tight spacing, you'll have to remove this attribute (though of course you'll still get the larger spacing pre-Lollipop).

Position view outside of ConstraintLayout

I want to position views outside of a ConstraintLayout to animate them with a sliding animation. I've tried setting contraints like constraintBottom_toTopOf="parent" but the View stays inside the container.
Note that I want to achieve this with constraints to use built-in animations, not with in-code animations.
Any idea how I could do this ?
I'm using compile 'com.android.support.constraint:constraint-layout:1.1.0-beta1'
with Android Studio 3.0 Beta 7
This is a simple xml file that should place the view outside of the container :
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:background="#color/colorAccent">
<View
android:layout_width="50dp"
android:layout_height="50dp"
android:background="#color/colorPrimary"
app:layout_constraintBottom_toTopOf="parent"/>
</android.support.constraint.ConstraintLayout>
But this is the result
This appears to be an issue with ConstraintLayout 1.1.0-beta1; It works as expected in ConstraintLayout 1.1.0-beta3.
Update to ConstraintLayout 1.1.0-beta3. I will also note that you need to constrain your view horizontally by doing something like the following.
<View
android:layout_width="50dp"
android:layout_height="50dp"
android:background="#color/colorPrimary"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintBottom_toTopOf="parent" />
On a side note, negative margins are not accepted in ConstraintLayout. See this Stack Overflow question regarding negative margins and ConstraintLayout.
In every view you can use negative margin, which will put the view outside of the parent view, and then set the clipping parameters.
android:clipChildren="false"
android:clipToPadding="false"
this will make the view not to clip.
I got another way to solve the problem:
1.Add a anchor(anchor_left) layout_constraintStart_toStartOf="parent".
2.Add YourView layout_constraintEnd_toStartOf="#+id/anchor_left"
That's it!
code:
<android.support.constraint.ConstraintLayout>
<View
android:id="#+id/anchor_left"
app:layout_constraintStart_toStartOf="parent"/>
<YourView
android:id="#+id/ll_left"
app:layout_constraintEnd_toStartOf="#+id/anchor_left"/>
</android.support.constraint.ConstraintLayout>
What I did is:
created a view of 0dp height inside the ConstraintLayout, e.g. "fakeView"
placed the new fakeView anchored at Top of the ConstraintLayout
when I need to hide a View, translate it outside the constraint..
change the constraint of the view you want to hide, in order to have BOTTOM connected to the Top of the FakeView.
I think you can use same technique to move object on the left of the fakeview or on the right.
One trick would be to set negative margin for the side you want, in the ConstraintLayout itself. This requires that other views that have constraint to that side be offset:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
...
android:layout_marginBottom="-48dp">
<ImageButton
android:id="#+id/leftButton"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_marginEnd="24dp"
android:layout_marginBottom="72dp"
android:background="#drawable/shape_next_button"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
<ImageButton
android:id="#+id/rightButton"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_marginStart="24dp"
android:background="#drawable/shape_previous_button"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

Categories

Resources