Snackbar not moving FAB that placed inside Fragment - android

There is a scheme that describes view hierarchy of my application.
And some XML
MainActivity
. CoordinatorLayout
. FrameLayout <- ContentFragment inserted here
app:layout_behavior="#string/appbar_scrolling_view_behavior"
. AppBarLayout
. Toolbar
ContentFragment
<FrameLayout
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.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical"/>
<android.support.design.widget.FloatingActionButton
android:id="#+id/fab"
android:layout_width="56dp"
android:layout_height="56dp"
android:src="#drawable/ic_plus_white_36dp"
android:layout_gravity="bottom|end"
android:layout_margin="15dp"
app:elevation="6dp"
app:pressedTranslationZ="12dp"/>
<TextView
android:id="#+id/hint_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="#string/empty_dates_list"
android:padding="20dp"
android:textSize="20sp"
android:layout_gravity="center" />
</FrameLayout>
With this code I make SnackBar:
Snackbar snackbar = Snackbar.make(
mainActivity.getCoordinatorLayout(),
R.string.date_removed,
Snackbar.LENGTH_LONG);
My problem is that fab is not moving up by SnackBar that I make in ContentFragment
I also tried point fab as view for Snackbar but it has not brought results.

You should use CoordinatorLayout to avoid this issue because CoordinatorLayout alone properly coordinates layout changes caused by its child views.
To solve your issue, simply move the FloatingActionButton from the fragment layout to the MainActivity layout. Or if you intend to use the FloatingActionButton in the fragment itself, then set the parent view of the fragment to be a CoordinatorLayout

For this to work, FloatingActionButton should be a child of CoordinatorLayout. Yours is a child of FrameLayout.

Related

Why does my RecyclerView not scroll when placed inside an AppBarLayout?

I have an AppBarLayout in my app along with a FrameLayout that I use as a placeholder to load in fragments:
<android.support.design.widget.AppBarLayout
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:theme="#style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="#style/AppTheme.PopupOverlay"/>
<FrameLayout android:id="#+id/main_content_fragment"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:background="#color/white" />
</android.support.design.widget.AppBarLayout>
The fragment in question looks like this:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ProgressBar android:id="#+id/loading_downloaded"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<android.support.v7.widget.RecyclerView
android:id = "#+id/items_downloaded"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical"
app:layout_constraintEnd_toEndOf="parent"
/>
</LinearLayout>
The Fragment is substituted in from code as you might anticipate:
val fragMan: FragmentManager = getSupportFragmentManager()
fragMan.beginTransaction().add(R.id.main_content_fragment, fragment).commit()
The problem is that I cannot scroll my RecyclerView when I format it this way. If I move the FrameLayout outside of the AppBarLayout it works perfectly but then the fragment lies behind the app bar, which is very untidy. This confirms for me that the fragment is working correctly, I just can't figure out why the fragment's scroll behaviour changes when it's within the AppBarLayout.
What do I need to do to be able to scroll my content? Or have I misunderstood and I need to display my fragments outside the AppBarLayout where they scroll correctly and shift everything down by the height of the app bar?
Your fragment's content is meant to be placed as a sibling of the AppBarLayout. You should wrap everything inside a CoordinatorLayout and set this attribute in your FrameLayout where your fragment resides: app:layout_behavior="#string/appbar_scrolling_view_behavior".
Here's your XML structure would be:
<CoordinatorLayout>
<FrameLayout
app:layout_behavior="#string/appbar_scrolling_view_behavior" ... >
...
</FrameLayout>
<AppBarLayout> ... </AppBarLayout>
</CoordinatorLayout>
Having this setup would allow your fragment to show all of it's views with your AppBarLayout. CoordinatorLayout will take care of everything for you.
Here's the official documentation:
AppBarLayout also requires a separate scrolling sibling in order to
know when to scroll. The binding is done through the
AppBarLayout.ScrollingViewBehavior behavior class, meaning that you
should set your scrolling view's behavior to be an instance of
AppBarLayout.ScrollingViewBehavior. A string resource containing the
full class name is available.
See this link for more details: https://developer.android.com/reference/android/support/design/widget/AppBarLayout.html

