17

In my application, I'm using tabHost Activiy.In the tabhost first tab,I'm using TabActivity,I'm loading more than 500 images.

Using Nested SCroll view:

I have used nested scroll view inside recyclerview.When loading the home page, it is loading all 500 images initially, then showing the home page.So that it cause memory out of error.

Without using nested SCroll view:

If I remove nested scroll view, everything is working good.it loads image one by one when scrolling.it doesn't cause out of memory error.

My Requirement:

I need to scroll the relative layout placed top of the recyclerview.So that I used nested scroll view.But it doesn't worked for me.

tab_home_layout:

<?xml version="1.0" encoding="utf-8"?>

<android.support.v4.widget.NestedScrollView
        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"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"
     >

<LinearLayout
    android:id="@+id/tab_home_activity"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    >

        <RelativeLayout
            android:id="@+id/home_layout_top_2_recycler"
            android:layout_width="match_parent"
            android:layout_height="60dp"
            android:background="@drawable/layout_border"
            >

            <ImageView
                android:id="@+id/img_user_home_tab_recycler"
                android:layout_width="40dp"
                android:layout_height="40dp"
                android:paddingLeft="5dp"
                android:paddingRight="5dp"
                android:layout_centerVertical="true"
                android:contentDescription="@string/cont_desc"
                android:src="@drawable/profile_pic_blue" />

            <TextView
                android:id="@+id/tv_user_mind_home_tab_recycler"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_centerVertical="true"
                android:layout_marginLeft="5dp"
                android:layout_toRightOf="@+id/img_user_home_tab_recycler"
                android:hint="@string/whats_on"
                android:textColor="@color/Black"
                android:textSize="@dimen/txt_size" />
        </RelativeLayout>

    <android.support.v7.widget.RecyclerView
            android:id="@+id/rv_list_tab_home_recycler"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:scrollbars="none"
            android:visibility="visible" />

     </LinearLayout>
</android.support.v4.widget.NestedScrollView>

Below I'm willing to share what I have tried so far.

  • I tried this SO Post.But I'm using home page inside tabActivity.So I can't use toolbar + coordinator layout.So this solution wasn't worked for me.

  • Then I tried to use multiple layout for recyclerview.But that doesn't worked for me.Because that relativelayout is a static one.If I'm getting any condition from webservice means, I can use multiple layout recyclerview.But I need to just scroll the views.

  • I planned to set the static relativelayout in 0th position of adapter.But my webservices images were loading from 0th position.So I can't set the static relativelayout in adapter at 0th position.

is there any alternate solution to solve this issue.Thank You.

Community
  • 1
  • 1
Stephen
  • 9,899
  • 16
  • 90
  • 137
  • Have you tried calling `requestDisallowInterceptTouchEvent()` from the nested View when scrolling starts? More info here: https://developer.android.com/reference/android/view/ViewGroup.html#requestDisallowInterceptTouchEvent(boolean) and here: https://developer.android.com/training/gestures/viewgroup.html – milosmns Oct 21 '16 at 13:32
  • Btw, maybe you'd like to rethink the idea of using TabActivity, as it was deprecated some time ago https://developer.android.com/reference/android/app/TabActivity.html – milosmns Oct 21 '16 at 13:35
  • @milosmns let me check requestDisallowInterceptTouchEvent() and tell you later. – Stephen Oct 21 '16 at 13:56
  • why dont you use image library like glide or picaso...that will also store your imaged in cache.. – H Raval Oct 22 '16 at 11:34

2 Answers2

22

You can use CoordinatorLayout just about anywhere you like similar to other layouts like LinearLayout or even RelativeLayout. If you want your RelativeLayout to scroll in response to your RecyclerView, simply place them inside a CoordinatorLayout with an AppBarLayout. Here's your layout modified:

<android.support.design.widget.CoordinatorLayout
    android:id="@+id/main_content"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.design.widget.AppBarLayout
        android:id="@+id/appbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <RelativeLayout
            android:id="@+id/home_layout_top_2_recycler"
            android:layout_width="match_parent"
            android:layout_height="60dp"
            android:background="@drawable/layout_border"
            app:layout_scrollFlags="scroll">

            <ImageView
                android:id="@+id/img_user_home_tab_recycler"
                android:layout_width="40dp"
                android:layout_height="40dp"
                android:paddingLeft="5dp"
                android:paddingRight="5dp"
                android:layout_centerVertical="true"
                android:contentDescription="@string/cont_desc"
                android:src="@drawable/profile_pic_blue" />

            <TextView
                android:id="@+id/tv_user_mind_home_tab_recycler"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_centerVertical="true"
                android:layout_marginLeft="5dp"
                android:layout_toRightOf="@+id/img_user_home_tab_recycler"
                android:hint="@string/whats_on"
                android:textColor="@color/Black"
                android:textSize="@dimen/txt_size" />
            </RelativeLayout>

    </android.support.design.widget.AppBarLayout>

    <android.support.v7.widget.RecyclerView
        android:id="@+id/rv_list_tab_home_recycler"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:scrollbars="none"
        android:visibility="visible"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"/>

