blob: 250fbd0fcf960a308e87fe7065a9125aefcd99ab [file] [log] [blame]
/*
* Copyright (C) 2013 Google Inc.
* Licensed to The Android Open Source Project.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.mail.browse;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.ScrollView;
import com.android.mail.utils.LogUtils;
/**
* A container that tries to play nice with an internally scrollable {@link Touchable} child view.
* The assumption is that the child view can scroll horizontally, but not vertically, so any
* touch events on that child view should ALSO be sent here so it can simultaneously vertically
* scroll (not the standard either/or behavior).
* <p>
* Touch events on any other child of this ScrollView are intercepted in the standard fashion.
*/
public class MessageScrollView extends ScrollView {
/**
* A View that reports whether onTouchEvent() was recently called.
*/
public interface Touchable {
boolean wasTouched();
void clearTouched();
}
/**
* True when performing "special" interception.
*/
private boolean mWantToIntercept;
/**
* Whether to perform the standard touch interception procedure. This is set to true when we
* want to intercept a touch stream from any child OTHER than {@link #mTouchableChild}.
*/
private boolean mInterceptNormally;
/**
* The special child that we want to NOT intercept from in the normal way. Instead, this child
* will continue to receive the touch event stream (so it can handle the horizontal component)
* while this parent will additionally handle the events to perform vertical scrolling.
*/
private Touchable mTouchableChild;
public static final String LOG_TAG = "MsgScroller";
public MessageScrollView(Context c) {
this(c, null);
}
public MessageScrollView(Context c, AttributeSet attrs) {
super(c, attrs);
}
public void setInnerScrollableView(Touchable child) {
mTouchableChild = child;
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
if (mInterceptNormally) {
LogUtils.d(LOG_TAG, "IN ScrollView.onIntercept, NOW stealing. ev=%s", ev);
return true;
} else if (mWantToIntercept) {
LogUtils.d(LOG_TAG, "IN ScrollView.onIntercept, already stealing. ev=%s", ev);
return false;
}
mWantToIntercept = super.onInterceptTouchEvent(ev);
LogUtils.d(LOG_TAG, "OUT ScrollView.onIntercept, steal=%s ev=%s", mWantToIntercept, ev);
return false;
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
final int action = ev.getActionMasked();
switch (action) {
case MotionEvent.ACTION_DOWN:
LogUtils.d(LOG_TAG, "IN ScrollView.dispatchTouch, clearing flags");
mWantToIntercept = false;
mInterceptNormally = false;
break;
}
if (mTouchableChild != null) {
mTouchableChild.clearTouched();
}
final boolean handled = super.dispatchTouchEvent(ev);
LogUtils.d(LOG_TAG, "OUT ScrollView.dispatchTouch, handled=%s ev=%s", handled, ev);
if (mWantToIntercept) {
final boolean touchedChild = (mTouchableChild != null && mTouchableChild.wasTouched());
if (touchedChild) {
// also give the event to this scroll view if the WebView got the event
// and didn't stop any parent interception
LogUtils.d(LOG_TAG, "IN extra ScrollView.onTouch, ev=%s", ev);
onTouchEvent(ev);
} else {
mInterceptNormally = true;
mWantToIntercept = false;
}
}
return handled;
}
}