DragDownHelper.java revision ecbab3662d4474bbb45477939aaa167eb883212b
1ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi/*
2ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi * Copyright (C) 2014 The Android Open Source Project
3ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi *
4ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi * Licensed under the Apache License, Version 2.0 (the "License");
5ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi * you may not use this file except in compliance with the License.
6ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi * You may obtain a copy of the License at
7ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi *
8ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi *      http://www.apache.org/licenses/LICENSE-2.0
9ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi *
10ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi * Unless required by applicable law or agreed to in writing, software
11ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi * distributed under the License is distributed on an "AS IS" BASIS,
12ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi * See the License for the specific language governing permissions and
14ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi * limitations under the License
15ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi */
16ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi
17ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggipackage com.android.systemui.statusbar;
18ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi
19ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggiimport android.content.Context;
20ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggiimport android.util.ArraySet;
21ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggiimport android.view.MotionEvent;
22ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggiimport android.view.View;
23ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggiimport android.view.ViewConfiguration;
24ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi
25ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggiimport com.android.systemui.ExpandHelper;
26ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggiimport com.android.systemui.Gefingerpoken;
27ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggiimport com.android.systemui.R;
28ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi
29ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggiimport java.util.HashSet;
30ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi
31ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi/**
32ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi * A utility class to enable the downward swipe on the lockscreen to go to the full shade and expand
33ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi * the notification where the drag started.
34ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi */
35ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggipublic class DragDownHelper implements Gefingerpoken {
36ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi
37ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi    private int mMinDragDistance;
38ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi    private ExpandHelper.Callback mCallback;
39ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi    private float mInitialTouchX;
40ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi    private float mInitialTouchY;
41ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi    private boolean mDraggingDown;
42ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi    private float mTouchSlop;
43ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi    private OnDragDownListener mOnDragDownListener;
44ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi    private View mHost;
45ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi    private final int[] mTemp2 = new int[2];
46ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi    private final ArraySet<View> mHoveredChildren = new ArraySet<View>();
47ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi    private boolean mDraggedFarEnough;
48ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi    private View mStartingChild;
49ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi
50ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi    public DragDownHelper(Context context, View host, ExpandHelper.Callback callback,
51ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi            OnDragDownListener onDragDownListener) {
52ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi        mMinDragDistance = context.getResources().getDimensionPixelSize(
53ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi                R.dimen.keyguard_drag_down_min_distance);
54ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
55ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi        mCallback = callback;
56ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi        mOnDragDownListener = onDragDownListener;
57ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi        mHost = host;
58ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi    }
59ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi
60ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi    @Override
61ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi    public boolean onInterceptTouchEvent(MotionEvent event) {
62ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi        final float x = event.getX();
63ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi        final float y = event.getY();
64ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi
65ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi        switch (event.getActionMasked()) {
66ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi            case MotionEvent.ACTION_DOWN:
67ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi                mHoveredChildren.clear();
68ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi                mDraggedFarEnough = false;
69ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi                mDraggingDown = false;
70ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi                mStartingChild = null;
71ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi                mInitialTouchY = y;
72ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi                mInitialTouchX = x;
73ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi                break;
74ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi
75ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi            case MotionEvent.ACTION_MOVE:
76ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi                final float h = y - mInitialTouchY;
77ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi                if (h > mTouchSlop && h > Math.abs(x - mInitialTouchX)) {
78ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi                    mDraggingDown = true;
79ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi                    mInitialTouchY = y;
80ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi                    mInitialTouchX = x;
81ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi                    return true;
82ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi                }
83ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi                break;
84ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi        }
85ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi        return false;
86ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi    }
87ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi
88ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi    @Override
89ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi    public boolean onTouchEvent(MotionEvent event) {
90ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi        if (!mDraggingDown) {
91ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi            return false;
92ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi        }
93ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi        final float x = event.getX();
94ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi        final float y = event.getY();
95ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi
96ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi        switch (event.getActionMasked()) {
97ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi            case MotionEvent.ACTION_MOVE:
98ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi                final float h = y - mInitialTouchY;
99ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi                View child = findView(x, y);
100ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi                if (child != null) {
101ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi                    hoverChild(findView(x, y));
102ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi                }
103ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi                if (h > mMinDragDistance) {
104ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi                    if (!mDraggedFarEnough) {
105ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi                        mDraggedFarEnough = true;
106ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi                        mOnDragDownListener.onThresholdReached();
107ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi                    }
108ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi                } else {
109ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi                    if (mDraggedFarEnough) {
110ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi                        mDraggedFarEnough = false;
111ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi                        mOnDragDownListener.onReset();
112ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi                    }
113ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi                }
114ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi                return true;
115ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi            case MotionEvent.ACTION_UP:
116ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi                if (mDraggedFarEnough) {
117ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi                    mOnDragDownListener.onDraggedDown(mStartingChild);
118ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi                } else {
119ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi                    stopDragging();
120ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi                    return false;
121ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi                }
122ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi                break;
123ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi            case MotionEvent.ACTION_CANCEL:
124ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi                stopDragging();
125ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi                return false;
126ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi        }
127ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi        return false;
128ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi    }
129ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi
130ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi    private void stopDragging() {
131ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi        mDraggingDown = false;
132ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi        mOnDragDownListener.onReset();
133ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi    }
134ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi
135ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi    private void hoverChild(View child) {
136ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi        if (mHoveredChildren.isEmpty()) {
137ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi            mStartingChild = child;
138ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi        }
139ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi        if (!mHoveredChildren.contains(child)) {
140ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi            mOnDragDownListener.onHover(child);
141ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi            mHoveredChildren.add(child);
142ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi        }
143ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi    }
144ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi
145ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi    private View findView(float x, float y) {
146ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi        mHost.getLocationOnScreen(mTemp2);
147ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi        x += mTemp2[0];
148ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi        y += mTemp2[1];
149ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi        return mCallback.getChildAtRawPosition(x, y);
150ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi    }
151ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi
152ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi    public interface OnDragDownListener {
153ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi        void onHover(View child);
154ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi        void onDraggedDown(View startingChild);
155ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi        void onReset();
156ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi        void onThresholdReached();
157ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi    }
158ecbab3662d4474bbb45477939aaa167eb883212bJorim Jaggi}
159