First things first, I've checked that answer: How to add shadow to the FAB provided with the android support design library?
But even adding the app:borderWidth="0dp" or elevation="6dp" it didn't work. I have checked this answer: https://stackoverflow.com/a/30752754/1121139 it says as bigger my elevation, bigger is the shadow, and here goes the funny thing, at the preview screen it shows the shadow, but when runs at smartphone I got no shadow.
Here goes an screenshot from smartphone:
and here goes and screenshot from preview screen at android studio:
My layout code:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="amaz1ngc0de.com.br.materialdesign.MainActivity">
<include android:id="#+id/app_bar" layout="#layout/toolbar_app_bar"/>
<android.support.v7.widget.RecyclerView
android:id="#+id/rv_test_fab"
android:layout_below="#id/app_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</android.support.v7.widget.RecyclerView>
<android.support.design.widget.FloatingActionButton
android:layout_margin="16dp"
android:layout_alignParentRight="true"
android:layout_alignParentBottom="true"
android:src="#drawable/ic_add_white_24dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:elevation="140dp"
app:borderWidth="0dp"
app:pressedTranslationZ="12dp"
android:clickable="true"/>
Try wrapping your layout inside a CoordinatorLayout and put the FAB at the same level, instead of a RelativeLayout, example:
<!-- main_layout.xml -->
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
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"
android:animateLayoutChanges="true"
android:fitsSystemWindows="true"
tools:context=".activity.MainActivity">
<include layout="#layout/toolbar_app_bar" />
<android.support.v7.widget.RecyclerView
android:id="#+id/rv_test_fab"
android:layout_below="#id/app_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<android.support.design.widget.FloatingActionButton
... />
</android.support.design.widget.CoordinatorLayout>
Edit:
This widget is from the design library, you should have it added in your app's build.gradle file:
compile 'com.android.support:design:24.0.0'
OK so I have tried around a bit and it seems shadowing with elevation doesn't work as you imagined. This code gives quite a shadow:
<android.support.design.widget.FloatingActionButton
android:id="#+id/name_add"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="15dp"
android:src="#drawable/ic_add"
app:elevation="20dp"/>
But if I set elevation to 200, the shadow disappears. So there is only a range at which the shadow is working.
Maybe you can understand it as an object, casting a shadow onto an underlaying object. The higher the elevation, the greater is the distance between the two objects and the less shadow is cast...
Related
I have currently a problem with a recycler view and a floating action button in my android app. The button always jumps to the right top of the page when I start the app.
The RecyclerView and the Button are inside a fragment. Currently I am using a ConstraintLayout to say the Button should always appear at the right end of the screen. However, I also tried it with a RelativeLayout and CoordinatorLayout with anchor and gravity attributes. In Android Studio, the layout shows it correct, with the button at the bottom right side of the screen. As soon as I start the app on my phone, it appears on the top right side of the screen...
Layout preview:
When I start the app on my phone:
Here's my Code I am using right now for the fragment:
<?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"
android:id="#+id/fragment_bucketlist"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
android:background="#color/colorPrimary">
<android.support.v7.widget.RecyclerView
android:id="#+id/rv_bucketList"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<android.support.design.widget.FloatingActionButton
android:id="#+id/fab_addToBucketList"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="16dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintRight_toRightOf="parent"/>
</android.support.constraint.ConstraintLayout>
Thanks in advance for helping!
Try using the recyclerview and fab button within a CoordinatorLayout.
The attribute app:layout_anchorGravity: will specify how an object should be positioned relative to an anchor, on both the X and Y axes, within its parent’s bounds.
<android.support.design.widget.CoordinatorLayout
android:id="#+id/fragment_bucketlist"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/colorPrimary">
<android.support.v7.widget.RecyclerView
android:id="#+id/rv_bucketList"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<android.support.design.widget.FloatingActionButton
android:id="#+id/floating_action_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:scaleType="center"
android:src="#drawable/android_floating_action_button_icon"
app:layout_anchor="#id/rv_bucketList"
app:layout_anchorGravity="bottom|right|end"
app:borderWidth="1dp"
app:elevation="10dp" />
</android.support.design.widget.CoordinatorLayout>
I solved the problem using a RelativeLayout. There was a problem that the Floating Action Button always showed up on the bottom edge and "stucked" at the bottom navigation bar (HUAWEI devices). The attribute app:useCompatPadding="true" solved the issue.
Here is the updated code:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/fragment_bucketlist"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
android:background="#color/colorPrimary">
<android.support.v7.widget.RecyclerView
android:id="#+id/rv_bucketList"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<android.support.design.widget.FloatingActionButton
android:id="#+id/fab_addToBucketList"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/ic_edit"
app:useCompatPadding="true"
android:layout_alignParentBottom="true"
android:layout_alignParentEnd="true" />
</RelativeLayout>
I need to make FloatingActionButton always stick to the bottom of my fragment where I display WebView. The problem is that the button in my current XML is cut in half and I can't manage to fix it. Here is my layout.
<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"
android:background="#color/colorBackgroundWhite"
tools:context=".fragments.CpuComparisionFragment">
<android.support.design.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<WebView
android:id="#+id/web_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<android.support.design.widget.FloatingActionButton
android:id="#+id/button_compare"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|bottom"
android:layout_marginBottom="#dimen/fb_margin_16dp"
android:layout_marginEnd="#dimen/fb_margin_16dp"
android:alpha="0.7"
android:src="#drawable/ic_compare" />
</android.support.design.widget.CoordinatorLayout>
</FrameLayout>
What am i doing wrong? Any ideas how to fix this? Here is screenshot how my app looks now.
It seems the android version installed on the device you're testing your app on doesn't support some of your xml attributes. Anyways, replace the FAB code with the below snippet. I hope it work for you.
<android.support.design.widget.FloatingActionButton
android:id="#+id/button_compare"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|right"
android:layout_marginBottom="#dimen/fb_margin_16dp"
android:layout_marginEnd="#dimen/fb_margin_16dp"
android:alpha="0.7"
app:layout_anchorGravity="bottom|right|end"
android:src="#drawable/ic_compare" />
Try to add android:fitsSystemWindows="true" to your FrameLayout .
As of now, with the official bottom sheet component from the Android design library implemented the top edge doesn't show a shadow. But for what I've seen in various mockups and in the Material Design specs, the bottom sheet include a discrete shadow of some sort.
I think the shadow would help distant the bottom sheet from the main layout, especially if there's a peek value set and/or the bottom sheet is always visible. Otherwise it just will blend together with the main layout and its items.
I've tried both ViewCompat.setElevation(bottomSheet, 5); and setting android:elevation="5dp" to the view in the XML, without success.
I know that a shadow shape doesn't have the same appearance as an elevation - but at least give it a try. The trick is to use app:layout_anchor to clip the shadow to the bottom sheet.
activity_main.xml
<android.support.design.widget.CoordinatorLayout 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">
<MapView
android:id="#+id/map"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<View
android:id="#+id/shadow"
android:layout_width="match_parent"
android:layout_height="16dp"
android:background="#drawable/shape_gradient_top_shadow"
app:layout_anchor="#id/bottom_sheet" />
<FrameLayout
android:id="#+id/bottom_sheet"
android:layout_width="match_parent"
android:layout_height="200dp"
android:clipToPadding="false"
app:layout_behavior="android.support.design.widget.BottomSheetBehavior" />
</android.support.design.widget.CoordinatorLayout>
shape_gradient_top_shadow.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<gradient
android:angle="90"
android:endColor="#android:color/transparent"
android:startColor="#64000000"/>
</shape>
Looks like this:
EDIT
Get an even better result with a custom ShadowView:
Post from Roman Nurik on this topic: https://plus.google.com/+RomanNurik/posts/2QvHVFWrHZf
Gist of the ShadowView based on Roman Nurik's solution: https://gist.github.com/MariusBoepple/bf869e02541cd4750550e88fa07b5ddd
Then you can do the following:
<ShadowView
android:id="#+id/shadow"
android:layout_width="match_parent"
android:layout_height="16dp"
android:gravity="bottom"
app:layout_anchor="#id/bottom_sheet" />
For API Level 21 and higher, set the following in the parent view. You can also try in the rootview of the bottomsheet (I have not tried it in the root view)
android:background="#android:color/white"
android:elevation="16dp"
If no background then can use
android:outlineProvider="bounds"
For example, I have my sheet inside a nested scroll view
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipToPadding="false"
app:layout_behavior="android.support.design.widget.BottomSheetBehavior"
android:elevation="16dp"
android:outlineProvider="bounds"
>
<include layout="#layout/bottomsheet_1" />
</android.support.v4.widget.NestedScrollView>
The trick is to use a CardView as parent and set the elevation in the CardView
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:background="#fff"
android:clickable="true"
android:focusable="true"
app:behavior_hideable="true"
app:layout_behavior="android.support.design.widget.BottomSheetBehavior"
android:layout_height="140dp"
app:cardElevation="8sp"
card_view:cardCornerRadius="0dp">
<!--The content of your Bottom sheet-->
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
.
.
</android.support.constraint.ConstraintLayout>
</android.support.v7.widget.CardView>
EDIT
This technique is not the best solution if you are supporting Kitkat and below. It's due to the extra margin added by the Cardview.
I think this will help you
first create bottom sheet like bellow then include in your main activity
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/bottom_sheet"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
app:behavior_hideable="true"
app:behavior_peekHeight="56dp"
android:layout_marginTop="0.5dp" // this margin depend on shadow area
android:background="set you color"
android:elevation="20dp" // chose your custom elevation
app:layout_behavior="#string/bottom_sheet_behavior">
<LinearLayout
android:layout_marginTop="1dp" // this margin depend on max elevation
android:layout_width="match_parent"
android:layout_height="200dp">
</LinearLayout>
</LinearLayout>
I've a weird behaviour problem:
on any device or emulator with a version lower than lollipop the floating action button and other components which float over the toolbar(e.g. the popup of a Spinner) are positioned wrong. They seem to move based on the value of the app:elevation, but even app:elevation="0" doesn't position them equal to lollipop devices.
EDIT:
I just wanted to explain the behavior of the FAB better. When i add an elevation tag on a pre lollipop device to the fab, its x and y coordinates increase. On a lollipop device the elevation tag has no influence on the position.
EDIT 2:
After some experiments I found out that the problem is that the layout size increases on pre lollipop devices to draw the shadow. This also increases the click able area. This behaviour makes it impossible to create 2 different layouts for lollipop and pre lollipop devices, because the behaviour and size of the FAB are just wrong. On lollipop devices the layout is (as wanted) 40dp * 40dp and the FAB draws its shadow on the layout below it.
Layout:
<android.support.v4.widget.DrawerLayout
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:fitsSystemWindows="true"
android:id="#+id/id_drawer_layout">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.Toolbar
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar"
android:layout_height="128dp"
android:layout_width="match_parent"
android:background="#color/primaryColor"
android:id="#+id/id_toolbar"
android:elevation="20dp"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light">
<Spinner
android:layout_marginStart="12dp"
android:layout_marginTop="62dp"
android:id="#+id/id_toolbar_spinner"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</android.support.v7.widget.Toolbar>
<android.support.v4.widget.SwipeRefreshLayout
android:id="#+id/id_swipe_refresh_layout"
android:layout_below="#id/id_toolbar"
android:layout_height="match_parent"
android:layout_width="match_parent">
<android.support.v7.widget.RecyclerView
android:layout_below="#id/id_toolbar"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:id="#+id/id_filemanager_recycler_view"
android:background="#android:color/white"/>
</android.support.v4.widget.SwipeRefreshLayout>
<android.support.design.widget.FloatingActionButton
android:layout_below="#id/id_toolbar"
android:layout_marginTop="-20dp"
android:layout_marginStart="16dp"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:id="#+id/id_floating_action_button"
android:src="#drawable/ic_add_white_24dp"
app:elevation="30dp"
app:borderWidth="0dp"
app:fabSize="mini"/>
</RelativeLayout>
<android.support.design.widget.NavigationView
android:layout_width="288dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="#android:color/white"
android:id="#+id/id_main_navigation_view"
app:menu="#menu/menu_drawer_main"/>
Pre Lollipop
Lollipop
I had the same problem. The solution is to put your FloatingActionButton inside android.support.design.widget.CoordinatorLayout.
This is what i'm using
<android.support.design.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.FloatingActionButton
android:id="#+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right|bottom"
android:layout_margin="16dp"
android:src="#drawable/ic_add_white_24dp"
app:elevation="6dp"
app:fabSize="normal"
app:pressedTranslationZ="12dp" />
</android.support.design.widget.CoordinatorLayout>
You can modify this code to meet your needs.
Add these lines to your FloatingActionButton tag, also change the appBar in my code snippet to the id of the layout you want to attach FloatingActionButton to.
app:layout_anchor="#+id/appBar"
app:layout_anchorGravity="bottom|left|end"
I have a CoordinatroLayoutwith FloatingActionButton. Here is my code:
<android.support.design.widget.CoordinatorLayout
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:layout_below="#+id/toolbar_layout"
android:layout_above="#+id/actionbar">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<android.support.v7.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="120dp"
android:minHeight="?android:attr/actionBarSize"
android:background="#color/toolbar_color" />
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
</ScrollView>
</LinearLayout>
<android.support.design.widget.FloatingActionButton
android:id="#+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clickable="true"
app:fabSize="mini"
android:src="#mipmap/ic_action_edit"
app:layout_anchor="#id/toolbar"
app:layout_anchorGravity="bottom|right|end"
app:backgroundTint="#color/toolbar_color" />
</android.support.design.widget.CoordinatorLayout>
But it appears differently in lollipop and pre-lollipop devices.
Lollipop:
Pre-Lollipop:
Actually I haven't add any margin. But FAB has margin in pre-lollipop devices.
I have also seen this problem in cheessesquare sample. It shows different margins too. What is the problem?
I dont think you want to place them without margins. If I understood it right, you've done this to see whats going on in different versions of android.
You can use app:useCompatPadding="true" and remove custom margins to maintain same margins across different versions of android
Proof of concept
According to this link, it seems to be a bug in android design library. It says that:
in API <20, the button renders its own shadow, which adds to the
overall logical width of the view, whereas in API >=20 it uses the new
Elevation parameters which don't contribute to the view width.
So I have to provide two resource files for margin:
res/values:
<dimen name= "fab_margin_right">0dp</dimen>
And in res/values-v21:
<dimen name = "fab_margin_right">8dp</dimen>
Since 22.2.1 version of support and design library, previous answer is no longer true. There is no extra padding if FAB is inside CoordinatorLayout.
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
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.support.design.widget.FloatingActionButton
android:id="#+id/button_show_qr"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|bottom"
android:src="#mipmap/ic_action_edit"
app:backgroundTint="#color/primary"
app:borderWidth="0dp"
app:elevation="4dp"
app:fabSize="normal"
app:rippleColor="#color/primary_dark"/>
</android.support.design.widget.CoordinatorLayout>
This code will produce following FAB on every Android version.