I am trying to make use of the elevation property in the latest Android Lollipop preview release. I set the targetSdk to 21 and the theme to Material. Next i added a background shape to a TextView and set the elevation to 8dp but the TextView is not showing any signs of a shadow. That is on a Nexus7 running the Lollipop preview. Is there anything else i have to consider?
Here is the layout:
<?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">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/rect"
android:text="hallo world"
android:padding="8dp"
android:elevation="8dp" />
</LinearLayout>
This is the background drawable:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#7d0073ff" />
<corners android:radius="16dp" />
</shape>
Here is the TextView:
For some reason if you set a solid color with a transparency, the elevation shadow does not show up.
In your example, I changed #7d0073ff to #0073ff and I got a shadow.
This is probably a bug, as in their documentation it gives a similar example using a translucent background color.
After going through the docs again, I finally found the solution.
Just add card_view:cardUseCompatPadding="true" to your CardView and shadows will appear on Lollipop devices.
What happens is, the content area in a CardView take different sizes on pre-lollipop and lollipop devices. So in lollipop devices the shadow is actually covered by the card so its not visible. By adding this attribute the content area remains the same across all devices and the shadow becomes visible.
My xml code is like :
<android.support.v7.widget.CardView
android:id="#+id/media_card_view"
android:layout_width="match_parent"
android:layout_height="130dp"
card_view:cardBackgroundColor="#android:color/white"
card_view:cardElevation="2sp"
card_view:cardUseCompatPadding="true"
>
...
</android.support.v7.widget.CardView>
ADDING android:elevation shadow to an ImageView:
android:clipToPadding="false"
+
android:outlineProvider="bounds"
+
android:elevation="2dp"
I was also having this problem, and as it turns out, you need to turn hardware acceleration on in the android manifest
<application
...
android:hardwareAccelerated="true">
be aware, if you have the following line in the manifest then shadows wont show:
android:hardwareAccelerated="false"
TL;DR
Check your card: (or whatever word you use) namespace declaration and make sure it matches this: xmlns:card="http://schemas.android.com/apk/res-auto"
I know there are a few answers here already, but I wanted to add mine as it wasn't included in these current suggestions. In order to get the shadows working on both KitKat and Marshmallow, (only emulators I tried, I'm sure it works in between) I added the following xml attributes to my card:
card:cardElevation="25dp"
card:cardUseCompatPadding="true"
After banging my head against my desk for why that wasn't working, trying to set the background color of the card to something completely opaque, enabling hardware acceleration in the manifest, and even praying, I checked the namespace declarations in my file. To my horror, I saw that the card xml namespace had been assigned to the following:
xmlns:card="http://schemas.android.com/tools"
After fixing that namespace declaration, I ran my dummy app again and let out a sigh of relief as shadows were finally being shown as expected.
Here is proof in case you're a doubter like me. And please Google, Android, whoever: Make shadows great again. They shouldn't be this difficult.
Here is the entire file that created the layout pictured below:
<?xml version="1.0" encoding="utf-8"?>
<!--MAKE SURE YOU HAVE THE RIGHT XML NAMESPACE ASSIGNED-->
<!--TO WHATEVER WORD YOU PUT IN FRONT OF THE CARD-->
<!--XML ATTRIBUTES. IN THIS CASE, MINE IS card-->
<android.support.percent.PercentRelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:card="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="#607D8B"
android:fitsSystemWindows="true"
tools:context="com.mlustig.playground.MainActivity">
<android.support.v7.widget.CardView
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_centerInParent="true"
app:layout_aspectRatio="66%"
app:layout_heightPercent="75%"
card:cardElevation="25dp"
card:cardUseCompatPadding="true" />
</android.support.percent.PercentRelativeLayout>
Yes, I know. It's annoying that you can't simply copy and paste this layout and run it because it has PercentRelativeLayout in it, but I left it there on purpose. You should definitely check it out. Super powerful, very useful. Nice nice nice. Hope this helped.
As noted earlier, this is an open bug in Android : if the background drawable uses a solid color with transparency, then the shadow won't be shown.
To work around the issue, display the background in its own separate view and set the alpha on that view. Wrap the background view and the TextView in a RelativeLayout to place the background directly under the TextView and use android:layout_alignLeft, android:layout_alignBottom etc to make it the same size. They need to be at the same elevation, and the background must appear before the TextView in the xml so it is drawn under it.
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="40dp"
android:paddingRight="40dp"
android:paddingTop="20dp"
android:paddingBottom="20dp"
android:clipToPadding="false"
android:background="#ffffff">
<View
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="#+id/text_view"
android:layout_alignRight="#id/text_view"
android:layout_alignBottom="#id/text_view"
android:layout_alignTop="#id/text_view"
android:background="#drawable/rect"
android:alpha="0.5"
android:elevation="8dp"/>
<TextView
android:id="#id/text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="hallo world"
android:textColor="#ffffff"
android:padding="8dp"
android:elevation="8dp" />
</RelativeLayout>
The drawable is the same as yours but without transparency:
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#0073ff" />
<corners android:radius="16dp" />
</shape>
Result:
A few notable points:
You must ensure that the enclosing RelativeLayout is large enough to display the shadow. If you just set its dimensions to wrap_content without padding, the shadow will be clipped to the layout's bounds. As explained in this question, you can use padding and set android:cipToPadding="false" to make it large enough for the shadow. You might not need as much padding in this case, I haven't experimented with that.
In this case we need to use a separate view for the background because if we had set the alpha directly on the TextView then the text would have been affected as well. Depending on your use case you might not need a separate view and enclosing layout and could just just have one view, with alpha set on the view and no transparency in the drawable.
Try using : app:cardElevation="4dp"
Try adding margin to the CardView.
Related
I'm struggling with CardView corner radius and background color with AndroidX libraries.
I've defined my layout as below:
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView
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"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:layout_width="#dimen/retail_card_width"
card_view:cardCornerRadius="#dimen/card_radius"
card_view:cardBackgroundColor="#color/baseYellow"
android:layout_height="#dimen/retail_card_height">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView android:layout_width="match_parent" android:layout_height="match_parent"
tools:src="#drawable/ic_fruit_1"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:scaleType="fitEnd"
app:layout_constraintTop_toTopOf="parent"/>
<ImageView
android:id="#+id/ivRetailBrand"
android:layout_width="#dimen/brand_icon_size"
android:layout_height="#dimen/brand_icon_size"
tools:src="#drawable/esselunga"
android:layout_marginTop="#dimen/retail_brand_margin"
android:background="#drawable/round_outline"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintStart_toStartOf="parent"
android:layout_marginStart="#dimen/retail_brand_margin"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
Unfortunately, neither cardCornerRadius nor cardBackgroundColor seem working on my layout. I can't understand if my issue depends on AndroidX libraries or not.
Here there's my layout preview:
I removed this lines in my Manifest file and after that my cardviews are worked prefectly fine
android:hardwareAccelerated="false"
Try modifying the CardView as:
<androidx.cardview.widget.CardView
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="#dimen/retail_card_width"
app:cardCornerRadius="#dimen/card_radius"
app:cardBackgroundColor="#color/baseYellow"
android:layout_height="#dimen/retail_card_height">
It turned out that the problem was I was mixing cardview androidx library with support recyclerview library. Once I rebuilt the project with:
implementation 'androidx.recyclerview:recyclerview:1.0.0'
implementation 'androidx.cardview:cardview:1.0.0'
everything turned out fine.
I might be late for this but let me save someone's time in the future. I had this problem on my Android Studio preview and came to realise that the problem is that the content inside the CardView is not clipped to the bounds of the CardView, so the corners you see are corners of the ImageView, which is actually clipped when you run the app on emulator/device.
I hope this helps!
I had a similar problem. I solved it by wrapping the CardView in FrameLayout.
Addition to an answer:
Or you can try using "app" namespace instead of "card_view":
app:cardBackgroundColor="#color/background_color"
app:cardCornerRadius="#dimen/corner_radius"
I don't think it's related to the CardView setup.
Check Your ImageView they can be the reason for corner's not being rounded.
Comment Out Image View Code(whole ConstraintLayout) and check the UI.As i had the Same Issue in Past.
try to clean and rebuild the project. This worked for me..
You can create a new drawable file round_corner_colored.xml and paste the following code in that file :
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid
android:color="#color/light_sky_blue"/>
<corners
android:radius="#dimen/_12sdp"/>
</shape>
Now set this drawable the background of cardview as :
android:background="#drawable/round_corner_colored"
Hope it will help !!
There are brands that force Dark mode when app installed for the first time this will affect the coloration of views and applying color in CardView will get ignored. You may apply this to your main theme to prevent such event.
<item name="android:forceDarkAllowed" tools:targetApi="q">false</item>
For me, It wasn't showing properly in Preview. But it was showing properly on the device. There is some rendering issue. I keep encountering such problems in android studio.
Faced issue in Android Studio 4.2.1 (Mac)
For me this worked
<androidx.cardview.widget.CardView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:cardBackgroundColor="#color/white"
app:contentPadding="#dimen/_10sdp"
app:cardCornerRadius="20dp"
app:cardUseCompatPadding="true"
android:layout_marginStart="#dimen/_20sdp"
android:layout_marginTop="#dimen/_10sdp">
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="#string/low"
android:textColor="#color/text_color_blue"
android:textSize="#dimen/_11ssp"
android:textStyle="normal" />
</androidx.cardview.widget.CardView>
Ok, So I ran into the same issue, and none of these suggestions resolved my issue. I was setting the background color of the card via cardview.setBackgroundColor(color):
, instead of cardview.setCardBackgroundColor()
. The cardview contains an embedded object, of card, the card is where the corner radius is appended to. So setting the color outside of the CardView.Card will not render the corner-radius as intended. Hope this helps.
I upgraded compileSdkVersion from 28 to 29 in app level gradle and the problem solved.
compileSdkVersion 29
My problem
My card views defined through XML are not showing their proper rounded corners (they are being covered by its subviews) in Android studio preview.
Although it shows up fine after rendering in the simulator, I fear that this "glitch" may be a symptom of me doing something wrong or forgetting some critical attribute. And even if it wasn't a symptom of a deeper problem, could anyone offer any insight on how to fix this aesthetic error?
Could anyone weigh in on this?
<android.support.v7.widget.CardView
android:layout_marginTop="16dp"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="16dp"
app:cardCornerRadius="10dp"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.AppCompatImageView
android:src="#color/red"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</android.support.v7.widget.CardView>
Android studio screenshot
Android emulator screenshot
The problem in the generated preview is that the content inside the CardView is not clipped to the bounds of the CardView, so the corner's you see are corners of the ImageView, which is actually clipped when you run on emulator/device.
If you really want to generate the real-like preview, you can try this workaround.
Add a stub drawable with the corner radius you want.
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="20dp" />
<solid android:color="#android:color/holo_green_light" />
</shape>
Then set it as the background of the ImageView under the tools: namespace.
<ImageView android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="#android:color/holo_blue_bright"
tools:src="#drawable/test" />
Android Studio supports a variety of XML attributes in the tools: namespace that enable design-time features (such as src of the ImageView to display when in preview mode).
here rounded corners show normally with your code. My test phone is Android 7.1. so I think you should clear the cache of your phone and install this app again. or maybe you should increase the value of
app:cardCornerRadius
then test it again.
I use latest Android Studio and SDK. In preview & real device i see this:
My code:
<?xml version="1.0" encoding="utf-8"?>
<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="match_parent"
tools:context="com.myappname.view.AboutActivity">
<ListView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/listViewAbout" />
</RelativeLayout>
How i make subtitle text color is gray? Like this:
I'm going out on a limb and assume that you're using the row layout simple_list_item_2.xml (based on the screenshot) which gives you two rows. The problem, if you may call it that, is that depending on the SDK version, the styling for this layout has changed.
On SDK 23, it looks like this:
However, on say SDK 19, it looks like this:
Why?
To understand this we first need to take a look at the xml that generates the rows from simple_list_item_2.xml, you'll see it's a pretty simple layout that uses the now deprecated view TwoLineListItem but that's just a plus on why to use your custom layout.
<TwoLineListItem xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?attr/listPreferredItemHeight"
android:mode="twoLine"
android:paddingStart="?attr/listPreferredItemPaddingStart"
android:paddingEnd="?attr/listPreferredItemPaddingEnd">
<TextView android:id="#id/text1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:textAppearance="?attr/textAppearanceListItem" />
<TextView android:id="#id/text2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#id/text1"
android:layout_alignStart="#id/text1"
android:textAppearance="?attr/textAppearanceListItemSecondary" />
</TwoLineListItem>
The reason is because of the way the style textAppearanceListItemSecondary is resolved in each SDK version. The style is what gives the text the size, the color, etc. The evolution of the interface in Android has given birth to a huge ecosystem of themes and relying on the default styling will result in inconsistencies like the one you stumbled upon.
What to do about it?
You should use your own layout for this to allow for uniform styling across versions. To do so, please refer to any of the multiple questions covering this matter. But in short it just means creating a layout file, call it for example custom_row.xml and having the layout look exactly as you please. This also gives you total control over placement of the items, extra Views that you may need, and overhead in terms of coding is minimal compared to the SimpleAdapter or ArrayAdapter that perhaps you were using.
Note
You should consider moving your code towards RecyclerView instead of ListView if you haven't already.
You can set Textview property
android:textColor="#color/grey"
in you Adapter layout to change colour of your sub item
Hope this will help
I think the title is pretty explicit about my problem... So here is my layout :
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<Button
android:id="#+id/button_action"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Login" />
<ProgressBar
android:id="#+id/progress_bar"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_centerInParent="true"/>
</RelativeLayout>
On android SDKs < 21, no problem, the ProgressBar is correctly displayed over the Button and centered in the Button. But on Android 5.0, the ProgressBar is displayed behind the Button.
So you can see it's correctly positionned it when you activate the option "Show layout bounds" in Developer Options settings, but you can't see anything on the screen without that option.
Would anybody know how to fix this? I guess it's a matter of elevation recently introduced, but I really don't know how to take care of it.
For the record, I'm using the recently released Theme.AppCompat style from the support.v7.
EDIT:
I also tried to apply setElevation(0) and setTranslationY(0) to the Button programmatically but it didn't change anything. So I wonder if it has to deal with the elevation.
You can add the android:translationZ attribute to the ProgressBar:
<ProgressBar
android:id="#+id/progress_bar"
android:layout_width="50dp"
android:layout_height="50dp"
android:translationZ="2dp"
android:layout_centerInParent="true"/>
Same issue here, my simple "hack" was too wrap the Button into another FrameLayout.
This way I don't care about the api version and other elevation issue ;)
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center" >
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<Button
android:id="#+id/button_action"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Login" />
</FrameLayout>
<ProgressBar
android:id="#+id/progress_bar"
android:layout_width="50dp"
android:layout_height="50dp" />
</FrameLayout>
Same question being asked here, with a better explanation of the issue:
https://stackoverflow.com/a/27216368/235910
To quote #CommonsWare:
The problem appears Android 5.0's elevation property. Apparently,
the RelativeLayout Z-axis ordering is tied into elevation. If both
widgets have the same elevation, the RelativeLayout will determine
the Z-axis order -- you can see that if you were to switch your layout
to be both Button widgets, for example. However, if one widget
(Button) has an elevation, and another widget (ImageView) does
not, the elevation will take precedence.
You can remove the Button elevation via
android:stateListAnimator="#null" or by defining your own custom
animator. Or, you can add some elevation to your ImageView to
get it to be higher on the Z axis than is the Button.
It is better to set android:translationZ more than 2dp. Your view/widget will disappear when you press the button. I explained the reason here.
<!-- Elevation when button is pressed -->
<dimen name="button_elevation_material">1dp</dimen>
<!-- Z translation to apply when button is pressed -->
<dimen name="button_pressed_z_material">2dp</dimen>
Button have these two values and defined in the framework.
If you add 'androidx.core:core' to your build.gradle, you can use this code for API < 21:
ViewCompat.setTranslationZ(viewToElevate, 5);
By default, if you want to show a view on top of a Button, it should have an elevation of at least 2dp.
This is caused by the fact that the elevation of a button is governed by their stateListAnimator. So long as it has one, setting the elevation to the button itself doesn't do anything. The stateListAnimator of Widget.MaterialComponents.Button has a default elevation of #dimen/mtrl_btn_elevation (2dp), so that's the elevation you have to take into account.
Doing android:stateListAnimator="#null" will also work, but that will get rid of any shadow effects at the button.
In my application, I want to set bubbles to a text view, in the text view I add the setBackgroundResource() as you can see in the code.
With this code i'm getting an image like this:
I want a bubble shape image like this:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<solid android:color="#EDF5E4" />
<corners android:bottomLeftRadius="#dimen/corner_radius"
android:bottomRightRadius="#dimen/corner_radius"
android:topLeftRadius="#dimen/corner_radius"
id:topRightRadius="#dimen/corner_radius" />
Please tell me how to make this in my setBackgroundResource() XML.
What you need to use is essentially a 9-patch image (As already pointed out by Ken Wolf in this comment).
To get you started, I am including a set of 9-patch images from one of my apps along with a brief piece of code on how to use it when creating a layout XMl. ;-)
The 9-patch Image Set:
(These are named: bubble_white_normal_mdpi.9, bubble_white_normal_hdpi.9 and bubble_white_normal_xhdpi.9 respectively. Remove the _mdpi, _hdpi and _xhdpi from the file names after placing them in their respective drawable folders.
The XML:
<LinearLayout
android:id="#+id/linlaUserOther"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:baselineAligned="false"
android:orientation="horizontal"
android:padding="2dp" >
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:gravity="top|center" >
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="vertical" >
<ImageView
android:id="#+id/imgvwProfileOther"
android:layout_width="42dp"
android:layout_height="42dp"
android:adjustViewBounds="true"
android:contentDescription="#string/content_desc_user_profile"
android:scaleType="centerCrop"
android:src="#drawable/ic_contact_picture" >
</ImageView>
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="0dip"
android:layout_height="fill_parent"
android:layout_weight="1"
android:background="#drawable/bubble_white_normal"
android:gravity="top|center"
android:orientation="vertical" >
.... // OTHER STUFF HERE THAT IS NOT NECESSARY IN THIS CODE SNIPPET ON SO
</LinearLayout>
</LinearLayout>
NOTE 1:
Although, I am including a working set of Images (almost spoon feeding, if you will), I would strongly urge you to create your own set of images that fit in your scheme of things. Plus, this will also equip you to build your own resources in the future. The only reason I am going the extra mile is because I personally lost 3 days getting the speech bubble looking and working right. :-(
NOTE 2:
I am setting the image as a background to a LinearLayout. You, however, will need to set it to the TextView you need looking like a Speech Bubble.
Additional Sites (Tutorials):
http://blog.booleanbites.com/2012/12/android-listview-with-speech-bubble.html
https://github.com/AdilSoomro/Android-Speech-Bubble
http://developer.android.com/reference/android/graphics/NinePatch.html
http://developer.android.com/tools/help/draw9patch.html
I think you are going to have a hard time trying to do it using just shape drawables.
I would use a 9-patch png.
http://developer.android.com/reference/android/graphics/NinePatch.html
Basically you either find/buy an image or create one in your favourite drawing program. Then you define the stretchable regions using the draw9patch tool which allow it to scale properly in your View.
Here is a tutorial, it's even specific to speech bubbles!
http://adilsoomro.blogspot.co.uk/2012/11/android-how-to-use-9-patch-png.html
It takes a bit of time but it is a crucial technique in making more designed visual interfaces.