blob: d40dbad893fdb2e4c0e6b230f343059380a91a99 [file] [log] [blame]
Jeff Sharkey3f177592009-05-18 15:23:12 -07001/*
2 * Copyright (C) 2009 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.contacts;
18
19import android.content.Context;
20import android.content.res.TypedArray;
21import android.util.AttributeSet;
22import android.view.MotionEvent;
23import android.view.ViewConfiguration;
24import android.widget.FrameLayout;
25
26/**
27 * Lightweight view that wraps around an existing view, watching and capturing
28 * sliding gestures from the left or right edges within a given tolerance.
29 */
30public class EdgeTriggerView extends FrameLayout {
31 public static final int FLAG_NONE = 0x00;
32 public static final int FLAG_LEFT = 0x01;
33 public static final int FLAG_RIGHT = 0x02;
34
35 private int mTouchSlop;
36
37 private int mEdgeWidth;
38 private int mListenEdges;
39
40 private boolean mListenLeft = false;
41 private boolean mListenRight = false;
42
43 private MotionEvent mDownStart;
44 private int mEdge = FLAG_NONE;
45
46 public static interface EdgeTriggerListener {
47 public void onTrigger(float downX, float downY, int edge);
48 }
49
50 private EdgeTriggerListener mListener;
51
52 /**
53 * Add a {@link EdgeTriggerListener} to watch for edge events.
54 */
55 public void setOnEdgeTriggerListener(EdgeTriggerListener listener) {
56 mListener = listener;
57 }
58
59 public EdgeTriggerView(Context context) {
60 this(context, null);
61 }
62
63 public EdgeTriggerView(Context context, AttributeSet attrs) {
64 this(context, attrs, 0);
65 }
66
67 public EdgeTriggerView(Context context, AttributeSet attrs, int defStyle) {
68 super(context, attrs, defStyle);
69
70 setClickable(true);
71
72 mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
73
74 // TODO: enable reading these values again once we move away from symlinks
75// TypedArray a = context.obtainStyledAttributes(attrs,
76// R.styleable.EdgeTriggerView, defStyle, -1);
77// mEdgeWidth = a.getDimensionPixelSize(R.styleable.EdgeTriggerView_edgeWidth, mTouchSlop);
78// mListenEdges = a.getInt(R.styleable.EdgeTriggerView_listenEdges, FLAG_LEFT);
79
80 mEdgeWidth = 80;
81 mListenEdges = FLAG_LEFT;
82
83 mListenLeft = (mListenEdges & FLAG_LEFT) == FLAG_LEFT;
84 mListenRight = (mListenEdges & FLAG_RIGHT) == FLAG_RIGHT;
85 }
86
87 /** {@inheritDoc} */
88 @Override
89 public boolean onInterceptTouchEvent(MotionEvent event) {
90 switch (event.getAction()) {
91 case MotionEvent.ACTION_DOWN: {
92 // Consider watching this touch event based on listening flags
93 final float x = event.getX();
94 if (mListenLeft && x < mEdgeWidth) {
95 mEdge = FLAG_LEFT;
96 } else if (mListenRight && x > getWidth() - mEdgeWidth) {
97 mEdge = FLAG_RIGHT;
98 } else {
99 mEdge = FLAG_NONE;
100 }
101
102 if (mEdge != FLAG_NONE) {
103 mDownStart = MotionEvent.obtain(event);
104 } else {
105 mDownStart = null;
106 }
107 break;
108 }
109 case MotionEvent.ACTION_MOVE: {
110 if (mEdge != FLAG_NONE) {
111 // If moved far enough, capture touch event for ourselves
112 float delta = event.getX() - mDownStart.getX();
113 if (mEdge == FLAG_LEFT && delta > mTouchSlop) {
114 return true;
115 } else if (mEdge == FLAG_RIGHT && delta < -mTouchSlop) {
116 return true;
117 }
118 }
119 break;
120 }
121 }
122
123 // Otherwise let the event slip through to children
124 return false;
125 }
126
127 /** {@inheritDoc} */
128 @Override
129 public boolean onTouchEvent(MotionEvent event) {
130 // Pass trigger event to listener and return true to consume
131 if (mEdge != FLAG_NONE && mListener != null) {
132 mListener.onTrigger(mDownStart.getX(), mDownStart.getY(), mEdge);
133
134 // Reset values so we don't sent twice
135 mEdge = FLAG_NONE;
136 mDownStart = null;
137 }
138 return true;
139 }
140}