am 97808b86: Merge "better scrolling in JS-less single-message conversation view" into jb-ub-mail-ur9
* commit '97808b864982d9b1bf81ba7e56162d73bc2357ea':
better scrolling in JS-less single-message conversation view
diff --git a/res/layout/secure_conversation_view.xml b/res/layout/secure_conversation_view.xml
index da1dae3..26b4920 100644
--- a/res/layout/secure_conversation_view.xml
+++ b/res/layout/secure_conversation_view.xml
@@ -18,7 +18,7 @@
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
- <ScrollView android:id="@+id/scroll_view"
+ <com.android.mail.browse.MessageScrollView android:id="@+id/scroll_view"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
@@ -37,18 +37,18 @@
android:layout_height="wrap_content"
android:layout_below="@id/conv_header" />
<!-- base WebView layer -->
- <WebView
+ <com.android.mail.browse.MessageWebView
android:id="@+id/webview"
android:layout_width="match_parent"
android:layout_height="0dp"
- android:layout_weight="1.0"/>
+ android:layout_weight="1.0" />
<include layout="@layout/conversation_message_footer"
android:id="@+id/message_footer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone" />
</LinearLayout>
- </ScrollView>
+ </com.android.mail.browse.MessageScrollView>
<include layout="@layout/conversation_load_spinner"/>
diff --git a/src/com/android/mail/browse/MessageScrollView.java b/src/com/android/mail/browse/MessageScrollView.java
new file mode 100644
index 0000000..250fbd0
--- /dev/null
+++ b/src/com/android/mail/browse/MessageScrollView.java
@@ -0,0 +1,122 @@
+/*
+ * 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;
+ }
+
+}
diff --git a/src/com/android/mail/browse/MessageWebView.java b/src/com/android/mail/browse/MessageWebView.java
new file mode 100644
index 0000000..253a16b
--- /dev/null
+++ b/src/com/android/mail/browse/MessageWebView.java
@@ -0,0 +1,61 @@
+/*
+ * 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.webkit.WebView;
+
+import com.android.mail.utils.LogUtils;
+
+/**
+ * A WebView designed to live within a {@link MessageScrollView}.
+ */
+public class MessageWebView extends WebView implements MessageScrollView.Touchable {
+
+ private boolean mTouched;
+
+ public MessageWebView(Context c) {
+ this(c, null);
+ }
+
+ public MessageWebView(Context c, AttributeSet attrs) {
+ super(c, attrs);
+ }
+
+ @Override
+ public boolean wasTouched() {
+ return mTouched;
+ }
+
+ @Override
+ public void clearTouched() {
+ mTouched = false;
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ mTouched = true;
+ final boolean handled = super.onTouchEvent(event);
+ LogUtils.d(MessageScrollView.LOG_TAG,"OUT WebView.onTouch, returning handled=%s ev=%s",
+ handled, event);
+ return handled;
+ }
+
+}
diff --git a/src/com/android/mail/ui/SecureConversationViewFragment.java b/src/com/android/mail/ui/SecureConversationViewFragment.java
index eebec55..12b7f00 100644
--- a/src/com/android/mail/ui/SecureConversationViewFragment.java
+++ b/src/com/android/mail/ui/SecureConversationViewFragment.java
@@ -39,6 +39,8 @@
import com.android.mail.browse.MessageFooterView;
import com.android.mail.browse.MessageHeaderView;
import com.android.mail.browse.MessageHeaderView.MessageHeaderViewCallbacks;
+import com.android.mail.browse.MessageScrollView;
+import com.android.mail.browse.MessageWebView;
import com.android.mail.providers.Account;
import com.android.mail.providers.Conversation;
import com.android.mail.providers.Message;
@@ -50,12 +52,12 @@
public class SecureConversationViewFragment extends AbstractConversationViewFragment implements
MessageHeaderViewCallbacks {
private static final String LOG_TAG = LogTag.getLogTag();
- private WebView mWebView;
+ private MessageWebView mWebView;
private ConversationViewHeader mConversationHeaderView;
private MessageHeaderView mMessageHeaderView;
private MessageFooterView mMessageFooterView;
private ConversationMessage mMessage;
- private ScrollView mScrollView;
+ private MessageScrollView mScrollView;
private final WebViewClient mWebViewClient = new AbstractConversationWebViewClient() {
@Override
@@ -113,12 +115,12 @@
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.secure_conversation_view, container, false);
- mScrollView = (ScrollView) rootView.findViewById(R.id.scroll_view);
+ mScrollView = (MessageScrollView) rootView.findViewById(R.id.scroll_view);
mConversationHeaderView = (ConversationViewHeader) rootView.findViewById(R.id.conv_header);
mMessageHeaderView = (MessageHeaderView) rootView.findViewById(R.id.message_header);
mMessageFooterView = (MessageFooterView) rootView.findViewById(R.id.message_footer);
instantiateProgressIndicators(rootView);
- mWebView = (WebView) rootView.findViewById(R.id.webview);
+ mWebView = (MessageWebView) rootView.findViewById(R.id.webview);
mWebView.setWebViewClient(mWebViewClient);
mWebView.setFocusable(false);
final WebSettings settings = mWebView.getSettings();
@@ -130,6 +132,8 @@
settings.setBuiltInZoomControls(true);
settings.setDisplayZoomControls(false);
+ mScrollView.setInnerScrollableView(mWebView);
+
return rootView;
}