Adjust ViewDragHelper to better support watches.

ViewDragHelper hard-codes the edge size to 20dp for all devices.
On watches, this is too small. Watches should define the edge size
as a percentage of the screen height. This introduces a new method
ViewDragHelper.refreshEdgeSize() to calculate the edge size. For
phones, this will continue being 20dp, but for watches edge size
will be calculated.

Change-Id: I2d8521fab702d447b63b8508634230a5699e1a43
diff --git a/v4/java/android/support/v4/widget/ViewDragHelper.java b/v4/java/android/support/v4/widget/ViewDragHelper.java
index 3f4e571..867d326 100644
--- a/v4/java/android/support/v4/widget/ViewDragHelper.java
+++ b/v4/java/android/support/v4/widget/ViewDragHelper.java
@@ -18,6 +18,7 @@
 package android.support.v4.widget;
 
 import android.content.Context;
+import android.content.res.Configuration;
 import android.support.v4.view.MotionEventCompat;
 import android.support.v4.view.VelocityTrackerCompat;
 import android.support.v4.view.ViewCompat;
@@ -101,6 +102,12 @@
     public static final int DIRECTION_ALL = DIRECTION_HORIZONTAL | DIRECTION_VERTICAL;
 
     private static final int EDGE_SIZE = 20; // dp
+    /**
+     * Ratio to calculate the edge size on watch devices. This is bounded by
+     * {@link #WATCH_MAX_EDGE_SIZE}.
+     */
+    private static final float WATCH_EDGE_SIZE_RATIO = .2f;
+    private static final int WATCH_MAX_EDGE_SIZE = 48; // dp
 
     private static final int BASE_SETTLE_DURATION = 256; // ms
     private static final int MAX_SETTLE_DURATION = 600; // ms
@@ -138,6 +145,9 @@
 
     private final ViewGroup mParentView;
 
+    private final float mDisplayDensity;
+    private final boolean mIsUiModeTypeWatch;
+
     /**
      * A Callback is used as a communication channel with the ViewDragHelper back to the
      * parent view using it. <code>on*</code>methods are invoked on siginficant events and several
@@ -381,10 +391,12 @@
         mParentView = forParent;
         mCallback = cb;
 
-        final ViewConfiguration vc = ViewConfiguration.get(context);
-        final float density = context.getResources().getDisplayMetrics().density;
-        mEdgeSize = (int) (EDGE_SIZE * density + 0.5f);
+        mDisplayDensity = context.getResources().getDisplayMetrics().density;
+        mIsUiModeTypeWatch = (context.getResources().getConfiguration().uiMode
+                & Configuration.UI_MODE_TYPE_MASK) == Configuration.UI_MODE_TYPE_WATCH;
+        refreshEdgeSize();
 
+        final ViewConfiguration vc = ViewConfiguration.get(context);
         mTouchSlop = vc.getScaledTouchSlop();
         mMaxVelocity = vc.getScaledMaximumFlingVelocity();
         mMinVelocity = vc.getScaledMinimumFlingVelocity();
@@ -449,6 +461,21 @@
     }
 
     /**
+     * Refreshes the edge size. This can be used if the edge size should change depending on the
+     * size of the {@link ViewGroup}. A good time to call this method is during
+     * {@link View#onSizeChanged()}.
+     */
+    public void refreshEdgeSize() {
+        if (mIsUiModeTypeWatch) {
+            int edgeSizePx = (int) (WATCH_EDGE_SIZE_RATIO * mParentView.getHeight());
+            int maxEdgeSizePx = (int) (WATCH_MAX_EDGE_SIZE * mDisplayDensity);
+            mEdgeSize = Math.min(edgeSizePx, maxEdgeSizePx);
+        } else {
+            mEdgeSize = (int) (EDGE_SIZE * mDisplayDensity + 0.5f);
+        }
+    }
+
+    /**
      * Capture a specific child view for dragging within the parent. The callback will be notified
      * but {@link Callback#tryCaptureView(android.view.View, int)} will not be asked permission to
      * capture this view.
@@ -1479,4 +1506,4 @@
 
         return result;
     }
-}
\ No newline at end of file
+}