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