1eedc67283a5a49dce86c625e54596dfdea9465a7Dianne Hackborn/*
2eedc67283a5a49dce86c625e54596dfdea9465a7Dianne Hackborn * Copyright (C) 2011 The Android Open Source Project
3eedc67283a5a49dce86c625e54596dfdea9465a7Dianne Hackborn *
4eedc67283a5a49dce86c625e54596dfdea9465a7Dianne Hackborn * Licensed under the Apache License, Version 2.0 (the "License");
5eedc67283a5a49dce86c625e54596dfdea9465a7Dianne Hackborn * you may not use this file except in compliance with the License.
6eedc67283a5a49dce86c625e54596dfdea9465a7Dianne Hackborn * You may obtain a copy of the License at
7eedc67283a5a49dce86c625e54596dfdea9465a7Dianne Hackborn *
8eedc67283a5a49dce86c625e54596dfdea9465a7Dianne Hackborn *      http://www.apache.org/licenses/LICENSE-2.0
9eedc67283a5a49dce86c625e54596dfdea9465a7Dianne Hackborn *
10eedc67283a5a49dce86c625e54596dfdea9465a7Dianne Hackborn * Unless required by applicable law or agreed to in writing, software
11eedc67283a5a49dce86c625e54596dfdea9465a7Dianne Hackborn * distributed under the License is distributed on an "AS IS" BASIS,
12eedc67283a5a49dce86c625e54596dfdea9465a7Dianne Hackborn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13eedc67283a5a49dce86c625e54596dfdea9465a7Dianne Hackborn * See the License for the specific language governing permissions and
14eedc67283a5a49dce86c625e54596dfdea9465a7Dianne Hackborn * limitations under the License.
15eedc67283a5a49dce86c625e54596dfdea9465a7Dianne Hackborn */
16eedc67283a5a49dce86c625e54596dfdea9465a7Dianne Hackborn
17eedc67283a5a49dce86c625e54596dfdea9465a7Dianne Hackbornpackage android.support.v4.view;
18eedc67283a5a49dce86c625e54596dfdea9465a7Dianne Hackborn
19a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyteimport android.content.Context;
20a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyteimport android.support.annotation.NonNull;
21a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyteimport android.support.v4.os.BuildCompat;
22a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyteimport android.util.Log;
23a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyteimport android.util.TypedValue;
24eedc67283a5a49dce86c625e54596dfdea9465a7Dianne Hackbornimport android.view.ViewConfiguration;
25eedc67283a5a49dce86c625e54596dfdea9465a7Dianne Hackborn
26a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyteimport java.lang.reflect.Method;
27a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte
28eedc67283a5a49dce86c625e54596dfdea9465a7Dianne Hackborn/**
297656308f9e4b25765d8105ab12c73b723d7f0c02Aurimas Liutikas * Helper for accessing features in {@link ViewConfiguration} in a backwards compatible fashion.
307656308f9e4b25765d8105ab12c73b723d7f0c02Aurimas Liutikas *
317656308f9e4b25765d8105ab12c73b723d7f0c02Aurimas Liutikas * @deprecated Use {@link ViewConfiguration} directly.
32eedc67283a5a49dce86c625e54596dfdea9465a7Dianne Hackborn */
337656308f9e4b25765d8105ab12c73b723d7f0c02Aurimas Liutikas@Deprecated
34c5847d13e40f5d52459f5c0dab32dc08f1a9a683Chris Banespublic final class ViewConfigurationCompat {
35a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte    private static final String TAG = "ViewConfigCompat";
36a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte
37a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte    private static Method sGetScaledScrollFactorMethod;
38a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte
39a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte    static {
40a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        if (android.os.Build.VERSION.SDK_INT >= 25 && !BuildCompat.isAtLeastO()) {
41a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte            try {
42a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte                sGetScaledScrollFactorMethod =
43a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte                        ViewConfiguration.class.getDeclaredMethod("getScaledScrollFactor");
44a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte            } catch (Exception e) {
45a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte                Log.i(TAG, "Could not find method getScaledScrollFactor() on ViewConfiguration");
46a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte            }
47a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        }
48a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte    }
49a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte
50eedc67283a5a49dce86c625e54596dfdea9465a7Dianne Hackborn    /**
51eedc67283a5a49dce86c625e54596dfdea9465a7Dianne Hackborn     * Call {@link ViewConfiguration#getScaledPagingTouchSlop()}.
52f185f104c4786740765e549d535f9ba1052f96ccKirill Grouchnikov     *
53f185f104c4786740765e549d535f9ba1052f96ccKirill Grouchnikov     * @deprecated Call {@link ViewConfiguration#getScaledPagingTouchSlop()} directly.
5417d15d92db2288bd27b8710c68e5bc1b9b5945f0Kirill Grouchnikov     * This method will be removed in a future release.
55eedc67283a5a49dce86c625e54596dfdea9465a7Dianne Hackborn     */
56f185f104c4786740765e549d535f9ba1052f96ccKirill Grouchnikov    @Deprecated
57eedc67283a5a49dce86c625e54596dfdea9465a7Dianne Hackborn    public static int getScaledPagingTouchSlop(ViewConfiguration config) {
58f185f104c4786740765e549d535f9ba1052f96ccKirill Grouchnikov        return config.getScaledPagingTouchSlop();
59eedc67283a5a49dce86c625e54596dfdea9465a7Dianne Hackborn    }
60b60cbcc22f5f5f0ed64a4b8afe70877b52c115c2Chris Banes
61b60cbcc22f5f5f0ed64a4b8afe70877b52c115c2Chris Banes    /**
62b60cbcc22f5f5f0ed64a4b8afe70877b52c115c2Chris Banes     * Report if the device has a permanent menu key available to the user, in a backwards
63b60cbcc22f5f5f0ed64a4b8afe70877b52c115c2Chris Banes     * compatible way.
647656308f9e4b25765d8105ab12c73b723d7f0c02Aurimas Liutikas     *
657656308f9e4b25765d8105ab12c73b723d7f0c02Aurimas Liutikas     * @deprecated Use {@link ViewConfiguration#hasPermanentMenuKey()} directly.
66b60cbcc22f5f5f0ed64a4b8afe70877b52c115c2Chris Banes     */
677656308f9e4b25765d8105ab12c73b723d7f0c02Aurimas Liutikas    @Deprecated
68b60cbcc22f5f5f0ed64a4b8afe70877b52c115c2Chris Banes    public static boolean hasPermanentMenuKey(ViewConfiguration config) {
697656308f9e4b25765d8105ab12c73b723d7f0c02Aurimas Liutikas        return config.hasPermanentMenuKey();
70b60cbcc22f5f5f0ed64a4b8afe70877b52c115c2Chris Banes    }
71c5847d13e40f5d52459f5c0dab32dc08f1a9a683Chris Banes
72a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte    /**
73a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte     * @param config Used to get the scaling factor directly from the {@link ViewConfiguration}.
74a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte     * @param context Used to locate a resource value.
75a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte     *
76a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte     * @return Amount to scroll in response to a horizontal {@link MotionEventCompat#ACTION_SCROLL}
77a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte     *         event. Multiply this by the event's axis value to obtain the number of pixels to be
78a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte     *         scrolled.
79a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte     */
80a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte    public static float getScaledHorizontalScrollFactor(@NonNull ViewConfiguration config,
81a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte            @NonNull Context context) {
82a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        if (BuildCompat.isAtLeastO()) {
83a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte            return config.getScaledHorizontalScrollFactor();
84a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        } else {
85a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte            return getLegacyScrollFactor(config, context);
86a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        }
87a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte    }
88a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte
89a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte    /**
90a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte     * @param config Used to get the scaling factor directly from the {@link ViewConfiguration}.
91a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte     * @param context Used to locate a resource value.
92a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte     *
93a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte     * @return Amount to scroll in response to a vertical {@link MotionEventCompat#ACTION_SCROLL}
94a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte     *         event. Multiply this by the event's axis value to obtain the number of pixels to be
95a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte     *         scrolled.
96a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte     */
97a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte    public static float getScaledVerticalScrollFactor(@NonNull ViewConfiguration config,
98a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte            @NonNull Context context) {
99a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        if (BuildCompat.isAtLeastO()) {
100a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte            return config.getScaledVerticalScrollFactor();
101a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        } else {
102a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte            return getLegacyScrollFactor(config, context);
103a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        }
104a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte    }
105a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte
106a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte    private static float getLegacyScrollFactor(ViewConfiguration config, Context context) {
107a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        if (android.os.Build.VERSION.SDK_INT >= 25 && sGetScaledScrollFactorMethod != null) {
108a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte            try {
109a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte                return (int) sGetScaledScrollFactorMethod.invoke(config);
110a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte            } catch (Exception e) {
111a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte                Log.i(TAG, "Could not find method getScaledScrollFactor() on ViewConfiguration");
112a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte            }
113a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        }
114a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        // Fall back to pre-API-25 behavior.
115a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        TypedValue outValue = new TypedValue();
116a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        if (context.getTheme().resolveAttribute(
117a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte                android.R.attr.listPreferredItemHeight, outValue, true)) {
118a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte            return outValue.getDimension(context.getResources().getDisplayMetrics());
119a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        }
120a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte        return 0;
121a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte    }
122a1f3f663034d903cb1a7036defa79bf462fca61cAaron Whyte
123c5847d13e40f5d52459f5c0dab32dc08f1a9a683Chris Banes    private ViewConfigurationCompat() {}
124eedc67283a5a49dce86c625e54596dfdea9465a7Dianne Hackborn}
125