OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 package org.chromium.chrome.browser.banners; | 5 package org.chromium.chrome.browser.banners; |
6 | 6 |
7 import android.animation.Animator; | 7 import android.animation.Animator; |
8 import android.animation.AnimatorListenerAdapter; | 8 import android.animation.AnimatorListenerAdapter; |
9 import android.animation.AnimatorSet; | 9 import android.animation.AnimatorSet; |
10 import android.animation.ObjectAnimator; | 10 import android.animation.ObjectAnimator; |
11 import android.animation.PropertyValuesHolder; | 11 import android.animation.PropertyValuesHolder; |
12 import android.content.Context; | 12 import android.content.Context; |
13 import android.util.AttributeSet; | 13 import android.util.AttributeSet; |
14 import android.view.GestureDetector; | 14 import android.view.GestureDetector; |
15 import android.view.GestureDetector.SimpleOnGestureListener; | 15 import android.view.GestureDetector.SimpleOnGestureListener; |
16 import android.view.Gravity; | 16 import android.view.Gravity; |
17 import android.view.MotionEvent; | 17 import android.view.MotionEvent; |
18 import android.view.View; | 18 import android.view.View; |
19 import android.view.ViewGroup; | 19 import android.view.ViewGroup; |
20 import android.view.animation.DecelerateInterpolator; | 20 import android.view.animation.DecelerateInterpolator; |
21 import android.view.animation.Interpolator; | 21 import android.view.animation.Interpolator; |
22 import android.widget.FrameLayout; | 22 import android.widget.FrameLayout; |
| 23 import android.widget.ScrollView; |
23 | 24 |
| 25 import org.chromium.chrome.browser.EmptyTabObserver; |
| 26 import org.chromium.chrome.browser.Tab; |
| 27 import org.chromium.chrome.browser.TabObserver; |
24 import org.chromium.content.browser.ContentViewCore; | 28 import org.chromium.content.browser.ContentViewCore; |
25 import org.chromium.content_public.browser.GestureStateListener; | 29 import org.chromium.content_public.browser.GestureStateListener; |
26 import org.chromium.ui.UiUtils; | 30 import org.chromium.ui.UiUtils; |
27 | 31 |
28 /** | 32 /** |
29 * View that appears on the screen as the user scrolls on the page and can be sw
iped away. | 33 * View that appears on the screen as the user scrolls on the page and can be sw
iped away. |
30 * Meant to be tacked onto the {@link org.chromium.content.browser.ContentViewCo
re}'s view and | 34 * Meant to be tacked onto the {@link org.chromium.content.browser.ContentViewCo
re}'s view and |
31 * alerted when either the page scroll position or viewport size changes. | 35 * alerted when either the page scroll position or viewport size changes. |
32 * | 36 * |
33 * GENERAL BEHAVIOR | 37 * GENERAL BEHAVIOR |
(...skipping 26 matching lines...) Expand all Loading... |
60 * horizontally (with "enough" defined by the DISMISS_SWIPE_THRESHOLD AND DISMIS
S_FLING_THRESHOLD) | 64 * horizontally (with "enough" defined by the DISMISS_SWIPE_THRESHOLD AND DISMIS
S_FLING_THRESHOLD) |
61 * triggers an animation that removes the View from the hierarchy. Failing to m
eet the threshold | 65 * triggers an animation that removes the View from the hierarchy. Failing to m
eet the threshold |
62 * will result in the View being translated back to the center of the screen. | 66 * will result in the View being translated back to the center of the screen. |
63 * | 67 * |
64 * Because the fling velocity handed in by Android is highly inaccurate and ofte
n indicates | 68 * Because the fling velocity handed in by Android is highly inaccurate and ofte
n indicates |
65 * that a fling is moving in an opposite direction than expected, the scroll dir
ection is tracked | 69 * that a fling is moving in an opposite direction than expected, the scroll dir
ection is tracked |
66 * to determine which direction the user was dragging the View when the fling wa
s initiated. When a | 70 * to determine which direction the user was dragging the View when the fling wa
s initiated. When a |
67 * fling is completed, the more forgiving FLING_THRESHOLD is used to determine h
ow far a user must | 71 * fling is completed, the more forgiving FLING_THRESHOLD is used to determine h
ow far a user must |
68 * swipe to dismiss the View rather than try to use the fling velocity. | 72 * swipe to dismiss the View rather than try to use the fling velocity. |
69 */ | 73 */ |
70 public abstract class SwipableOverlayView extends FrameLayout { | 74 public abstract class SwipableOverlayView extends ScrollView { |
71 private static final float ALPHA_THRESHOLD = 0.25f; | 75 private static final float ALPHA_THRESHOLD = 0.25f; |
72 private static final float DISMISS_SWIPE_THRESHOLD = 0.75f; | 76 private static final float DISMISS_SWIPE_THRESHOLD = 0.75f; |
73 private static final float FULL_THRESHOLD = 0.5f; | 77 private static final float FULL_THRESHOLD = 0.5f; |
74 private static final float VERTICAL_FLING_SHOW_THRESHOLD = 0.2f; | 78 private static final float VERTICAL_FLING_SHOW_THRESHOLD = 0.2f; |
75 private static final float VERTICAL_FLING_HIDE_THRESHOLD = 0.9f; | 79 private static final float VERTICAL_FLING_HIDE_THRESHOLD = 0.9f; |
| 80 private static final long REATTACH_FADE_IN_MS = 250; |
76 protected static final float ZERO_THRESHOLD = 0.001f; | 81 protected static final float ZERO_THRESHOLD = 0.001f; |
77 | 82 |
78 private static final int GESTURE_NONE = 0; | 83 private static final int GESTURE_NONE = 0; |
79 private static final int GESTURE_SCROLLING = 1; | 84 private static final int GESTURE_SCROLLING = 1; |
80 private static final int GESTURE_FLINGING = 2; | 85 private static final int GESTURE_FLINGING = 2; |
81 | 86 |
82 private static final int DRAGGED_LEFT = -1; | 87 private static final int DRAGGED_LEFT = -1; |
83 private static final int DRAGGED_CANCEL = 0; | 88 private static final int DRAGGED_CANCEL = 0; |
84 private static final int DRAGGED_RIGHT = 1; | 89 private static final int DRAGGED_RIGHT = 1; |
85 | 90 |
86 protected static final long MS_ANIMATION_DURATION = 250; | 91 protected static final long MS_ANIMATION_DURATION = 250; |
87 private static final long MS_DISMISS_FLING_THRESHOLD = MS_ANIMATION_DURATION
* 2; | 92 private static final long MS_DISMISS_FLING_THRESHOLD = MS_ANIMATION_DURATION
* 2; |
88 private static final long MS_SLOW_DISMISS = MS_ANIMATION_DURATION * 3; | 93 private static final long MS_SLOW_DISMISS = MS_ANIMATION_DURATION * 3; |
89 | 94 |
| 95 /** Resets the state of the SwipableOverlayView, as needed. */ |
| 96 protected class SwipableOverlayViewTabObserver extends EmptyTabObserver { |
| 97 @Override |
| 98 public void onDidNavigateMainFrame(Tab tab, String url, String baseUrl, |
| 99 boolean isNavigationToDifferentPage, boolean isFragmentNavigatio
n, |
| 100 int statusCode) { |
| 101 setDoStayInvisible(false); |
| 102 } |
| 103 } |
| 104 |
90 // Detects when the user is dragging the View. | 105 // Detects when the user is dragging the View. |
91 private final GestureDetector mGestureDetector; | 106 private final GestureDetector mGestureDetector; |
92 | 107 |
93 // Detects when the user is dragging the ContentViewCore. | 108 // Detects when the user is dragging the ContentViewCore. |
94 private final GestureStateListener mGestureStateListener; | 109 private final GestureStateListener mGestureStateListener; |
95 | 110 |
| 111 // Listens for changes in the layout. |
| 112 private final View.OnLayoutChangeListener mLayoutChangeListener; |
| 113 |
96 // Monitors for animation completions and resets the state. | 114 // Monitors for animation completions and resets the state. |
97 private final AnimatorListenerAdapter mAnimatorListenerAdapter; | 115 private final AnimatorListenerAdapter mAnimatorListenerAdapter; |
98 | 116 |
99 // Interpolator used for the animation. | 117 // Interpolator used for the animation. |
100 private final Interpolator mInterpolator; | 118 private final Interpolator mInterpolator; |
101 | 119 |
| 120 // Observes the Tab. |
| 121 private final TabObserver mTabObserver; |
| 122 |
102 // Tracks whether the user is scrolling or flinging. | 123 // Tracks whether the user is scrolling or flinging. |
103 private int mGestureState; | 124 private int mGestureState; |
104 | 125 |
105 // Animation currently being used to translate the View. | 126 // Animation currently being used to translate the View. |
106 private AnimatorSet mCurrentAnimation; | 127 private AnimatorSet mCurrentAnimation; |
107 | 128 |
108 // Direction the user is horizontally dragging. | 129 // Direction the user is horizontally dragging. |
109 private int mDragDirection; | 130 private int mDragDirection; |
110 | 131 |
111 // How quickly the user is horizontally dragging. | 132 // How quickly the user is horizontally dragging. |
(...skipping 16 matching lines...) Expand all Loading... |
128 | 149 |
129 // Whether or not the View ever been fully displayed. | 150 // Whether or not the View ever been fully displayed. |
130 private boolean mIsBeingDisplayedForFirstTime; | 151 private boolean mIsBeingDisplayedForFirstTime; |
131 | 152 |
132 // Whether or not the View has been, or is being, dismissed. | 153 // Whether or not the View has been, or is being, dismissed. |
133 private boolean mIsDismissed; | 154 private boolean mIsDismissed; |
134 | 155 |
135 // The ContentViewCore to which the overlay is added. | 156 // The ContentViewCore to which the overlay is added. |
136 private ContentViewCore mContentViewCore; | 157 private ContentViewCore mContentViewCore; |
137 | 158 |
| 159 // Keeps the View from becoming visible when it normally would. |
| 160 private boolean mDoStayInvisible; |
| 161 |
| 162 // Whether the View should be allowed to be swiped away. |
| 163 private boolean mIsSwipable = true; |
| 164 |
138 /** | 165 /** |
139 * Creates a SwipableOverlayView. | 166 * Creates a SwipableOverlayView. |
140 * @param context Context for acquiring resources. | 167 * @param context Context for acquiring resources. |
141 * @param attrs Attributes from the XML layout inflation. | 168 * @param attrs Attributes from the XML layout inflation. |
142 */ | 169 */ |
143 public SwipableOverlayView(Context context, AttributeSet attrs) { | 170 public SwipableOverlayView(Context context, AttributeSet attrs) { |
144 super(context, attrs); | 171 super(context, attrs); |
145 SimpleOnGestureListener gestureListener = createGestureListener(); | 172 SimpleOnGestureListener gestureListener = createGestureListener(); |
146 mGestureDetector = new GestureDetector(context, gestureListener); | 173 mGestureDetector = new GestureDetector(context, gestureListener); |
147 mGestureStateListener = createGestureStateListener(); | 174 mGestureStateListener = createGestureStateListener(); |
148 mGestureState = GESTURE_NONE; | 175 mGestureState = GESTURE_NONE; |
| 176 mLayoutChangeListener = createLayoutChangeListener(); |
149 mAnimatorListenerAdapter = createAnimatorListenerAdapter(); | 177 mAnimatorListenerAdapter = createAnimatorListenerAdapter(); |
150 mInterpolator = new DecelerateInterpolator(1.0f); | 178 mInterpolator = new DecelerateInterpolator(1.0f); |
| 179 mTabObserver = createTabObserver(); |
151 } | 180 } |
152 | 181 |
153 /** | 182 /** |
154 * Adds this View to the given ContentViewCore's view. | 183 * Indicates whether the View should be allowed to be swiped away. |
155 * @param layout Layout to add this View to. | 184 * @param swipable Whether the View is reacts to horizontal gestures. |
156 */ | 185 */ |
157 protected void addToView(ContentViewCore contentViewCore) { | 186 protected void setIsSwipable(boolean swipable) { |
158 assert mContentViewCore == null; | 187 mIsSwipable = swipable; |
159 mContentViewCore = contentViewCore; | |
160 contentViewCore.getContainerView().addView(this, 0, createLayoutParams()
); | |
161 contentViewCore.addGestureStateListener(mGestureStateListener); | |
162 | |
163 // Listen for the layout to know when to animate the View coming onto th
e screen. | |
164 addOnLayoutChangeListener(createLayoutChangeListener()); | |
165 } | 188 } |
166 | 189 |
167 /** | 190 /** |
| 191 * Watches the given ContentViewCore for scrolling changes. |
| 192 */ |
| 193 public void setContentViewCore(ContentViewCore contentViewCore) { |
| 194 if (mContentViewCore != null) { |
| 195 mContentViewCore.removeGestureStateListener(mGestureStateListener); |
| 196 } |
| 197 |
| 198 mContentViewCore = contentViewCore; |
| 199 if (mContentViewCore != null) { |
| 200 mContentViewCore.addGestureStateListener(mGestureStateListener); |
| 201 } |
| 202 } |
| 203 |
| 204 public void addToParentView(ViewGroup parentView) { |
| 205 if (parentView != null && parentView.indexOfChild(this) == -1) { |
| 206 parentView.addView(this, createLayoutParams()); |
| 207 |
| 208 // Listen for the layout to know when to animate the View coming ont
o the screen. |
| 209 addOnLayoutChangeListener(mLayoutChangeListener); |
| 210 } |
| 211 } |
| 212 |
| 213 /** |
| 214 * Removes the SwipableOverlayView from its parent and stops monitoring the
ContentViewCore. |
| 215 * @return Whether the View was removed from its parent. |
| 216 */ |
| 217 public boolean removeFromParentView() { |
| 218 if (getParent() == null) return false; |
| 219 |
| 220 ((ViewGroup) getParent()).removeView(this); |
| 221 removeOnLayoutChangeListener(mLayoutChangeListener); |
| 222 return true; |
| 223 } |
| 224 |
| 225 /** |
168 * Creates a set of LayoutParams that makes the View hug the bottom of the s
creen. Override it | 226 * Creates a set of LayoutParams that makes the View hug the bottom of the s
creen. Override it |
169 * for other types of behavior. | 227 * for other types of behavior. |
170 * @return LayoutParams for use when adding the View to its parent. | 228 * @return LayoutParams for use when adding the View to its parent. |
171 */ | 229 */ |
172 protected ViewGroup.MarginLayoutParams createLayoutParams() { | 230 public ViewGroup.MarginLayoutParams createLayoutParams() { |
173 return new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutPar
ams.WRAP_CONTENT, | 231 return new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutPar
ams.WRAP_CONTENT, |
174 Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL); | 232 Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL); |
175 } | 233 } |
176 | 234 |
177 /** | 235 /** |
178 * Removes the View from its parent. | 236 * Call with {@code true} when a higher priority bottom element is visible t
o keep the View |
| 237 * from ever becoming visible. Call with {@code false} to restore normal vi
sibility behavior. |
| 238 * @param doStayInvisible Whether the View should stay invisible even when t
hey would |
| 239 * normally become visible. |
179 */ | 240 */ |
180 boolean removeFromParent() { | 241 public void setDoStayInvisible(boolean doStayInvisible) { |
181 if (mContentViewCore != null) { | 242 mDoStayInvisible = doStayInvisible; |
182 mContentViewCore.getContainerView().removeView(this); | 243 } |
183 mContentViewCore = null; | 244 |
184 return true; | 245 @Override |
| 246 protected void onAttachedToWindow() { |
| 247 super.onAttachedToWindow(); |
| 248 if (!mDoStayInvisible) { |
| 249 ObjectAnimator.ofFloat(this, "alpha", 0.f, 1.f).setDuration(REATTACH
_FADE_IN_MS) |
| 250 .start(); |
| 251 setVisibility(VISIBLE); |
185 } | 252 } |
186 return false; | |
187 } | 253 } |
188 | 254 |
189 /** | 255 /** |
| 256 * @return TabObserver that can be used to monitor a Tab. |
| 257 */ |
| 258 protected TabObserver createTabObserver() { |
| 259 return new SwipableOverlayViewTabObserver(); |
| 260 } |
| 261 |
| 262 /** |
| 263 * @return TabObserver that is used to monitor a Tab. |
| 264 */ |
| 265 public TabObserver getTabObserver() { |
| 266 return mTabObserver; |
| 267 } |
| 268 |
| 269 /** |
190 * See {@link #android.view.ViewGroup.onLayout(boolean, int, int, int, int)}
. | 270 * See {@link #android.view.ViewGroup.onLayout(boolean, int, int, int, int)}
. |
191 */ | 271 */ |
192 @Override | 272 @Override |
193 protected void onLayout(boolean changed, int l, int t, int r, int b) { | 273 protected void onLayout(boolean changed, int l, int t, int r, int b) { |
194 // Hide the View when the keyboard is showing. | 274 // Hide the View when the keyboard is showing. |
195 boolean keyboardIsShowing = UiUtils.isKeyboardShowing(getContext(), this
); | 275 boolean isShowing = (getVisibility() == View.VISIBLE); |
196 setVisibility(keyboardIsShowing ? INVISIBLE : VISIBLE); | 276 if (UiUtils.isKeyboardShowing(getContext(), this)) { |
| 277 if (isShowing) { |
| 278 setVisibility(View.INVISIBLE); |
| 279 } |
| 280 } else { |
| 281 if (!isShowing && !mDoStayInvisible) { |
| 282 setVisibility(View.VISIBLE); |
| 283 } |
| 284 } |
197 | 285 |
198 // Update the viewport height when the parent View's height changes (e.g
. after rotation). | 286 // Update the viewport height when the parent View's height changes (e.g
. after rotation). |
199 int currentParentHeight = getParent() == null ? 0 : ((View) getParent())
.getHeight(); | 287 int currentParentHeight = getParent() == null ? 0 : ((View) getParent())
.getHeight(); |
200 if (mParentHeight != currentParentHeight) { | 288 if (mParentHeight != currentParentHeight) { |
201 mParentHeight = currentParentHeight; | 289 mParentHeight = currentParentHeight; |
202 mGestureState = GESTURE_NONE; | 290 mGestureState = GESTURE_NONE; |
203 if (mCurrentAnimation != null) mCurrentAnimation.end(); | 291 if (mCurrentAnimation != null) mCurrentAnimation.end(); |
204 } | 292 } |
205 | 293 |
206 // Update the known effective height of the View. | 294 // Update the known effective height of the View. |
207 mTotalHeight = getMeasuredHeight(); | 295 mTotalHeight = getMeasuredHeight(); |
208 if (getLayoutParams() instanceof MarginLayoutParams) { | 296 if (getLayoutParams() instanceof MarginLayoutParams) { |
209 MarginLayoutParams params = (MarginLayoutParams) getLayoutParams(); | 297 MarginLayoutParams params = (MarginLayoutParams) getLayoutParams(); |
210 mTotalHeight += params.topMargin + params.bottomMargin; | 298 mTotalHeight += params.topMargin + params.bottomMargin; |
211 } | 299 } |
212 | 300 |
213 super.onLayout(changed, l, t, r, b); | 301 super.onLayout(changed, l, t, r, b); |
214 } | 302 } |
215 | 303 |
216 /** | 304 /** |
217 * See {@link #android.view.View.onTouchEvent(MotionEvent)}. | 305 * See {@link #android.view.View.onTouchEvent(MotionEvent)}. |
218 */ | 306 */ |
219 @Override | 307 @Override |
220 public boolean onTouchEvent(MotionEvent event) { | 308 public boolean onTouchEvent(MotionEvent event) { |
| 309 if (!mIsSwipable) return false; |
| 310 |
221 if (mGestureDetector.onTouchEvent(event)) return true; | 311 if (mGestureDetector.onTouchEvent(event)) return true; |
222 if (mCurrentAnimation != null) return true; | 312 if (mCurrentAnimation != null) return true; |
223 | 313 |
224 int action = event.getActionMasked(); | 314 int action = event.getActionMasked(); |
225 if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANC
EL) { | 315 if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANC
EL) { |
226 onFinishHorizontalGesture(); | 316 onFinishHorizontalGesture(); |
227 return true; | 317 return true; |
228 } | 318 } |
229 return false; | 319 return false; |
230 } | 320 } |
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
384 | 474 |
385 /** | 475 /** |
386 * Creates a listener that is used only to animate the View coming onto the
screen. | 476 * Creates a listener that is used only to animate the View coming onto the
screen. |
387 * @return The SimpleOnGestureListener that will monitor the View. | 477 * @return The SimpleOnGestureListener that will monitor the View. |
388 */ | 478 */ |
389 private View.OnLayoutChangeListener createLayoutChangeListener() { | 479 private View.OnLayoutChangeListener createLayoutChangeListener() { |
390 return new View.OnLayoutChangeListener() { | 480 return new View.OnLayoutChangeListener() { |
391 @Override | 481 @Override |
392 public void onLayoutChange(View v, int left, int top, int right, int
bottom, | 482 public void onLayoutChange(View v, int left, int top, int right, int
bottom, |
393 int oldLeft, int oldTop, int oldRight, int oldBottom) { | 483 int oldLeft, int oldTop, int oldRight, int oldBottom) { |
394 removeOnLayoutChangeListener(this); | 484 removeOnLayoutChangeListener(mLayoutChangeListener); |
395 | 485 |
396 // Animate the View coming in from the bottom of the screen. | 486 // Animate the View coming in from the bottom of the screen. |
397 setTranslationY(mTotalHeight); | 487 setTranslationY(mTotalHeight); |
398 mIsBeingDisplayedForFirstTime = true; | 488 mIsBeingDisplayedForFirstTime = true; |
399 createVerticalSnapAnimation(true); | 489 createVerticalSnapAnimation(true); |
400 mCurrentAnimation.start(); | 490 mCurrentAnimation.start(); |
401 } | 491 } |
402 }; | 492 }; |
403 } | 493 } |
404 | 494 |
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
553 } | 643 } |
554 | 644 |
555 /** | 645 /** |
556 * Creates an AnimatorListenerAdapter that cleans up after an animation is c
ompleted. | 646 * Creates an AnimatorListenerAdapter that cleans up after an animation is c
ompleted. |
557 * @return {@link AnimatorListenerAdapter} to use for animations. | 647 * @return {@link AnimatorListenerAdapter} to use for animations. |
558 */ | 648 */ |
559 private AnimatorListenerAdapter createAnimatorListenerAdapter() { | 649 private AnimatorListenerAdapter createAnimatorListenerAdapter() { |
560 return new AnimatorListenerAdapter() { | 650 return new AnimatorListenerAdapter() { |
561 @Override | 651 @Override |
562 public void onAnimationEnd(Animator animation) { | 652 public void onAnimationEnd(Animator animation) { |
563 if (mIsDismissed) removeFromParent(); | 653 if (mIsDismissed) removeFromParentView(); |
564 | 654 |
565 mGestureState = GESTURE_NONE; | 655 mGestureState = GESTURE_NONE; |
566 mCurrentAnimation = null; | 656 mCurrentAnimation = null; |
567 mIsBeingDisplayedForFirstTime = false; | 657 mIsBeingDisplayedForFirstTime = false; |
568 } | 658 } |
569 }; | 659 }; |
570 } | 660 } |
571 | 661 |
572 /** | 662 /** |
573 * Records the conditions of the page when a gesture is initiated. | 663 * Records the conditions of the page when a gesture is initiated. |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
606 /** | 696 /** |
607 * Called when the View has been clicked. | 697 * Called when the View has been clicked. |
608 */ | 698 */ |
609 protected abstract void onViewClicked(); | 699 protected abstract void onViewClicked(); |
610 | 700 |
611 /** | 701 /** |
612 * Called when the View needs to show that it's been pressed. | 702 * Called when the View needs to show that it's been pressed. |
613 */ | 703 */ |
614 protected abstract void onViewPressed(MotionEvent event); | 704 protected abstract void onViewPressed(MotionEvent event); |
615 } | 705 } |
OLD | NEW |