1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.android.documentsui.dirlist;
17 
18 import static androidx.core.util.Preconditions.checkState;
19 import static com.android.documentsui.base.SharedMinimal.DEBUG;
20 import static com.android.documentsui.base.SharedMinimal.VERBOSE;
21 
22 import android.content.Context;
23 import android.os.Build;
24 import androidx.annotation.Nullable;
25 import androidx.recyclerview.widget.RecyclerView;
26 import androidx.recyclerview.widget.RecyclerView.OnItemTouchListener;
27 import android.util.Log;
28 import android.view.MotionEvent;
29 import android.view.ScaleGestureDetector;
30 
31 import com.android.documentsui.base.Features;
32 
33 import java.util.function.Consumer;
34 
35 /**
36  * Class providing support for gluing gesture scaling of the ui into RecyclerView + DocsUI.
37  */
38 final class ScaleHelper {
39 
40     private static final String TAG = "ScaleHelper";
41 
42     private final Context mContext;
43     private final Features mFeatures;
44     private final Consumer<Float> mScaleCallback;
45 
46     private @Nullable ScaleGestureDetector mScaleDetector;
47 
ScaleHelper(Context context, Features features, Consumer<Float> scaleCallback)48     public ScaleHelper(Context context, Features features, Consumer<Float> scaleCallback) {
49         mContext = context;
50         mFeatures = features;
51         mScaleCallback = scaleCallback;
52     }
53 
onInterceptTouchEvent(RecyclerView rv, MotionEvent e)54     private boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
55         // Checking feature is deferred to runtime so the feature can be enabled
56         // after this class has been setup.
57         if (mFeatures.isGestureScaleEnabled() && mScaleDetector != null) {
58             mScaleDetector.onTouchEvent(e);
59         }
60 
61         return false;
62     }
63 
attach(RecyclerView view)64     void attach(RecyclerView view) {
65         checkState(DEBUG);
66         checkState(mScaleDetector == null);
67 
68         mScaleDetector = new ScaleGestureDetector(
69             mContext,
70             new ScaleGestureDetector.SimpleOnScaleGestureListener() {
71                 @Override
72                 public boolean onScale(ScaleGestureDetector detector) {
73                     if (VERBOSE) Log.v(TAG,
74                             "Received scale event: " + detector.getScaleFactor());
75                     mScaleCallback.accept(detector.getScaleFactor());
76                     return true;
77                 }
78             });
79 
80         view.addOnItemTouchListener(
81                 new OnItemTouchListener() {
82                     @Override
83                     public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
84                         return ScaleHelper.this.onInterceptTouchEvent(rv, e);
85                     }
86 
87                     @Override
88                     public void onTouchEvent(RecyclerView rv, MotionEvent e) {}
89 
90                     @Override
91                     public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {}
92         });
93     }
94 }
95