Where to put floating action button when there are multiple fragments

I'm trying to create a layout with a MainActivity which incorporates a BottomNavigationBar and a FrameLayout for swapping out fragments. I want the BottomNavigationBar to stay fixed with every fragment having a fab which on the other hand disappears when scrolling. The problem is that I'm not sure which layout to use for the MainActivity and the Fragments and where to put the fab, I could put the fab either in the MainActivity's layout and change the behaviour of the fab for each fragments (don't know how though) or add a fab to every fragment's layout. When I do the latter I cannot reference the MainActivity's bottom bar to stay over it.
I tried #1:
MainActivity:
<CoordinatorLayout>
<FrameLayout/>
<BottomNav/>
<FAB/>
</CoordinatorLayout>
And #2:
<CoordinatorLayout>
<FrameLayout/> -> fabs defined in each fragment layout
<BottomNav/>
</CoordinatorLayout>
My Main activites xml file looks somewhat like this:
<?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"
xmlns:app="http://schemas.android.com/apk/res-auto">
<FrameLayout
android:id="#+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="#id/bottom_navigation"/>
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="#+id/bottom_navigation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:menu="#menu/bottom_navigation"
android:layout_gravity="bottom"
android:background="?android:attr/windowBackground"/>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
And one of my fragments with FAB:
<?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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".View.MainActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:listitem="#layout/note_item"
android:layout_gravity="top" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="#+id/button_add_note"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|right"
android:layout_marginBottom="64dp"
android:layout_marginEnd="16dp"
android:src="#drawable/ic_add"
app:layout_anchor="#id/recycler_view"
app:layout_anchorGravity="bottom|right|end"/>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
I want the bottom nav and coordinator layout to be aware of the fab and the fab to be above the bottom nav without using hard-coded dp values but how do I do that?
If you want to use CoordinatorLayout.Behavior logic, your fab should at the same level with CoorditorLayout.
For you i recommend this logic: Activity contains BottomNavigation, FrameLayout (fragment container). Then all your fragment contains:
<CoordinatorLayout>
<RecyclerView/>
<FloatingButton/>
</CoordinatorLayout>
It will give a power to construct UI of fragment exactly how you want.

Collapse layout in a fragment under toolbar

The following is my layout in a Fragment.
<?xml version="1.0" encoding="utf-8"?>
<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"
android:id="#+id/parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context=".fragments.TAClaimFragment"
android:background="#drawable/main_gradient"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_anchor="#id/parent"
app:layout_anchorGravity="top">
<android.support.v7.widget.SearchView
android:layout_width="0dp"
android:layout_weight="2"
android:layout_height="?actionBarSize"
android:layoutDirection="rtl"
android:id="#+id/ta_search"
android:animateLayoutChanges="true"
app:searchIcon="#drawable/ic_search"
app:closeIcon="#drawable/ic_close"
android:tooltipText="tooltip"
app:searchHintIcon="#drawable/ic_search"
app:queryHint="#string/search_hint"
/>
<ImageView
android:layout_width="0dp"
android:id="#+id/ta_menu"
android:padding="16dp"
android:layout_weight="0.3"
android:layout_height="50dp" />
</LinearLayout>
<android.support.v7.widget.RecyclerView
android:id="#+id/ta_recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent">
</android.support.v7.widget.RecyclerView>
</LinearLayout>
The RecyclerView has a SearchView and an ImageView above it in a linear layout I want the linear layout to disappear under the toolbar which the Activity containing the fragment has. I am not familiar enough with coordinator layout or collapsing toolbar layout, however I guess the solution lies in the use of the two.
How do I go about it?
I want the linear layout to disappear under the toolbar which the
Activity containing the fragment has.
If you are showing the Fragment by a FrameLayout (Or whatever), show the Fragment like following layout: (FrameLayout inside NestedScrollView for being the layout scrollable)
<CoordinatorLayout>
<AppBarLayout>
<Toolbar/>
</AppBarLayout>
<NestedScrollView>
<FrameLayout />
</NestedScrollView>
</CoordinatorLayout>
And then your Fragment codes (like your current layout codes) in another layout called myfragmentlayout.xml.
So, here, if you are trying to hide the LinearLayout, it will be disappear when you scroll the RecyclerView. Or, you can create a CollpasingToolbarLayout which contains a picture then if you scroll the content, it will be disappear.
Example for CollapsingToolbarLayout with an ImageView inside. (And so much more on SO by CollapsingToolbarLayout tag!):
How to add an ImageView with the title in collapsingtoolbarlayout in Android

