blob: 9e5cefd7b13c655c10837b7ce1d8bcaafbfed13e [file] [log] [blame]
Jorim Jaggid7daab72014-05-06 22:22:20 +02001/*
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.phone;
18
19import android.content.Context;
20import android.util.AttributeSet;
Jorim Jaggice50b812014-05-24 16:29:57 +020021import android.view.MotionEvent;
Jorim Jaggid7daab72014-05-06 22:22:20 +020022import android.view.View;
23import android.widget.ScrollView;
24
25/**
26 * A scroll view which can be observed for scroll change events.
27 */
28public class ObservableScrollView extends ScrollView {
29
30 private Listener mListener;
Jorim Jaggifc1a8242014-05-12 19:30:05 +020031 private int mLastOverscrollAmount;
Jorim Jaggif62f2bb2014-05-25 22:28:41 +020032 private boolean mTouchEnabled = true;
Jorim Jaggi3f48f462014-07-08 16:53:29 +020033 private boolean mHandlingTouchEvent;
Jorim Jaggie0640dd2014-08-05 23:12:40 +020034 private float mLastX;
35 private float mLastY;
Jorim Jaggi11c071a2014-08-14 19:17:11 +020036 private boolean mBlockFlinging;
Selim Cinek311fc0b2014-09-25 13:55:01 +020037 private boolean mTouchCancelled;
Jorim Jaggid7daab72014-05-06 22:22:20 +020038
39 public ObservableScrollView(Context context, AttributeSet attrs) {
40 super(context, attrs);
41 }
42
43 public void setListener(Listener listener) {
44 mListener = listener;
45 }
46
Jorim Jaggif62f2bb2014-05-25 22:28:41 +020047 public void setTouchEnabled(boolean touchEnabled) {
48 mTouchEnabled = touchEnabled;
49 }
50
Jorim Jaggid7daab72014-05-06 22:22:20 +020051 public boolean isScrolledToBottom() {
52 return getScrollY() == getMaxScrollY();
53 }
54
Jorim Jaggi3f48f462014-07-08 16:53:29 +020055 public boolean isHandlingTouchEvent() {
56 return mHandlingTouchEvent;
Jorim Jaggice50b812014-05-24 16:29:57 +020057 }
58
Jorim Jaggid7daab72014-05-06 22:22:20 +020059 private int getMaxScrollY() {
60 int scrollRange = 0;
61 if (getChildCount() > 0) {
62 View child = getChildAt(0);
63 scrollRange = Math.max(0,
64 child.getHeight() - (getHeight() - mPaddingBottom - mPaddingTop));
65 }
66 return scrollRange;
67 }
68
69 @Override
Jorim Jaggi56306252014-07-03 00:40:09 +020070 public boolean onTouchEvent(MotionEvent ev) {
Jorim Jaggi3f48f462014-07-08 16:53:29 +020071 mHandlingTouchEvent = true;
Jorim Jaggie0640dd2014-08-05 23:12:40 +020072 mLastX = ev.getX();
73 mLastY = ev.getY();
Jorim Jaggi56306252014-07-03 00:40:09 +020074 boolean result = super.onTouchEvent(ev);
Jorim Jaggi3f48f462014-07-08 16:53:29 +020075 mHandlingTouchEvent = false;
Jorim Jaggi56306252014-07-03 00:40:09 +020076 return result;
77 }
78
79 @Override
80 public boolean onInterceptTouchEvent(MotionEvent ev) {
Jorim Jaggi3f48f462014-07-08 16:53:29 +020081 mHandlingTouchEvent = true;
Jorim Jaggie0640dd2014-08-05 23:12:40 +020082 mLastX = ev.getX();
83 mLastY = ev.getY();
Jorim Jaggi56306252014-07-03 00:40:09 +020084 boolean result = super.onInterceptTouchEvent(ev);
Jorim Jaggi3f48f462014-07-08 16:53:29 +020085 mHandlingTouchEvent = false;
Jorim Jaggi56306252014-07-03 00:40:09 +020086 return result;
87 }
88
89 @Override
Jorim Jaggice50b812014-05-24 16:29:57 +020090 public boolean dispatchTouchEvent(MotionEvent ev) {
Selim Cinek311fc0b2014-09-25 13:55:01 +020091 if (ev.getAction() == MotionEvent.ACTION_DOWN) {
92 if (!mTouchEnabled) {
93 mTouchCancelled = true;
94 return false;
95 }
96 mTouchCancelled = false;
97 } else if (mTouchCancelled) {
98 return false;
99 } else if (!mTouchEnabled) {
100 MotionEvent cancel = MotionEvent.obtain(ev);
101 cancel.setAction(MotionEvent.ACTION_CANCEL);
Adrian Roos5c82e342015-05-20 18:08:58 -0700102 super.dispatchTouchEvent(cancel);
Selim Cinek311fc0b2014-09-25 13:55:01 +0200103 cancel.recycle();
104 mTouchCancelled = true;
Jorim Jaggif62f2bb2014-05-25 22:28:41 +0200105 return false;
106 }
Jorim Jaggi3f48f462014-07-08 16:53:29 +0200107 return super.dispatchTouchEvent(ev);
Jorim Jaggice50b812014-05-24 16:29:57 +0200108 }
109
110 @Override
Jorim Jaggid7daab72014-05-06 22:22:20 +0200111 protected void onScrollChanged(int l, int t, int oldl, int oldt) {
112 super.onScrollChanged(l, t, oldl, oldt);
113 if (mListener != null) {
114 mListener.onScrollChanged();
115 }
116 }
117
Jorim Jaggifc1a8242014-05-12 19:30:05 +0200118 @Override
119 protected boolean overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY,
120 int scrollRangeX, int scrollRangeY, int maxOverScrollX, int maxOverScrollY,
121 boolean isTouchEvent) {
122 mLastOverscrollAmount = Math.max(0, scrollY + deltaY - getMaxScrollY());
123 return super.overScrollBy(deltaX, deltaY, scrollX, scrollY, scrollRangeX, scrollRangeY,
124 maxOverScrollX, maxOverScrollY, isTouchEvent);
125 }
126
Jorim Jaggi11c071a2014-08-14 19:17:11 +0200127 public void setBlockFlinging(boolean blockFlinging) {
128 mBlockFlinging = blockFlinging;
129 }
130
131 @Override
132 public void fling(int velocityY) {
133 if (!mBlockFlinging) {
134 super.fling(velocityY);
135 }
136 }
137
Jorim Jaggifc1a8242014-05-12 19:30:05 +0200138 @Override
139 protected void onOverScrolled(int scrollX, int scrollY, boolean clampedX, boolean clampedY) {
140 super.onOverScrolled(scrollX, scrollY, clampedX, clampedY);
141 if (mListener != null && mLastOverscrollAmount > 0) {
Jorim Jaggie0640dd2014-08-05 23:12:40 +0200142 mListener.onOverscrolled(mLastX, mLastY, mLastOverscrollAmount);
Jorim Jaggifc1a8242014-05-12 19:30:05 +0200143 }
144 }
145
Jorim Jaggid7daab72014-05-06 22:22:20 +0200146 public interface Listener {
147 void onScrollChanged();
Jorim Jaggie0640dd2014-08-05 23:12:40 +0200148 void onOverscrolled(float lastX, float lastY, int amount);
Jorim Jaggid7daab72014-05-06 22:22:20 +0200149 }
150}