I am new to android and this is my first time asking question on stackoverflow. I am trying to implement a layout that has
A horizontal ViewPager2
Some horizontal scrolling RecyclerViews
A vertical main RecyclerView
For now I have wrapped all of the above views inside a NestedScrollView like this
<?xml version="1.0" encoding="utf-8"?>
<androidx.core.widget.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="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<include
android:id="#+id/vpMainCarasouel"
layout="#layout/item_carasouel" />
<include
android:id="#+id/rvTrendingSlide"
layout="#layout/rv_image_card_slide" />
<include
android:id="#+id/rvPopularSlide"
layout="#layout/rv_image_card_slide" />
<include android:id="#+id/rvTopRated"
layout="#layout/rv_image_card_vertical"
/>
</LinearLayout>
</androidx.core.widget.NestedScrollView>
But I have read that using a Vertical Scroll view (The Vertical RecyclerView rvTopRated) inside another Vertical ScrollView (NestedScrollView) is not a good practice.
So how can I add other views (that requires scroll) and then continue on with a main Vertical RecyclerView (rvTopRated) ?
Here is the layout I am trying to implement.
Related
I don't want to use recycler view here.
Because here is 3-4 Linear Layouts with static data.
I am using coordinator layout here, how can I make scrollable linear layouts inside it.
<?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"
android:background="#color/colorDark"
android:fitsSystemWindows="true"
tools:context=".EarnActivity">
<include layout="#layout/appbar"></include>
<- Here I want to insert linear layouts,
But how can I make this coordinator layout scrollable.
All things inside it should Scroll -->
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="#+id/bottomNav3"
android:layout_gravity="bottom"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:itemBackground="#android:color/transparent"
app:layout_behavior="#string/hide_bottom_view_on_scroll_behavior"
app:itemIconTint="#color/item_selector"
app:itemTextColor="#color/item_selector"
app:menu="#menu/nav_menu">
</com.google.android.material.bottomnavigation.BottomNavigationView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
I have a view that acts like BottomSheetBehavior and this view has ViewPager2 inside. Each ViewPager2's page is a vertical RecyclerView. The issue is that BottomSheet doesn't scroll down when current vertical RecyclerView (which is a page of ViewPager) can't scroll vertically anymore. Everything works file when instead of ViePager I have only one vertical RecyclerView.
The temporary solution is to wrap ViewPager with NestedScrollView but it's horrible for performance and has it's own bugs.
The original layout:
<?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/core"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#C7C7C7"
tools:context=".MainActivity">
<LinearLayout
android:id="#+id/bottom_sheet"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#FFFFFF"
android:elevation="8dp"
android:orientation="vertical"
app:behavior_hideable="true"
app:behavior_peekHeight="300dp"
app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior">
<com.google.android.material.tabs.TabLayout
android:id="#+id/tab_layout"
android:layout_width="wrap_content"
android:layout_height="24dp"
android:layout_gravity="center_horizontal"
app:tabGravity="center"
app:tabMode="scrollable" />
<androidx.viewpager2.widget.ViewPager2
android:id="#+id/view_pager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
[Here's how it looks (sorry for the gif quality)]
I've found a solution for this case, I set isNestedScrollingEnabled = false for inner RecyclerView so that BottomSheetBehavior finds another scrolling view
viewPager.children.find { it is RecyclerView }?.let {
(it as RecyclerView).isNestedScrollingEnabled = false
}
BottomSheetBehaviour only detects the first scrollable view. So it is always recommended to use only one scrollable view inside of it.
For More information check this answer bottomsheetbehavior-with-two-recyclerview
And this one also Scroll not working for multiple RecyclerView in BottomSheet
If you really want to have the two scrollable views I recommend you to take a look at this library also AndroidSlidingUpPanel
Abstract
Trying something similar to Google Maps layout behaviour
Detail
I'm trying to implement a BottomSheetBehavior that has a
ViewGroup (any) -> ViewPager(Fragments) -> RecyclerView (Vertical) -> Multiple horizontally scrollable RecyclerView / or any scrollable view.
The horizontally scrollable child RecyclerViews are part of ItemHolders of parent RecyclerView (vertically scrollable)
<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"
tools:context=".bottom.BottomSheetActivity">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
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" />
</android.support.design.widget.AppBarLayout>
<include layout="#layout/content_bottom_sheet" />
<android.support.v4.widget.NestedScrollView
android:id="#+id/frame_bottom"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:behavior_hideable="false"
app:behavior_peekHeight="240dp"
android:background="#android:color/white"
app:layout_behavior="android.support.design.widget.BottomSheetBehavior">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerView_bottom"
android:layout_width="match_parent"
android:nestedScrollingEnabled="true"
android:layout_height="match_parent"/>
</FrameLayout>
</android.support.v4.widget.NestedScrollView>
</android.support.design.widget.CoordinatorLayout>
Problem
When a user touches inside the horizontal scrollable element & tries to scroll vertically, the parent RecyclerView is not scrolling up/down.
When the user touches outside the horizontal scrollable element & tries to scroll vertically, the parent RecyclerView is WORKING as usual.
This problem happens only when using BottomSheetBehavior, without BottomSheetBehavior, it works perfectly fine.
I tried with a FrameLayout instead of a NestedScrollView, also tried directly putting ReyclerView as the BottomSheetBehavior viewgroup. It didn't work.
So, how do I pass the vertical scroll touch events from a horizontally scrollable reyclerView which is part of a viewHolder to the parent RecyclerView when using a BottomSheetBehavior?
I am using the following layout, but unable to get the RecyclerView to scroll(it is not visible on the screen when using this layout, scrolling stops till the NestedScrollView).
I can scroll up to the NestedScrollView and the CollapsingToolbar to collapse, if I remove the entire NestedScrollView then I get the RecyclerView to scroll.
If I keep the linear layout without the NestedScrollView, only the RecyclerView scrolls, the rest of the layout is fixed.
I have also added app:layout_behavior="#string/appbar_scrolling_view_behavior" to the RecyclerView, and have kept the RecyclerView out of the NestedScrollView.
If I add the RecyclerView inside the NestedScrollView, the RecyclerView does not appear.
<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:fitsSystemWindows="true"
tools:context="com.example.MainFragment">
<!-- android.support.design.widget.AppBarLayout here
with a android.support.design.widget.CollapsingToolbarLayout
-->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dp">
<!-- more layout code here -->
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="#string/large_text"/>
</RelativeLayout>
<View
android:id="#+id/separator"
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#color/colorAccent" />
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerViewListOfData"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:listitem="#layout/recycler_view"
app:layout_behavior="#string/appbar_scrolling_view_behavior"/>
</LinearLayout>
Ok, if you want to add RecyclerView inside NestedScrollView add this line into RecyclerView in xml file app:layoutManager="LinearLayoutManager".
Example
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="#+id/your_recyclerview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layoutManager="LinearLayoutManager"/>
</android.support.v4.widget.NestedScrollView>
Then in your SomeActivity.java file where you populate RecyclerView put this line recyclerView.setNestedScrollingEnabled(false); before you setting adapter to RecyclerView.
Example
RecyclerView recyclerView=(RecyclerView)findViewById(R.id.your_recyclerview);
recyclerView.setNestedScrollingEnabled(false);
recyclerView.setAdapter(yourAdapter);
I solved it by nesting RecyclerView inside the NestedScrollView and updating the support library for recyclerview
I was using com.android.support:recyclerview-v7:23.0.1
as of Android Support Library, revision 23.2.0 (February 2016)
(refer revision archive here)
Changes for v7 RecyclerView library:
RecyclerView now has an opt-in feature called AutoMeasure which allows RecyclerView.LayoutManager to easily wrap content or
handle various measurement specifications provided by the parent of
the RecyclerView. It supports all existing animation capabilities of
the RecyclerView.
If you have a custom RecyclerView.LayoutManager, call setAutoMeasureEnabled(true) to start using the new AutoMeasure API.
All built-in RecyclerView.LayoutManager objects enable auto-measure by
default.
RecyclerView.LayoutManager no longer ignores some RecyclerView.LayoutParams settings, such as MATCH_PARENT in the scroll
direction.
Note: These lifted restrictions may cause unexpected behavior in your
layouts. Make sure you specify the correct layout
parameters.
Using com.android.support:recyclerview-v7:23.4.0 solves the problem of nested recyclerview not appearing in nested scroll view
I have a fragment which uses a coordinator layout to show an AppBarLayout and a recycler view like this:
The layout file is thus far:
<?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:orientation="vertical">
<android.support.design.widget.AppBarLayout
android:layout_width="wrap_content"
app:elevation="4dp"
android:layout_height="wrap_content">
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_scrollFlags="scroll|snap">
<!-->Content removed<-->
</RelativeLayout>
</android.support.design.widget.AppBarLayout>
<android.support.v7.widget.RecyclerView
android:id="#+id/fragment_recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior"/>
</android.support.design.widget.CoordinatorLayout>
The problem I'm having is that if I fling the recycler view so that the list scrolls all the way to the top, the AppBarLayout doesn't reveal unless I specifically pull down again. Is there a scroll flag to make the AppBarLayout come down when the recycler view reaches the top, as if it's attached to the first item in the recycler view?
No, transferring inertial is a known issue with nested scrolling in general, both with the platform APIs and those used by CoordinatorLayout.