I have an app with the one Activity, many Fragments model, where several Fragments have a RecyclerView to show cards with content. I also have implemented the BottomAppBar from Material Design 2.0, and everything is fine except when the AppBar blocks the last CardView in the RecyclerView.
In terms of layout, I have a RecyclerView inside ConstraintLayout inside a Fragment, which sits in a FrameLayout in the main activity.
The documentation shows that for the BottomAppBar to be hidden on Scroll, we need to implement RecyclerView inside a NestedScrollView. There is one question here on SO where the answer has stated the same as well, but there seems to be no actual documentation or examples to demonstrate how this is to be done, except for this article on Medium, which uses the NestedScrollView in an Activity directly, holding a CoordinatorLayout which holds a ConstraintLayout.
Note: I think it also works on magic, because duplicating the layout in my fragment doesn't have any effect at all in my app.
How do I use NestedScrollView here?
PS : I need to have the TextView, as I set the RecyclerView to VISIBILITY.GONE and set the TextView to VISIBLE when I have no data to display.
Fragment Layout
<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:id="#+id/constraintLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="in.domain.APPNAME.Fragments.FragmentList">
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerViewIncident"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:paddingBottom="30dp"
android:visibility="visible"
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" />
<TextView
android:id="#+id/emptyView"
android:layout_width="wrap_content"
android:layout_height="17dp"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:text="No Incidents to display"
android:visibility="visible"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.503"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
Activity Layout
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/uberLayout"
tools:context=".APPNAME">
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:id="#+id/containerFrameLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
</FrameLayout>
</android.support.constraint.ConstraintLayout>
<android.support.design.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.bottomappbar.BottomAppBar
android:id="#+id/bottom_app_bar"
style="#style/Widget.MaterialComponents.BottomAppBar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
app:backgroundTint="#color/colorPrimary"
app:fabAlignmentMode="center"
app:navigationIcon="#drawable/baseline_menu_white_24dp"
app:hideOnScroll="true"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light"
app:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar">
</android.support.design.bottomappbar.BottomAppBar>
<android.support.design.widget.FloatingActionButton
android:id="#+id/floatingActionButton"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:clickable="true"
android:src="#drawable/baseline_add_white_24dp"
app:backgroundTint="#color/brightred"
app:fabSize="normal"
app:layout_anchor="#+id/bottom_app_bar"
tools:layout_editor_absoluteX="160dp"
tools:layout_editor_absoluteY="465dp" />
</android.support.design.widget.CoordinatorLayout>
</android.support.design.widget.CoordinatorLayout>
you shouldn't put the BottomAppBar and the FloatingActionButton in a separate CoordinatorLayout. Ditch the CoordinatorLayout they're in, the ConstraintLayout around your FrameLayout and that may already solve the problem.
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/uberLayout"
tools:context=".APPNAME">
<FrameLayout
android:id="#+id/containerFrameLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
</FrameLayout>
<android.support.design.bottomappbar.BottomAppBar
android:id="#+id/bottom_app_bar"
style="#style/Widget.MaterialComponents.BottomAppBar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
app:backgroundTint="#color/colorPrimary"
app:fabAlignmentMode="center"
app:navigationIcon="#drawable/baseline_menu_white_24dp"
app:hideOnScroll="true"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light"
app:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar"/>
<android.support.design.widget.FloatingActionButton
android:id="#+id/floatingActionButton"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:src="#drawable/baseline_add_white_24dp"
app:backgroundTint="#color/brightred"
app:fabSize="normal"
app:layout_anchor="#+id/bottom_app_bar" />
</android.support.design.widget.CoordinatorLayout>
I'm using a similar layout, the only difference being a <fragment> instead of a <FrameLayout>, and the BottomAppBar hides on scroll just fine. We don't need to use a NestedScrollView, if our scrolling content is a RecyclerView anyway, because RecyclerView implements NestedScrollingChild.
This interface should be implemented by View subclasses that wish to support dispatching nested scrolling operations to a cooperating parent ViewGroup.
Related
i have a floatingActionButton inside a ConstraintLayout which is inside a ScrollView
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/background_grey">
<androidx.constraintlayout.widget.ConstraintLayout>
----
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/bag_background"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
/>
-----
</androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>
the problem is that the button is scrolling down and up with the UI
Ps: i don't know if it is important, but the scrollView is inside a drawerLayout
You can make Your root view as FrameLayout then inside it, you will but the ScrollView then the FAB button something like below
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/background_grey">
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/background_grey">
<androidx.constraintlayout.widget.ConstraintLayout>
<!-- your view xml here -->
</androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:src="#drawable/bag_background"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
/>
</FrameLayout>
To place the floating action button, use CoordinatorLayout. A CoordinatorLayout helps facilitate interactions between views contained within it, which will be useful to describe how to animate the button depending on scroll changes.
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
</androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="left|bottom"
android:layout_margin="16dp" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
I am new to Android and UI development. I have downloaded latest version of Windows Android studio and did some basic native UI, it worked well. Now, I am trying to develop floating action button UI.
I have added CoordinatorLayout inside ConstraintLayout. FAB is added inside CoordinatorLayout. My FAB is not visible in layout preview.
I see androidx.coordinatorlayout.widget.CoordinatorLayout text in that layout with background color. Please let me know how to fix this
implementation 'com.google.android.material:material:1.2.0'
<androidx.constraintlayout.widget.ConstraintLayout 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"
xmlns:app="http://schemas.android.com/apk/res-auto">
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#F44336"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
tools:ignore="MissingConstraints">
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:backgroundTint="#color/colorPrimary"
android:src="#drawable/ic_baseline_add_24"
android:layout_gravity="bottom|end"
/>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
add constraintTop for your CoordinatorLayout for filling whole screen
app:layout_constraintTop_toTopOf="parent"
or even this will be better
android:layout_width="match_parent"
android:layout_height="match_parent"
with removing all constraints
for test you may also add fixed size FloatingActionButton. if you want to keep wrap_content for FAB then ensure that ic_baseline_add_24 is valid icon with proper size
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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"
xmlns:app="http://schemas.android.com/apk/res-auto">
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#F44336"
tools:ignore="MissingConstraints">
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:layout_width="80dp"
android:layout_height="80dp"
android:backgroundTint="#color/colorPrimary"
android:src="#drawable/ic_baseline_add_24"
android:layout_gravity="bottom|end"
/>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
in above code ConstraintLayout isn't needed and you may remove it if you aren't planning to make some more complicated layout. RecyclerView may be placed inside CoordinatorLayout just before FAB - at first REcyclerView will be drawn, after that FAB on top of recycler
Try
<?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">
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#F44336"
android:layout_gravity="bottom"
tools:ignore="MissingConstraints">
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:layout_width="104dp"
android:layout_height="107dp"
android:layout_gravity="center"
android:foregroundGravity="center"
android:visibility="visible"
android:src="#drawable/ic_baseline_add_24"
app:backgroundTint="#color/colorPrimary" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
</LinearLayout>
Don't use a CoordinatorLayout with android:layout_height="wrap_content" to contain just the FAB:
<androidx.coordinatorlayout.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"
android:fitsSystemWindows="true">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/rvItems"
android:scrollbars="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="#+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
app:layout_behavior="com.google.android.material.behavior.HideBottomViewOnScrollBehavior"
android:layout_margin="#dimen/fab_margin"
app:srcCompat="#drawable/ic_add_24px" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
I have this layout for my activity which uses multiple fragments that have RecyclerView in it. The FrameLayout here is the container for the fragments. The problem is that, although I set my FrameLayout's bottom to the top of BottomNavigationView, last element of RecyclerView gets hidden under BottomNavigationView.
My code for activity layout:
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.appcompat.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="#style/ToolbarTheme"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:logo="#drawable/money_icon"
/>
<FrameLayout
android:id="#+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/toolbar"
app:layout_constraintBottom_toTopOf="#+id/bottomNavigationView"/>
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="#+id/bottomNavigationView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:menu="#menu/bottom_nav_menu" />
Code for fragment includes RecyclerView:
<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:background="#color/dark_gray"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/finishedSlipsRecycler"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
</androidx.recyclerview.widget.RecyclerView>
Screenshot of the problem:
Obviously the issue is because of this line:
app:layout_behavior="#string/hide_bottom_view_on_scroll_behavior"
Just remove it and everything will be fine.
EDIT:
Replace your ConstraintLayout in
Code for fragment includes RecyclerView:
by FrameLayout since it only contains one element. I think there's a problem with putting the ConstraintLayout inside FrameLayout like this.
The problem actually raised due to RecyclerView flows over FrameLayout. The better definition and the answer of the problem can be found here
I would like to use a CoordinatorLayout to include a BottomAppBar at the bottom of the screen, and to display some content in the remaining space (for example using a ConstraintLayout).
If I add a ConstraintLayout to the CoordinatorLayout, and then I add a button which is placed at the bottom of the ConstraintLayout, the button is covered by the BottomAppBar.
I would like the ConstraintLayout to use up all the vertical space, except for where the BottomAppBar is located, so that the button is not covered.
I tried including app:layout_behavior="#string/appbar_scrolling_view_behavior" in the ConstraintLayout, as suggested on some sites, but it doesn't work.
Also, setting app:layout_insetEdge="bottom" in the BottomAppBar, and then setting app:layout_dodgeInsetEdges="bottom" in the ConstraintLayout does not work properly, since the ConstraintLayout then overflows at the top of the screen (but the bottom is not covered anymore).
Below is the xml layout file where the BottomAppBar covers the button.
Thank you
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.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:id="#+id/coordinatorLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="top"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
<Button
android:id="#+id/myButton"
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_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<com.google.android.material.bottomappbar.BottomAppBar
android:id="#+id/bottomAppBar"
style="#style/Widget.MaterialComponents.BottomAppBar.Colored"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
I haven't found a proper fix, but what works for me is adding a margin to the one overlapping the BottomAppBar,
android:layout_marginBottom="?attr/actionBarSize"
e.g.
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="top"
android:layout_marginBottom="?attr/actionBarSize"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
<Button
android:id="#+id/myButton"
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_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
I'm trying to achieve a layout where my view will extend all the way across the screen, under the ActionBar, and the ActionBar will be transparent. I also need the ActionBar and BottomNavigationView to hide on scroll, so I'm using CoordinatorLayout.
I'm using the AppCompat theme with the attribute <item name="windowActionBarOverlay">true</item> in order to have my views extend under the ActionBar. However, after adding app:layout_behavior="#string/appbar_scrolling_view_behavior" to my container Fragment, the view gets placed below the ActionBar.
Is there a way to prevent this part of the appbar_scrolling_behaviour? I've tried without the behaviour, but the scrolling of the AppBar is not synced witht he RecyclerView scrolling underneath it. Thank you!
Here's a gif of the problem
P.S.: I'm trying to use the Android Navigation Component, so I'm following a single activity, multi fragment architecture, if that matters.
Try this code and make some changes because i used androidx..
make main layout like this way..
<?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"
android:background="#color/white">
<com.google.android.material.appbar.AppBarLayout
android:id="#+id/appBarLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<androidx.appcompat.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="#color/white"
android:theme="#style/MyToolbar"
app:contentInsetStart="0dp"
app:contentInsetStartWithNavigation="0dp"
app:titleTextAppearance="#style/MyToolbar">
<ImageView
android:id="#+id/headerIcon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="#dimen/_6sdp"
android:src="#drawable/ic_edit_location_black"
android:visibility="gone" />
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="#dimen/_6sdp">
<TextView
android:id="#+id/header"
style="#style/MyToolbar"
android:layout_width="wrap_content"
android:layout_height="?attr/actionBarSize"
android:gravity="center_vertical"
android:textColor="#color/primary"
app:layout_constraintStart_toStartOf="parent" />
<ImageView
android:id="#+id/ivSearch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="#dimen/_10sdp"
android:src="#drawable/search_icon"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.appcompat.widget.Toolbar>
</com.google.android.material.appbar.AppBarLayout>
<FrameLayout
android:id="#+id/activity_main_container"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toTopOf="#+id/bottomContainer"
app:layout_constraintTop_toBottomOf="#+id/appBarLayout" />
<RelativeLayout
android:id="#+id/bottomContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="#+id/bvTabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="#style/Widget.BottomNavigationView"
app:itemIconTint="#drawable/navigation_drawable_tint"
app:itemTextColor="#drawable/navigation_drawable_tint"
app:menu="#menu/bottom_menu_item" />
</RelativeLayout>
</androidx.constraintlayout.widget.ConstraintLayout>