title: Android WebView and recyclerview inside ScrollView
body: <p>I have a web page with image and some text, image is having parallax effect. when i am loading the web page in a web view which is inside a scroll view, the parallax effect is not working. Scroll view also have recycler view along with web view. How to achieve the parallax effect in web page as well as seamless  scroll for the whole page?</p>
  <p><a href="https://vimeo.com/210562790" rel="nofollow noreferrer">This video have the page i have developed with web view inside scroll view</a></p>
  <p><a href="https://vimeo.com/210562915" rel="nofollow noreferrer">This video is the demo screen with only web view, just to test the parallax in the web page</a></p>
  <h1>Layout</h1>
  <pre><code>&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
  &lt;RelativeLayout xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
      android:id=&quot;@+id/parent_view&quot;
      android:layout_width=&quot;match_parent&quot;
      android:layout_height=&quot;match_parent&quot;
      android:background=&quot;@android:color/white&quot;&gt;
  
      &lt;android.support.v4.widget.NestedScrollView xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
          android:layout_width=&quot;match_parent&quot;
          android:layout_height=&quot;match_parent&quot;
          android:fillViewport=&quot;true&quot;&gt;
  
          &lt;LinearLayout xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
              android:id=&quot;@+id/news_detail_layout&quot;
              android:layout_width=&quot;match_parent&quot;
              android:layout_height=&quot;match_parent&quot;
              android:orientation=&quot;vertical&quot;&gt;
  
              &lt;WebView
                  android:id=&quot;@+id/web_view&quot;
                  android:layout_width=&quot;match_parent&quot;
                  android:layout_height=&quot;wrap_content&quot; /&gt;
  
              &lt;RelativeLayout
                  android:id=&quot;@+id/related&quot;
                  android:layout_width=&quot;match_parent&quot;
                  android:layout_height=&quot;wrap_content&quot;
                  android:visibility=&quot;gone&quot;&gt;
  
                  &lt;View
                      android:id=&quot;@+id/view&quot;
                      android:layout_width=&quot;match_parent&quot;
                      android:layout_height=&quot;@dimen/list_item_divider_height&quot;
                      android:background=&quot;#dedede&quot;
                      android:visibility=&quot;visible&quot; /&gt;
  
                  &lt;TextView
                      android:id=&quot;@+id/related_title&quot;
                      android:layout_width=&quot;match_parent&quot;
                      android:layout_height=&quot;wrap_content&quot;
                      android:layout_below=&quot;@+id/view&quot;
                      android:layout_margin=&quot;@dimen/main_margin&quot;
                      android:text=&quot;@string/related_news&quot;
                      android:textColor=&quot;@android:color/black&quot;
                      android:textSize=&quot;@dimen/list_item_title&quot;
                      android:textStyle=&quot;bold&quot;
                      android:visibility=&quot;visible&quot; /&gt;
  
                  &lt;android.support.v7.widget.RecyclerView
                      android:id=&quot;@+id/related_article&quot;
                      android:layout_width=&quot;match_parent&quot;
                      android:layout_height=&quot;wrap_content&quot;
                      android:layout_below=&quot;@+id/related_title&quot;
                      android:layout_marginLeft=&quot;8dp&quot;
                      android:layout_marginRight=&quot;8dp&quot;
                      android:visibility=&quot;visible&quot; /&gt;
              &lt;/RelativeLayout&gt;
  
              &lt;RelativeLayout
                  android:id=&quot;@+id/recommendation&quot;
                  android:layout_width=&quot;match_parent&quot;
                  android:layout_height=&quot;wrap_content&quot;
                  android:visibility=&quot;gone&quot;&gt;
  
                  &lt;View
                      android:id=&quot;@+id/recommendation_seperator&quot;
                      android:layout_width=&quot;match_parent&quot;
                      android:layout_height=&quot;@dimen/list_item_divider_height&quot;
                      android:background=&quot;#dedede&quot;
                      android:visibility=&quot;visible&quot; /&gt;
  
                  &lt;TextView
                      android:id=&quot;@+id/recommendation_title&quot;
                      android:layout_width=&quot;wrap_content&quot;
                      android:layout_height=&quot;wrap_content&quot;
                      android:layout_margin=&quot;@dimen/main_margin&quot;
                      android:text=&quot;Sponsored Stories&quot;
                      android:textColor=&quot;@android:color/black&quot;
                      android:textSize=&quot;@dimen/list_item_title&quot;
                      android:textStyle=&quot;bold&quot; /&gt;
  
                  &lt;LinearLayout
                      android:layout_width=&quot;wrap_content&quot;
                      android:layout_height=&quot;wrap_content&quot;
                      android:layout_alignParentRight=&quot;true&quot;
                      android:layout_margin=&quot;@dimen/main_margin&quot;
                      android:orientation=&quot;horizontal&quot;&gt;
  
                      &lt;TextView
                          android:id=&quot;@+id/drawer_title_view&quot;
                          android:layout_width=&quot;wrap_content&quot;
                          android:layout_height=&quot;wrap_content&quot;
                          android:layout_centerVertical=&quot;true&quot;
                          android:layout_gravity=&quot;center&quot;
                          android:text=&quot;Recommended by &quot;
                          android:textColor=&quot;@color/black_semi_trans&quot;
                          android:textSize=&quot;12dp&quot;
                          android:textStyle=&quot;bold&quot; /&gt;
  
                      &lt;ImageView
                          android:layout_width=&quot;24dp&quot;
                          android:layout_height=&quot;24dp&quot;
                          android:src=&quot;@drawable/ic_recommendation&quot; /&gt;
                  &lt;/LinearLayout&gt;
  
                  &lt;android.support.v7.widget.RecyclerView
                      android:id=&quot;@+id/recommendation_view&quot;
                      android:layout_width=&quot;match_parent&quot;
                      android:layout_height=&quot;wrap_content&quot;
                      android:layout_below=&quot;@+id/recommendation_title&quot; /&gt;
              &lt;/RelativeLayout&gt;
  
          &lt;/LinearLayout&gt;
      &lt;/android.support.v4.widget.NestedScrollView&gt;
  
      &lt;ProgressBar
          android:id=&quot;@+id/progress_bar&quot;
          android:layout_width=&quot;wrap_content&quot;
          android:layout_height=&quot;wrap_content&quot;
          android:layout_centerInParent=&quot;true&quot; /&gt;
  &lt;/RelativeLayout&gt;
  </code></pre>
  <h1>Java Class</h1>
  <pre><code>   public class NewsDetailFragment extends Fragment implements ViewModel.ResponseListener&lt;News&gt;, RecyclerViewEvents.Listener&lt;Object&gt;,
          View.OnKeyListener, RecommendationsListener {
  
      private List&lt;NewsItem&gt; relatedList = new ArrayList&lt;&gt;();
      private RelatedArticleListAdapter relatedAdapter;
      private String url;
      private ClickEvents.ListItemListener listItemListener;
      private WebView webView;
      private ProgressBar progressBar;
      private boolean isWebViewPaused;
      private List&lt;OBRecommendation&gt; outbrainList = new ArrayList();
      private OutbrainAdapter outbrainAdapter;
  
      @Override
      public void onAttach(Activity activity) {
          super.onAttach(activity);
          listItemListener = (ClickEvents.ListItemListener) activity;
      }
  
      @Override
      public void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          url = getArguments().getString(Constants.BundleKeys.URL);
      }
  
      @Nullable
      @Override
      public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
          View view = inflater.inflate((Network.isConnected(getActivity())) ? R.layout.fragment_news_detail : R.layout.fragment_news_detail_offline, container, false);
          progressBar = (ProgressBar) view.findViewById(R.id.progress_bar);
          webView = (WebView) view.findViewById(R.id.web_view);
          webView.setHorizontalScrollBarEnabled(false);
          webView.getSettings().setAppCacheEnabled(false);
          webView.setScrollBarStyle(WebView.SCROLLBARS_INSIDE_INSET);
          webView.setVerticalScrollBarEnabled(false);
          webView.setOnKeyListener(this);
          webView.getSettings().setJavaScriptEnabled(true);
          int fontSize = PreferenceManager.getsInstance(getActivity()).getSharedPrefs().getInt(PreferenceManager.PreferenceKeys.SETTINGS_CURRENT_FONT_SIZE, -1);
          switch (fontSize) {
              case 0: //LARGE
                  webView.getSettings().setTextZoom(160);
                  break;
              case 1: // MEDIUM
                  webView.getSettings().setTextZoom(130);
                  break;
              case 2: //NORMAL
                  webView.getSettings().setTextZoom(100);
                  break;
              case 3: //SMALL
                  webView.getSettings().setTextZoom(70);
                  break;
              default:
                  webView.getSettings().setTextZoom(100);
          }
  
          return view;
      }
  
      @Override
      public void onActivityCreated(Bundle savedInstanceState) {
          super.onActivityCreated(savedInstanceState);
          if (Network.isConnected(getActivity())) {
              RecyclerView relatedRecyclerView = (RecyclerView) getView().findViewById(R.id.related_article);
              RecyclerView recommendationRecyclerView = (RecyclerView) getView().findViewById(R.id.recommendation_view);
              RelativeLayout recommendationLayout = (RelativeLayout) getView().findViewById(R.id.recommendation);
              RelativeLayout relatedLayout = (RelativeLayout) getView().findViewById(R.id.related);
  
              webView.setWebViewClient(new WebClient(progressBar, recommendationLayout, relatedLayout));
              relatedRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity(), LinearLayoutManager.HORIZONTAL, false));
              relatedRecyclerView.setAdapter(relatedAdapter = new RelatedArticleListAdapter(getActivity(), relatedList, this));
  
              OBRequest request = new OBRequest(url, getResources().getString(R.string.outbrain_widget));
              Outbrain.fetchRecommendations(request, this);
              GridLayoutManager layoutManager = new GridLayoutManager(getActivity(), 2);
              recommendationRecyclerView.setLayoutManager(layoutManager);
              outbrainAdapter = new OutbrainAdapter(getActivity(), outbrainList, this);
              recommendationRecyclerView.setAdapter(outbrainAdapter);
  
              webView.loadUrl(url);
              String keywords = getArguments().getString(Constants.BundleKeys.KEYWORDS);
  
              if (keywords != null) {
                  String newsId = getArguments().getString(Constants.BundleKeys.NEWS_ID);
                  String url = ConfigManager.getsInstance().getURL(Constants.CustomApiType.RELATED_NEWS);
                  StringBuilder builder = new StringBuilder(url).append(&quot;&amp;&quot;).append(APIService.QueryKeys.EXCLUDE_ID)
                          .append(&quot;=&quot;).append(newsId)
                          .append(&quot;&amp;&quot;).append(APIService.QueryKeys.ALL_FIELDS).append(&quot;=&quot;)
                          .append(keywords);
                  NewsViewModel newsViewModel = new NewsViewModel(getActivity(), this, builder.toString());
                  newsViewModel.downloadRelatedNews();
              }
          } else {
              webView.setWebViewClient(new WebClient(progressBar));
              downloadCachedHTML(url);
          }
  
      }
  
      private void downloadCachedHTML(String url) {
          boolean isBookMarkNews = getArguments().getBoolean(Constants.BundleKeys.IS_BOOKMARK, false);
          HTMLClient client = HTMLClientFactory.create(getActivity(), isBookMarkNews ? CacheInfo.BOOKMARK_NEWS : CacheInfo.NEWS_DETAIL);
          HTMLAPIService apiService = client.getAPIService(HTMLAPIService.class);
          Call&lt;String&gt; call = apiService.downloadHtml(url);
          call.enqueue(new Callback&lt;String&gt;() {
              @Override
              public void onResponse(Call&lt;String&gt; call, retrofit2.Response&lt;String&gt; response) {
                  if (getActivity() == null)
                      return;
                  progressBar.setVisibility(View.GONE);
                  if (response.body() != null) {
                      webView.loadDataWithBaseURL(&quot;&quot;, response.body(), &quot;text/html&quot;, &quot;utf-8&quot;, null);
                  }
              }
  
              @Override
              public void onFailure(Call&lt;String&gt; call, Throwable t) {
                  progressBar.setVisibility(View.GONE);
              }
          });
      }
  
      @Override
      public void onItemClick(Object item, View v, int position) {
          if (item instanceof NewsItem) {
              News news = new News();
              news.newsList = relatedList;
              listItemListener.onNewsListItemClick(news, position, &quot;&quot;,  false);
          }
          if (item instanceof OBRecommendation)
              listItemListener.onRecommendationItemClick(((OBRecommendation) item).getUrl());
  
      }
  
      @Override
      public void onResponse(News response) {
          relatedList.clear();
          relatedList.addAll(response.newsList);
          relatedAdapter.notifyDataSetChanged();
      }
  
      @Override
      public void onNextResponse(News response) {
      }
  
      @Override
      public void onNextError() {
      }
  
      @Override
      public void onError() {
          relatedList.clear();
      }
  
      @Override
      public void setUserVisibleHint(boolean isVisibleToUser) {
          super.setUserVisibleHint(isVisibleToUser);
          if (getActivity() == null)
              return;
          if (webView == null)
              return;
          if (isVisibleToUser)
              webView.onResume();
          else webView.onPause();
  
      }
  
      @Override
      public void onPause() {
          super.onPause();
          webView.onPause();
          isWebViewPaused = true;
      }
  
      @Override
      public void onResume() {
          super.onResume();
          if (isWebViewPaused) {
              webView.onResume();
              isWebViewPaused = false;
          }
      }
  
      @Override
      public void onOutbrainRecommendationsSuccess(OBRecommendationsResponse recommendations) {
          outbrainList.clear();
          outbrainList.addAll(recommendations.getAll());
          outbrainAdapter.notifyDataSetChanged();
      }
  
      @Override
      public void onOutbrainRecommendationsFailure(Exception ex) {
          outbrainList.clear();
      }
  
  
      private class WebClient extends WebViewClient {
          private final ProgressBar progressBar;
          private RelativeLayout recommendation;
          private RelativeLayout related;
  
          public WebClient(ProgressBar progressBar, RelativeLayout recommendation, RelativeLayout related) {
              this.progressBar = progressBar;
              this.recommendation = recommendation;
              this.related = related;
  
          }
  
          public WebClient(ProgressBar progressBar) {
              this.progressBar = progressBar;
          }
  
          @Override
          public void onPageStarted(WebView view, String url, Bitmap favicon) {
              super.onPageStarted(view, url, favicon);
              progressBar.setVisibility(View.VISIBLE);
              if (Network.isConnected(getActivity())) {
                  recommendation.setVisibility(View.GONE);
                  related.setVisibility(View.GONE);
              }
          }
  
          @Override
          public void onPageFinished(WebView view, String url) {
              super.onPageFinished(view, url);
              progressBar.setVisibility(View.GONE);
              if (Network.isConnected(getActivity())) {
                  related.setVisibility(relatedList.isEmpty() ? View.GONE : View.VISIBLE);
                  recommendation.setVisibility(outbrainList.isEmpty() ? View.GONE : View.VISIBLE);
              }
          }
  
          @SuppressWarnings(&quot;deprecation&quot;)
          @Override
          public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
              if (!Network.isConnected(getActivity())) {
                  WebResourceResponse response = getResponse(url);
                  return response == null ? super.shouldInterceptRequest(view, url) : response;
              }
              return super.shouldInterceptRequest(view, url);
          }
  
          @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
          @Override
          public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
              if (!Network.isConnected(getActivity())) {
                  String url = request.getUrl().toString();
                  WebResourceResponse response = getResponse(url);
                  return response == null ? super.shouldInterceptRequest(view, request) : response;
  
              }
              return super.shouldInterceptRequest(view, request);
          }
  
          @Nullable
          private WebResourceResponse getResponse(String url) {
              if (url.endsWith(&quot;.png&quot;) || url.endsWith(&quot;.jpg&quot;)) {
                  boolean isBookMarkNews = getArguments().getBoolean(Constants.BundleKeys.IS_BOOKMARK, false);
                  HTMLClient client = HTMLClientFactory.create(getActivity(), isBookMarkNews ? CacheInfo.BOOKMARK_NEWS : CacheInfo.NEWS_DETAIL);
                  File cachedFile = new File(client.getImageDir() + File.separator + HTMLInterceptor.getFileName(url));
                  if (cachedFile.exists()) {
                      try {
                          return new WebResourceResponse(
                                  &quot;image/*&quot;, &quot;utf-8&quot;, new FileInputStream(cachedFile));
                      } catch (FileNotFoundException e) {
                          e.printStackTrace();
                      }
                  }
              }
              return null;
          }
  
          @Override
          public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
              if (Network.isConnected(progressBar.getContext()))
                  return false;
              else return true;
          }
  
          @Override
          public boolean shouldOverrideUrlLoading(WebView view, String url) {
              return super.shouldOverrideUrlLoading(view, url);
          }
      }
  
  
      @Override
      public boolean onKey(View v, int keyCode, KeyEvent event) {
          if (event.getAction() == KeyEvent.ACTION_DOWN) {
              WebView webView = (WebView) v;
              switch (keyCode) {
                  case KeyEvent.KEYCODE_BACK:
                      if (webView.canGoBack()) {
                          webView.goBack();
                          return true;
                      }
                      break;
              }
          }
          return false;
  
      }
  
      @Override
      public void onDestroyView() {
          super.onDestroyView();
          webView.destroy();
      }
  }
  </code></pre>