Home | History | Annotate | Download | only in view
      1 /*
      2  * Copyright 2018 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 
     17 package androidx.core.view;
     18 
     19 import android.content.Context;
     20 import android.content.res.Resources;
     21 import android.os.Build;
     22 import android.util.Log;
     23 import android.util.TypedValue;
     24 import android.view.ViewConfiguration;
     25 
     26 import androidx.annotation.NonNull;
     27 
     28 import java.lang.reflect.Method;
     29 
     30 /**
     31  * Helper for accessing features in {@link ViewConfiguration}.
     32  */
     33 public final class ViewConfigurationCompat {
     34     private static final String TAG = "ViewConfigCompat";
     35 
     36     private static Method sGetScaledScrollFactorMethod;
     37 
     38     static {
     39         if (Build.VERSION.SDK_INT == 25) {
     40             try {
     41                 sGetScaledScrollFactorMethod =
     42                         ViewConfiguration.class.getDeclaredMethod("getScaledScrollFactor");
     43             } catch (Exception e) {
     44                 Log.i(TAG, "Could not find method getScaledScrollFactor() on ViewConfiguration");
     45             }
     46         }
     47     }
     48 
     49     /**
     50      * Call {@link ViewConfiguration#getScaledPagingTouchSlop()}.
     51      *
     52      * @deprecated Call {@link ViewConfiguration#getScaledPagingTouchSlop()} directly.
     53      * This method will be removed in a future release.
     54      */
     55     @Deprecated
     56     public static int getScaledPagingTouchSlop(ViewConfiguration config) {
     57         return config.getScaledPagingTouchSlop();
     58     }
     59 
     60     /**
     61      * Report if the device has a permanent menu key available to the user, in a backwards
     62      * compatible way.
     63      *
     64      * @deprecated Use {@link ViewConfiguration#hasPermanentMenuKey()} directly.
     65      */
     66     @Deprecated
     67     public static boolean hasPermanentMenuKey(ViewConfiguration config) {
     68         return config.hasPermanentMenuKey();
     69     }
     70 
     71     /**
     72      * @param config Used to get the scaling factor directly from the {@link ViewConfiguration}.
     73      * @param context Used to locate a resource value.
     74      *
     75      * @return Amount to scroll in response to a horizontal {@link MotionEventCompat#ACTION_SCROLL}
     76      *         event. Multiply this by the event's axis value to obtain the number of pixels to be
     77      *         scrolled.
     78      */
     79     public static float getScaledHorizontalScrollFactor(@NonNull ViewConfiguration config,
     80             @NonNull Context context) {
     81         if (Build.VERSION.SDK_INT >= 26) {
     82             return config.getScaledHorizontalScrollFactor();
     83         } else {
     84             return getLegacyScrollFactor(config, context);
     85         }
     86     }
     87 
     88     /**
     89      * @param config Used to get the scaling factor directly from the {@link ViewConfiguration}.
     90      * @param context Used to locate a resource value.
     91      *
     92      * @return Amount to scroll in response to a vertical {@link MotionEventCompat#ACTION_SCROLL}
     93      *         event. Multiply this by the event's axis value to obtain the number of pixels to be
     94      *         scrolled.
     95      */
     96     public static float getScaledVerticalScrollFactor(@NonNull ViewConfiguration config,
     97             @NonNull Context context) {
     98         if (Build.VERSION.SDK_INT >= 26) {
     99             return config.getScaledVerticalScrollFactor();
    100         } else {
    101             return getLegacyScrollFactor(config, context);
    102         }
    103     }
    104 
    105     private static float getLegacyScrollFactor(ViewConfiguration config, Context context) {
    106         if (android.os.Build.VERSION.SDK_INT >= 25 && sGetScaledScrollFactorMethod != null) {
    107             try {
    108                 return (int) sGetScaledScrollFactorMethod.invoke(config);
    109             } catch (Exception e) {
    110                 Log.i(TAG, "Could not find method getScaledScrollFactor() on ViewConfiguration");
    111             }
    112         }
    113         // Fall back to pre-API-25 behavior.
    114         TypedValue outValue = new TypedValue();
    115         if (context.getTheme().resolveAttribute(
    116                 android.R.attr.listPreferredItemHeight, outValue, true)) {
    117             return outValue.getDimension(context.getResources().getDisplayMetrics());
    118         }
    119         return 0;
    120     }
    121 
    122     /**
    123      * @param config Used to get the hover slop directly from the {@link ViewConfiguration}.
    124      *
    125      * @return The hover slop value.
    126      */
    127     public static int getScaledHoverSlop(ViewConfiguration config) {
    128         if (android.os.Build.VERSION.SDK_INT >= 28) {
    129             return config.getScaledHoverSlop();
    130         }
    131         return config.getScaledTouchSlop() / 2;
    132     }
    133 
    134     /**
    135      * Check if shortcuts should be displayed in menus.
    136      *
    137      * @return {@code True} if shortcuts should be displayed in menus.
    138      */
    139     public static boolean shouldShowMenuShortcutsWhenKeyboardPresent(ViewConfiguration config,
    140             @NonNull Context context) {
    141         if (android.os.Build.VERSION.SDK_INT >= 28) {
    142             return config.shouldShowMenuShortcutsWhenKeyboardPresent();
    143         }
    144         final Resources res = context.getResources();
    145         final int platformResId = res.getIdentifier(
    146                 "config_showMenuShortcutsWhenKeyboardPresent", "bool", "android");
    147         return platformResId != 0 && res.getBoolean(platformResId);
    148     }
    149 
    150     private ViewConfigurationCompat() {}
    151 }
    152