</android.support.design.widget.CoordinatorLayout>

Change it to your preference but be sure to set the layout_height of the RelativeLayout to something other than wrap_content.

If this CoordinatorLayout is inside another CoordinatorLayout, use the NestedCoordinatorLayout from this answer as your inside CoordinatorLayout.

Community
  • 1
  • 1
razzledazzle
  • 6,900
  • 4
  • 26
  • 37
  • I tried this solution it is not scrolling the relativelayout.You can check my layout [here](http://pastie.org/private/tqzfm4b16q0l08nkypfsxa).I haven't used nested scrollview. – Stephen Oct 22 '16 at 05:30
  • 2
    You haven't included `app:layout_scrollFlags="scroll"` in your `RelativeLayout`. It's very important. Also add `app:layout_behavior="@string/appbar_scrolling_view_behavior"` to your `RecyclerView`. – razzledazzle Oct 22 '16 at 10:15
  • Your solution is working for me in profile page similar to instagram without using nested scroll view.In that profile page, I can't use multiple layout in recyclerview adapter .This solution helped me in critical situation.willing to reward bounty for 500.thank you. – Stephen Oct 26 '16 at 11:39
  • when i fling scroll from bottom to top it the recyclerview stops at item 0, and then i have to swipe again to see the relativelayout.... – Aman Verma Apr 28 '17 at 22:34
  • Does not work completely. Once I have scrolled to the bottom and again if I want to go to the top then it does not gets scrolled to the top – MrinmoyMk Apr 08 '20 at 10:06
  • You are real hero! – Dharmesh G Jul 11 '20 at 16:31
  • 1
    @razzledazzle, Scrolling works very well. However, how can I detect scroll change of the app bar, and recyclerview? – Gary Chen Dec 15 '20 at 09:09
5

The important is in onBindViewHolder you should load the image from your webservice from position-1 .
This is an example from here and in your case the Header is your static RelativeLayout

public class HeaderAdapter extends RecyclerView.Adapter < RecyclerView.ViewHolder > {
     private static final int TYPE_HEADER = 0;
     private static final int TYPE_ITEM = 1;
     String[] data;

     public HeaderAdapter(String[] data) {
         this.data = data;
     }

     @Override
     public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
         if (viewType == TYPE_ITEM) {
             //inflate your layout and pass it to view holder
             return new VHItem(null);
         } else if (viewType == TYPE_HEADER) {
             //inflate your layout and pass it to view holder
             return new VHHeader(null);
         }
     }

     @Override
     public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
         if (holder instanceof VHItem) {
             String dataItem = getItem(position);
             //cast holder to VHItem and set data

             // ***********    
             // LOAD YOUR WEBSERVICE IMAGE FROM **position - 1**
             // => for row 1 you will get the image 0 ...
             // ***********


         } else if (holder instanceof VHHeader) {
             //cast holder to VHHeader and set data for header.
         }
     }

     //increasing getItemcount to 1. This will be the row of header.
     @Override
     public int getItemCount() {
         return data.length + 1;
     }

     @Override
     public int getItemViewType(int position) {
         if (isPositionHeader(position))
             return TYPE_HEADER;

         return TYPE_ITEM;
     }

     // condition for header
     private boolean isPositionHeader(int position) {
         return position == 0;
     }

     // getItem -1 because we have add 1 header
     private String getItem(int position) {
         return data[position - 1];
     }

     class VHItem extends RecyclerView.ViewHolder {
         TextView title;

         public VHItem(View itemView) {
             super(itemView);
         }
     }

     class VHHeader extends RecyclerView.ViewHolder {
         Button button;

         public VHHeader(View itemView) {
             super(itemView);
         }
     }
 }
Community
  • 1
  • 1
Linh
  • 57,942
  • 23
  • 262
  • 279
  • @Stephen have you tried my solution? with your explain I think it can help you, but if you have more requirement please explain more – Linh Oct 24 '16 at 03:58
  • 1
    sure.now i try that one and let you know – Stephen Oct 24 '16 at 06:23
  • How can I have 2 `TYPE_ITEM` layouts and hide show each one on click? – jlively Apr 11 '17 at 07:27
  • @jlively of course you can create it, simple create one more item type – Linh Apr 11 '17 at 07:38
  • @PhanVanLinh I've tried that, but how can I show/hide each one on click? How to dynamically update the `viewType`'s? – jlively Apr 11 '17 at 07:39
  • @jlively sorry I never do it before. if possible, please post it as a another question then we can easy to help – Linh Apr 11 '17 at 07:48
  • @jlively I have an idea. for example, you RecyclerView have 2 item type -> your datasource have 2 item type, when you want to hide item1, you need remove all item from your datasource then notify all your RecyclerView, when you want to show it, you need add all item1 to your datasource again. hope it help you – Linh Apr 11 '17 at 08:04
  • For me, this solution is not working, onBindViewHolder is called for all the items at a time. – GvSharma Nov 20 '17 at 09:19