Floating Action Button position

I have a Fragment in the bottom of my layout, and when it is shown it overlaps with my FAB.
So, how can I make FAB to depend on this Fragment (lift FAB when the Fragment is shown, just like it does when Snackbar is shown)?
The behaviour between the FAB and the Snackbar is result of having the CoordinatorLayout as the direct parent of the two views. The coordinator layout handles this animation effect.
Coordinator layout is used as a container for a specific
interaction with one or more child views.
By specifying Behaviors for child views of a CoordinatorLayout you can
provide many different interactions within a single parent and those
views can also interact with one another.
Reference: Coordinator Layout | Android Developers
So your view holding the fragment needs to have a Behaviour implementation for it. This will define how your views interact with other views.
Check this guide for how to create Behaviours for CoordinatorLayout.
For FloatingActionButton this behaviour is already defined in its class. Check source here.
I've found a solution. Here is my layout:
<RelativeLayout
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.CoordinatorLayout
android:id="#+id/main_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="#+id/mediaPlayerControlBar">
<RelativeLayout>
</RelativeLayout>
<android.support.design.widget.FloatingActionButton
app:layout_behavior="com.unimusic.ScrollAwareFABBehavior"
app:fabSize="normal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:src="#drawable/ic_search_white_24dp"
android:id="#+id/fab"
android:layout_margin="16dp"
app:elevation="4dp"/>
</android.support.design.widget.CoordinatorLayout>
<fragment android:name="com.unimusic.mediaPlayerControlBar"
android:layout_width="match_parent"
android:layout_height="70dp"
android:id="#+id/mediaPlayerControlBar"
android:layout_gravity="bottom"
app:layout_anchor="#id/snackbarPosition"
app:layout_anchorGravity="bottom"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
</RelativeLayout>
Basicly, I've made Relative layout a root component instead of CoordinatorLayout.

Android Cannot anchor FAB button to BottomSheet

I'm trying to attach a FAB button to the BottomSheet view like Google Maps does. However I cannot make it work,
this is the code of the FAB button:
<android.support.design.widget.FloatingActionButton
android:id="#+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="#dimen/fab_margin"
android:src="#android:drawable/ic_dialog_email"
app:layout_anchor="#+id/nestedscrollview" --> BottomSheet view ID
app:layout_anchorGravity="bottom|end"
app:elevation="4dp"
/>
and this is the code of the BottomSheet View
<android.support.v4.widget.NestedScrollView
android:id="#+id/nestedscrollview"
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"
app:layout_behavior="android.support.design.widget.BottomSheetBehavior"
tools:context="com.pub.uac.ui.location.LocationActivity"
android:background="#color/background_white_trasnparent"
>
...
</...
It depends on what you mean by "cannot make it work" and also what you try to achieve.
Does it work better if you set on the FAB:
app:layout_anchorGravity="top|end"
You used "bottom" instead of "top", so the FAB will not be pushed by the bottom sheet, it will stay at the bottom. With "top" it should at least follow the sheet.

Categories

Resources