DragDownHelper.java revision ecbab3662d4474bbb45477939aaa167eb883212b
1/* 2 * Copyright (C) 2014 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 17package com.android.systemui.statusbar; 18 19import android.content.Context; 20import android.util.ArraySet; 21import android.view.MotionEvent; 22import android.view.View; 23import android.view.ViewConfiguration; 24 25import com.android.systemui.ExpandHelper; 26import com.android.systemui.Gefingerpoken; 27import com.android.systemui.R; 28 29import java.util.HashSet; 30 31/** 32 * A utility class to enable the downward swipe on the lockscreen to go to the full shade and expand 33 * the notification where the drag started. 34 */ 35public class DragDownHelper implements Gefingerpoken { 36 37 private int mMinDragDistance; 38 private ExpandHelper.Callback mCallback; 39 private float mInitialTouchX; 40 private float mInitialTouchY; 41 private boolean mDraggingDown; 42 private float mTouchSlop; 43 private OnDragDownListener mOnDragDownListener; 44 private View mHost; 45 private final int[] mTemp2 = new int[2]; 46 private final ArraySet<View> mHoveredChildren = new ArraySet<View>(); 47 private boolean mDraggedFarEnough; 48 private View mStartingChild; 49 50 public DragDownHelper(Context context, View host, ExpandHelper.Callback callback, 51 OnDragDownListener onDragDownListener) { 52 mMinDragDistance = context.getResources().getDimensionPixelSize( 53 R.dimen.keyguard_drag_down_min_distance); 54 mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop(); 55 mCallback = callback; 56 mOnDragDownListener = onDragDownListener; 57 mHost = host; 58 } 59 60 @Override 61 public boolean onInterceptTouchEvent(MotionEvent event) { 62 final float x = event.getX(); 63 final float y = event.getY(); 64 65 switch (event.getActionMasked()) { 66 case MotionEvent.ACTION_DOWN: 67 mHoveredChildren.clear(); 68 mDraggedFarEnough = false; 69 mDraggingDown = false; 70 mStartingChild = null; 71 mInitialTouchY = y; 72 mInitialTouchX = x; 73 break; 74 75 case MotionEvent.ACTION_MOVE: 76 final float h = y - mInitialTouchY; 77 if (h > mTouchSlop && h > Math.abs(x - mInitialTouchX)) { 78 mDraggingDown = true; 79 mInitialTouchY = y; 80 mInitialTouchX = x; 81 return true; 82 } 83 break; 84 } 85 return false; 86 } 87 88 @Override 89 public boolean onTouchEvent(MotionEvent event) { 90 if (!mDraggingDown) { 91 return false; 92 } 93 final float x = event.getX(); 94 final float y = event.getY(); 95 96 switch (event.getActionMasked()) { 97 case MotionEvent.ACTION_MOVE: 98 final float h = y - mInitialTouchY; 99 View child = findView(x, y); 100 if (child != null) { 101 hoverChild(findView(x, y)); 102 } 103 if (h > mMinDragDistance) { 104 if (!mDraggedFarEnough) { 105 mDraggedFarEnough = true; 106 mOnDragDownListener.onThresholdReached(); 107 } 108 } else { 109 if (mDraggedFarEnough) { 110 mDraggedFarEnough = false; 111 mOnDragDownListener.onReset(); 112 } 113 } 114 return true; 115 case MotionEvent.ACTION_UP: 116 if (mDraggedFarEnough) { 117 mOnDragDownListener.onDraggedDown(mStartingChild); 118 } else { 119 stopDragging(); 120 return false; 121 } 122 break; 123 case MotionEvent.ACTION_CANCEL: 124 stopDragging(); 125 return false; 126 } 127 return false; 128 } 129 130 private void stopDragging() { 131 mDraggingDown = false; 132 mOnDragDownListener.onReset(); 133 } 134 135 private void hoverChild(View child) { 136 if (mHoveredChildren.isEmpty()) { 137 mStartingChild = child; 138 } 139 if (!mHoveredChildren.contains(child)) { 140 mOnDragDownListener.onHover(child); 141 mHoveredChildren.add(child); 142 } 143 } 144 145 private View findView(float x, float y) { 146 mHost.getLocationOnScreen(mTemp2); 147 x += mTemp2[0]; 148 y += mTemp2[1]; 149 return mCallback.getChildAtRawPosition(x, y); 150 } 151 152 public interface OnDragDownListener { 153 void onHover(View child); 154 void onDraggedDown(View startingChild); 155 void onReset(); 156 void onThresholdReached(); 157 } 158} 159