I have created and xml file like:
<android.support.design.widget.CoordinatorLayout>
<android.support.design.widget.AppBarLayout>
<android.support.design.widget.CollapsingToolbarLayout/>
<android.support.design.widget.AppBarLayout/>
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fillViewport="true"
app:layout_behavior="CustomScrollingBehavior">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TableLayout
android:layout_width="fill_parent"
android:layout_height="?attr/actionBarSize"/>
<android.support.v4.view.ViewPager
android:id="#+id/viewPager"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:nestedScrollingEnabled="true"
app:layout_behavior="CustomScrollingBehavior"/>
<LinearLayout/>
<android.support.v4.widget.NestedScrollView/>
<android.support.design.widget.CoordinatorLayout/>
ViewPager has FragmentStatePagerAdapterand each fragment has a RecyclerView insdie. Everything is working fine except when loading content the first Fragment of the ViewPager has scrolling issue.
When I scroll first Fragment it gets stuck and does not scroll after the CollapsingToolbarLayout is collapsed completely. But after waiting for 2-3 seconds or switching to another fragment inside ViewPager and scrolling, it starts scrolling normally.
If anyone else has come across this problem please help me.
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 have a screen where i need to display a toolbar at the top, a slideshow below the toolbar and a recyclerview below the slideshow.
For displaying the slideshow I am using a viewPager which slides images horizontally.
The problem I am currently facing is that when the recyclerview is scrolled the viewPager needs to scroll with it and the toolbar should stay pinned.
I tried putting the viewPager and the recyclerview inside a nested Scroll but since a nested scroll requires a single child i had to put both the viewpager and recyclerview inside a linear layout because of which the scrolling behaviour of the recyclerview went for a toss ( i am monitoring the recyclerview scroll so i can load more results when it reaches the bottom ).
You can solve this problem by using CoordinatorLayout, AppBarLayout, and CollapsingToolbarLayout. You put your Toolbar and ViewPager in the CollapsingToolbarLayout, and you use the RecyclerView as the scrolling sibling to the AppBarLayout so that it can correctly collapse the ViewPager.
Here's some example XML I used to achieve what I think you described:
<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.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.design.widget.CollapsingToolbarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<android.support.v4.view.ViewPager
android:layout_width="match_parent"
android:layout_height="200dp"
android:layout_marginTop="?attr/actionBarSize"/>
<android.support.v7.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_collapseMode="pin"/>
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
app:layoutManager="LinearLayoutManager"/>
</android.support.design.widget.CoordinatorLayout>
The only tricky bit is that the <Toolbar> tag has to come after the <ViewPager> tag, since they're both inside a view that derives from FrameLayout. Normally, this would mean that the toolbar obscures the top portion of the viewpager, but the viewpager's marginTop attribute stops that from happening.
I have:
1.Coordinator layout
2.appbar layout (child of Coordinator layout)
3.Collapsing toolbar layout (child of app bar)
4.NestedScrollView (child of coordinator)
I want to put a grid view inside NestedScrollView so that user can scroll over the entire screen space.
My problem is that currently the gridview occupies a small portion of the NestedScrollView and not full space of NestedScrollView and scrolls inside that portion,like in this image:
As you can see my gridview height is limited upto only that highlighted portion in sky blue color, i want that to occupy the entire screen space below that image(which is my Collapsing toolbar).i tried different ways but nothing works out.
my xml file is:
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:id="#+id/app_bar"
android:layout_height="wrap_content"
android:theme="#style/AppTheme.AppBarOverlay">
<android.support.design.widget.CollapsingToolbarLayout
android:id="#+id/collapsing_toolbar"
android:layout_width="match_parent"
android:layout_height="196dp"
android:background="#3f51b5"
app:contentScrim="#color/colorPrimary"
app:expandedTitleMarginEnd="64dp"
app:expandedTitleMarginStart="48dp"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<ImageView
android:id="#+id/imageview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
android:src="#drawable/index"
app:layout_collapseMode="parallax" />
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_collapseMode="pin"
app:layout_scrollFlags="scroll|enterAlways"
app:popupTheme="#style/AppTheme.PopupOverlay" />
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
<GridView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="1dp"
android:layout_marginRight="1dp"
android:id="#+id/gridView"
android:verticalSpacing="1dp"
android:horizontalSpacing="1dp"
android:numColumns="2"
android:stretchMode="columnWidth"/>
</android.support.v4.widget.NestedScrollView>
<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="#dimen/fab_margin"
android:src="#android:drawable/ic_dialog_email" />
GridView already has scrolling built in, so it conflicts with a NestedScrollView. You should be using a RecyclerView with a GridLayoutManager and appbar_scrolling_view_behavior layout behavior in place of the NestedScrollView.
well i had the same issue , the following worked for me.
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
android:fillViewport="true">
It is true, that GridView conflicts with the NestedScrollView and the correct solution would be to use the RecyclerView, but I needed a quick workaround with such setup and came across a solution using a custom class extending the GridView:
https://gist.github.com/jiahuang/2591977
Then you just have to replace your GridView with the custom class and set the parameter of NestedScrollView as in Apoorv's answer:
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
android:fillViewport="true">
Apoorv Singh's answer helped me, but not fully. You can put a GridView inside a NestedScrollView, but only the 1st row will show up. You need to add the android:fillViewport="true" inside the NestedScrollView definition in order for everything to display properly.
But, when I scroll down, it doesn't scroll past the bottom of the screen. I have a grid with 10 rows, there are multiple rows not on screen, but I cannot scroll down to view them now.
Answer:
This worked for me now. Use RecyclerView with GridLayoutManager instead of GridView. As Recycler view is compatible with Collapsing toolbar as well. And when you use RecyclerView inside NestedScrollView, it works well. Everything sizes correctly, as well as scrolls correctly.
Inside NestedScrollView add this one line code
android:fillViewport="true"
Have a look at the following layout. You will see, that the floating button is too far to the bottom. This is because the Toolbar and the Tabs are shown and the height of the ViewPager is wrong. So somehow I'm doing something wrong with the layout_height. But how can I fix that?
Remark: The ViewPager is the main content and it contains a fragment with a ListView and a Google Map V2 in the second tab.
That's the layout XML:
<?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.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:layout_scrollFlags="scroll|enterAlways" />
<android.support.design.widget.TabLayout
android:id="#+id/sliding_tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
android:id="#+id/pager_list_views"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
android:layout_width="match_parent"
android:layout_height="fill_parent">
</android.support.v4.view.ViewPager>
</android.support.design.widget.CoordinatorLayout>
Here's the layout for the fragment in the first tab (the list):
<?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">
<ListView
android:id="#+id/preview_list"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:choiceMode="singleChoice"
android:orientation="vertical" />
<android.support.design.widget.FloatingActionButton
android:id="#+id/action_add"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|bottom"
android:layout_margin="16dp"
android:src="#mipmap/ic_add_white_48dp" />
</android.support.design.widget.CoordinatorLayout>
Just to make sure; it's not a problem with the FAB. See this picture. It's a similar layout. A CoordinatorLayout with a ToolBar and a ViewPager which swipes through all detail-entries (therefore no tabs are needed). And again, the inner view seems to be too long (the same height as the ToolBar).
You should use android.support.v7.widget.RecyclerView and not ListView
Although you are already using android.support.v7.widget.RecyclerView be 100% sure that you have declard compile 'com.android.support:recyclerview-v7:23.0.0' in your build.gradle dependencies. I encountered the same issue where the viewpager overlaps the system buttons. I fixed it by simply adding this dependency.
Anything you what to be "coordinate" need to be direct child of CoordinatorLayout, Including the AppBar, RecyclerView (ListView in API21+ or other view support nested scroll is OK), or FAB, etc.
The reason why your FAB is offset out of screen, is that:
ViewPager has a #string/appbar_scrolling_view_behavior, the implement of this behavior will offset view when you scroll.
you put FAB inside ViewPager.
So when the offset of ViewPager changed, anything inside ViewPager will offset together (extra CoordinatorLayout has no help to change offset).
To fix this, don't use CoordinatorLayout outside ViewPager.
Or:
Put your FAB out of ViewPager so it won't scroll with ViewPager.
If the FAB only work with some of your page, hide() it when need.
BTW, there is very good App, Cheesesquare Sample, to demo the design library.
I have a little strange problem for me. I need to translate view which is located over a viewpager on recyclerview scroll. RecyclerView is located in fragment and fragments are located in viewpager. When I scroll recyclerview in fragment and want to translate View which is located over viewpager my problem occurs. ViewPager is moving up to fill space left by translated view, but fragments aren't. Because of it I can see space empty space on viewpager. I checked it by setting viewpager background and i saw that viewpager actually resized to match container but fragments remained still. Any ideas how to force it to works as it should be? This code works perfectly when recyclerview and view which I want to resize are on same fragment.
Issue look like this http://i.imgur.com/wyxXGYh.png
Layout look like this
ViewPagerFragment
<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:orientation="vertical"
android:clipToPadding="false">
<android.support.v7.widget.RecyclerView
android:id="#+id/subcategory_fragment_recycle_view"
android:scrollbars="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</android.support.v7.widget.RecyclerView>
Layout with Viewpager
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#id/fragment_category_sliding_tab_layout">
<android.support.v4.view.ViewPager
android:id="#+id/fragment_category_viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingTop="100dp"
android:clipToPadding="false"
android:background="#0000FF"
android:animateLayoutChanges="true">
</android.support.v4.view.ViewPager>
<TextView
android:id="#+id/scrollTemp"
android:layout_width="match_parent"
android:layout_height="100dp"
android:background="#FF0000"
android:gravity="center|center_vertical"
android:text="TEMP"
android:textSize="40dp" />
</FrameLayout>
For detecting scrollevents and triggering show/hide of temp view I am using basically this HidingScrollListener https://mzgreen.github.io/2015/02/28/How-to-hideshow-Toolbar-when-list-is-scrolling%28part2%29/. As I said it works perfectly when recyclerview and view which I want to scroll are on same fragment.