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.
Related
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
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.
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
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.
I encountered a strange problem with the new Android Design Support Librar (http://android-developers.blogspot.com.ar/2015/05/android-design-support-library.html). If I place additional content (like a LinearLayout) in an AppBarLayout along with the ToolBar and toggle the visibility of that content then switching fragments will have show a dead space at the top of the fragment content.
It appears that AppBarLayout isn't resizing the parent CoordinatorLayout correctly when visibility of the content is toggled. I have my CoordinatorLayout wrapped in the DrawerLayout. I want to toggle the visibility of the extra LinearLayout in the AppBarLayout depending on the which fragment shown.
Here is my main.xml file for the MainActivity:
<android.support.v4.widget.DrawerLayout
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/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<android.support.design.widget.CoordinatorLayout
android:layout_height="match_parent"
android:layout_width="match_parent">
<android.support.design.widget.AppBarLayout
android:id="#+id/appBarLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="center_vertical"">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="start"
android:text="Hello"/>
</LinearLayout>
</android.support.design.widget.AppBarLayout>
<FrameLayout
app:layout_behavior="#string/appbar_scrolling_view_behavior"
android:id="#+id/content_frame"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</android.support.design.widget.CoordinatorLayout>
<android.support.design.widget.NavigationView
android:id="#+id/navigation"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
app:menu="#menu/drawer"/>
</android.support.v4.widget.DrawerLayout>
I had a similar problem using the support design widget. I had a CoordinatorLayout inside a DrawerLayout and an AppBarLayout inside the CoordinatorLayout. I had two toolbars inside the AppBarLayout. My aim was to display a toolbar with a ViewPager displaying a recyclerview content. I wanted to swop between the toolbars when selecting items. In other words, I made one toolbar GONE while the other was visible and vise versa. Scrolling the content up would push the toolbar up off the top of the screen. Everything worked perfectly except that changing orientation would show a space for the toolbar that should be gone. I tried every hack I could think of to get rid of it but did not succeed. I then came across this post and realized that it was a bug in the support library. I then tried putting a FrameLayout in the AppBarLayout and then put the two toolbars inside the FrameLayout and NO MORE SPACE! everything now works as I intend it to work. GONE toolbars are GONE and only the visible toolbar shows, even when changing the orientation.
Hope this helps someone.