10ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam/* 20ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam * Copyright (C) 2017 The Android Open Source Project 30ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam * 40ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam * Licensed under the Apache License, Version 2.0 (the "License"); 50ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam * you may not use this file except in compliance with the License. 60ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam * You may obtain a copy of the License at 70ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam * 80ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam * http://www.apache.org/licenses/LICENSE-2.0 90ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam * 100ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam * Unless required by applicable law or agreed to in writing, software 110ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam * distributed under the License is distributed on an "AS IS" BASIS, 120ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 130ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam * See the License for the specific language governing permissions and 140ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam * limitations under the License. 150ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam */ 160ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam 170ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lampackage com.android.setupwizardlib.template; 180ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam 190ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lamimport android.support.annotation.NonNull; 200ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lamimport android.support.annotation.Nullable; 210ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lamimport android.support.v7.widget.RecyclerView; 220ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lamimport android.util.Log; 230ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam 240ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lamimport com.android.setupwizardlib.template.RequireScrollMixin.ScrollHandlingDelegate; 250ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam 260ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam/** 270ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam * {@link ScrollHandlingDelegate} which analyzes scroll events from {@link RecyclerView} and 280ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam * notifies {@link RequireScrollMixin} about scrollability changes. 290ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam */ 300ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lampublic class RecyclerViewScrollHandlingDelegate implements ScrollHandlingDelegate { 310ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam 320ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam private static final String TAG = "RVRequireScrollMixin"; 330ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam 340ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam @Nullable 350ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam private final RecyclerView mRecyclerView; 360ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam 370ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam @NonNull 380ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam private final RequireScrollMixin mRequireScrollMixin; 390ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam 400ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam public RecyclerViewScrollHandlingDelegate( 410ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam @NonNull RequireScrollMixin requireScrollMixin, 420ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam @Nullable RecyclerView recyclerView) { 430ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam mRequireScrollMixin = requireScrollMixin; 440ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam mRecyclerView = recyclerView; 450ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam } 460ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam 470ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam private boolean canScrollDown() { 480ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam if (mRecyclerView != null) { 490ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam // Compatibility implementation of View#canScrollVertically 500ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam final int offset = mRecyclerView.computeVerticalScrollOffset(); 510ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam final int range = mRecyclerView.computeVerticalScrollRange() 520ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam - mRecyclerView.computeVerticalScrollExtent(); 530ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam return range != 0 && offset < range - 1; 540ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam } 550ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam return false; 560ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam } 570ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam 580ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam @Override 590ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam public void startListening() { 600ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam if (mRecyclerView != null) { 610ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { 620ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam @Override 630ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam public void onScrolled(RecyclerView recyclerView, int dx, int dy) { 640ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam mRequireScrollMixin.notifyScrollabilityChange(canScrollDown()); 650ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam } 660ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam }); 670ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam 680ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam if (canScrollDown()) { 690ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam mRequireScrollMixin.notifyScrollabilityChange(true); 700ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam } 710ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam } else { 720ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam Log.w(TAG, "Cannot require scroll. Recycler view is null."); 730ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam } 740ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam } 750ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam 760ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam @Override 770ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam public void pageScrollDown() { 780ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam if (mRecyclerView != null) { 790ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam final int height = mRecyclerView.getHeight(); 800ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam mRecyclerView.smoothScrollBy(0, height); 810ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam } 820ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam } 830ceb8d53e39ebb5bc103863787afb39ec5c41ad8Maurice Lam} 84