ConversationWebView.java revision c1fb9a9c2730178105977fca629e80951bfc3cdc
1f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang/* 2f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang * Copyright (C) 2012 Google Inc. 3f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang * Licensed to The Android Open Source Project. 4f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang * 5f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang * Licensed under the Apache License, Version 2.0 (the "License"); 6f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang * you may not use this file except in compliance with the License. 7f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang * You may obtain a copy of the License at 8f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang * 9f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang * http://www.apache.org/licenses/LICENSE-2.0 10f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang * 11f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang * Unless required by applicable law or agreed to in writing, software 12f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang * distributed under the License is distributed on an "AS IS" BASIS, 13f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang * See the License for the specific language governing permissions and 15f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang * limitations under the License. 16f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang */ 17f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang 185ff63747a1b5c6e2197528972cbc3ba808b09d8dAndy Huangpackage com.android.mail.browse; 19f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang 20f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huangimport android.content.Context; 21afc9b365dc9199ee9b2a1e598b8f40b3c78b6d9fmindypimport android.content.res.Resources; 22afc9b365dc9199ee9b2a1e598b8f40b3c78b6d9fmindypimport android.graphics.Bitmap; 23afc9b365dc9199ee9b2a1e598b8f40b3c78b6d9fmindypimport android.graphics.Canvas; 24f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huangimport android.util.AttributeSet; 25bb56a1512559a5f024ba213c4bdcfe3d9d9387deAndy Huangimport android.view.MotionEvent; 2602f9d18a54072db8d86c524f9c09e508092ddd7cAndy Huangimport android.view.ScaleGestureDetector; 2702f9d18a54072db8d86c524f9c09e508092ddd7cAndy Huangimport android.view.ScaleGestureDetector.OnScaleGestureListener; 28f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang 2923014705ca9872cd5004a1aa76e83ae260165ecaAndy Huangimport com.android.mail.R; 30b334c9035e9b7a38766bb66c29da2208525d1e11Paul Westbrookimport com.android.mail.utils.LogTag; 31632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huangimport com.android.mail.utils.LogUtils; 32632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang 33f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huangimport java.util.Set; 34f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huangimport java.util.concurrent.CopyOnWriteArraySet; 35f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang 36c1fb9a9c2730178105977fca629e80951bfc3cdcAndy Huangpublic class ConversationWebView extends MailWebView implements ScrollNotifier { 37afc9b365dc9199ee9b2a1e598b8f40b3c78b6d9fmindyp /** The initial delay when rendering in hardware layer. */ 3830bcfe7b69f9d8e0cad2ee62dae9d3571cd0d88bAndy Huang private final int mWebviewInitialDelay; 39afc9b365dc9199ee9b2a1e598b8f40b3c78b6d9fmindyp 40afc9b365dc9199ee9b2a1e598b8f40b3c78b6d9fmindyp private Bitmap mBitmap; 41afc9b365dc9199ee9b2a1e598b8f40b3c78b6d9fmindyp private Canvas mCanvas; 42afc9b365dc9199ee9b2a1e598b8f40b3c78b6d9fmindyp 43afc9b365dc9199ee9b2a1e598b8f40b3c78b6d9fmindyp private boolean mUseSoftwareLayer; 4430bcfe7b69f9d8e0cad2ee62dae9d3571cd0d88bAndy Huang /** 4530bcfe7b69f9d8e0cad2ee62dae9d3571cd0d88bAndy Huang * Whether this view is user-visible; we don't bother doing supplemental software drawing 4630bcfe7b69f9d8e0cad2ee62dae9d3571cd0d88bAndy Huang * if the view is off-screen. 4730bcfe7b69f9d8e0cad2ee62dae9d3571cd0d88bAndy Huang */ 4830bcfe7b69f9d8e0cad2ee62dae9d3571cd0d88bAndy Huang private boolean mVisible; 49afc9b365dc9199ee9b2a1e598b8f40b3c78b6d9fmindyp 50afc9b365dc9199ee9b2a1e598b8f40b3c78b6d9fmindyp /** {@link Runnable} to be run when the page is rendered in hardware layer. */ 51afc9b365dc9199ee9b2a1e598b8f40b3c78b6d9fmindyp private final Runnable mNotifyPageRenderedInHardwareLayer = new Runnable() { 52afc9b365dc9199ee9b2a1e598b8f40b3c78b6d9fmindyp @Override 53afc9b365dc9199ee9b2a1e598b8f40b3c78b6d9fmindyp public void run() { 54afc9b365dc9199ee9b2a1e598b8f40b3c78b6d9fmindyp // Switch to hardware layer. 55afc9b365dc9199ee9b2a1e598b8f40b3c78b6d9fmindyp mUseSoftwareLayer = false; 56afc9b365dc9199ee9b2a1e598b8f40b3c78b6d9fmindyp destroyBitmap(); 57afc9b365dc9199ee9b2a1e598b8f40b3c78b6d9fmindyp invalidate(); 58afc9b365dc9199ee9b2a1e598b8f40b3c78b6d9fmindyp } 59afc9b365dc9199ee9b2a1e598b8f40b3c78b6d9fmindyp }; 60afc9b365dc9199ee9b2a1e598b8f40b3c78b6d9fmindyp 61afc9b365dc9199ee9b2a1e598b8f40b3c78b6d9fmindyp @Override 62afc9b365dc9199ee9b2a1e598b8f40b3c78b6d9fmindyp public void onDraw(Canvas canvas) { 63afc9b365dc9199ee9b2a1e598b8f40b3c78b6d9fmindyp // Always render in hardware layer to avoid flicker when switch. 64afc9b365dc9199ee9b2a1e598b8f40b3c78b6d9fmindyp super.onDraw(canvas); 65afc9b365dc9199ee9b2a1e598b8f40b3c78b6d9fmindyp 6630bcfe7b69f9d8e0cad2ee62dae9d3571cd0d88bAndy Huang // Render in software layer on top if needed, and we're visible (i.e. it's worthwhile to 6730bcfe7b69f9d8e0cad2ee62dae9d3571cd0d88bAndy Huang // do all this) 6830bcfe7b69f9d8e0cad2ee62dae9d3571cd0d88bAndy Huang if (mUseSoftwareLayer && mVisible && getWidth() > 0 && getHeight() > 0) { 6930bcfe7b69f9d8e0cad2ee62dae9d3571cd0d88bAndy Huang if (mBitmap == null) { 7030bcfe7b69f9d8e0cad2ee62dae9d3571cd0d88bAndy Huang try { 7130bcfe7b69f9d8e0cad2ee62dae9d3571cd0d88bAndy Huang // Create an offscreen bitmap. 7230bcfe7b69f9d8e0cad2ee62dae9d3571cd0d88bAndy Huang mBitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.RGB_565); 7330bcfe7b69f9d8e0cad2ee62dae9d3571cd0d88bAndy Huang mCanvas = new Canvas(mBitmap); 7430bcfe7b69f9d8e0cad2ee62dae9d3571cd0d88bAndy Huang } catch (OutOfMemoryError e) { 7530bcfe7b69f9d8e0cad2ee62dae9d3571cd0d88bAndy Huang // just give up 7630bcfe7b69f9d8e0cad2ee62dae9d3571cd0d88bAndy Huang mBitmap = null; 7730bcfe7b69f9d8e0cad2ee62dae9d3571cd0d88bAndy Huang mCanvas = null; 7830bcfe7b69f9d8e0cad2ee62dae9d3571cd0d88bAndy Huang mUseSoftwareLayer = false; 7930bcfe7b69f9d8e0cad2ee62dae9d3571cd0d88bAndy Huang } 8030bcfe7b69f9d8e0cad2ee62dae9d3571cd0d88bAndy Huang } 8130bcfe7b69f9d8e0cad2ee62dae9d3571cd0d88bAndy Huang 8230bcfe7b69f9d8e0cad2ee62dae9d3571cd0d88bAndy Huang if (mBitmap != null) { 8330bcfe7b69f9d8e0cad2ee62dae9d3571cd0d88bAndy Huang final int x = getScrollX(); 8430bcfe7b69f9d8e0cad2ee62dae9d3571cd0d88bAndy Huang final int y = getScrollY(); 8530bcfe7b69f9d8e0cad2ee62dae9d3571cd0d88bAndy Huang 8630bcfe7b69f9d8e0cad2ee62dae9d3571cd0d88bAndy Huang mCanvas.save(); 8730bcfe7b69f9d8e0cad2ee62dae9d3571cd0d88bAndy Huang mCanvas.translate(-x, -y); 8830bcfe7b69f9d8e0cad2ee62dae9d3571cd0d88bAndy Huang super.onDraw(mCanvas); 8930bcfe7b69f9d8e0cad2ee62dae9d3571cd0d88bAndy Huang mCanvas.restore(); 9030bcfe7b69f9d8e0cad2ee62dae9d3571cd0d88bAndy Huang 9130bcfe7b69f9d8e0cad2ee62dae9d3571cd0d88bAndy Huang canvas.drawBitmap(mBitmap, x, y, null /* paint */); 9230bcfe7b69f9d8e0cad2ee62dae9d3571cd0d88bAndy Huang } 93afc9b365dc9199ee9b2a1e598b8f40b3c78b6d9fmindyp } 94afc9b365dc9199ee9b2a1e598b8f40b3c78b6d9fmindyp } 95afc9b365dc9199ee9b2a1e598b8f40b3c78b6d9fmindyp 96afc9b365dc9199ee9b2a1e598b8f40b3c78b6d9fmindyp @Override 97afc9b365dc9199ee9b2a1e598b8f40b3c78b6d9fmindyp public void destroy() { 98afc9b365dc9199ee9b2a1e598b8f40b3c78b6d9fmindyp destroyBitmap(); 9930bcfe7b69f9d8e0cad2ee62dae9d3571cd0d88bAndy Huang removeCallbacks(mNotifyPageRenderedInHardwareLayer); 100afc9b365dc9199ee9b2a1e598b8f40b3c78b6d9fmindyp 101afc9b365dc9199ee9b2a1e598b8f40b3c78b6d9fmindyp super.destroy(); 102afc9b365dc9199ee9b2a1e598b8f40b3c78b6d9fmindyp } 103afc9b365dc9199ee9b2a1e598b8f40b3c78b6d9fmindyp 104afc9b365dc9199ee9b2a1e598b8f40b3c78b6d9fmindyp /** 105afc9b365dc9199ee9b2a1e598b8f40b3c78b6d9fmindyp * Destroys the {@link Bitmap} used for software layer. 106afc9b365dc9199ee9b2a1e598b8f40b3c78b6d9fmindyp */ 107afc9b365dc9199ee9b2a1e598b8f40b3c78b6d9fmindyp private void destroyBitmap() { 108afc9b365dc9199ee9b2a1e598b8f40b3c78b6d9fmindyp if (mBitmap != null) { 109afc9b365dc9199ee9b2a1e598b8f40b3c78b6d9fmindyp mBitmap = null; 11030bcfe7b69f9d8e0cad2ee62dae9d3571cd0d88bAndy Huang mCanvas = null; 111afc9b365dc9199ee9b2a1e598b8f40b3c78b6d9fmindyp } 112afc9b365dc9199ee9b2a1e598b8f40b3c78b6d9fmindyp } 113afc9b365dc9199ee9b2a1e598b8f40b3c78b6d9fmindyp 114afc9b365dc9199ee9b2a1e598b8f40b3c78b6d9fmindyp /** 115afc9b365dc9199ee9b2a1e598b8f40b3c78b6d9fmindyp * Enable this WebView to also draw to an internal software canvas until 11630bcfe7b69f9d8e0cad2ee62dae9d3571cd0d88bAndy Huang * {@link #onRenderComplete()} is called. The software draw will happen every time 117afc9b365dc9199ee9b2a1e598b8f40b3c78b6d9fmindyp * a normal {@link #onDraw(Canvas)} happens, and will overwrite whatever is normally drawn 118afc9b365dc9199ee9b2a1e598b8f40b3c78b6d9fmindyp * (i.e. drawn in hardware) with the results of software rendering. 119afc9b365dc9199ee9b2a1e598b8f40b3c78b6d9fmindyp * <p> 120afc9b365dc9199ee9b2a1e598b8f40b3c78b6d9fmindyp * This is useful when you know that the WebView draws sooner to a software layer than it does 121afc9b365dc9199ee9b2a1e598b8f40b3c78b6d9fmindyp * to its normal hardware layer. 122afc9b365dc9199ee9b2a1e598b8f40b3c78b6d9fmindyp */ 123afc9b365dc9199ee9b2a1e598b8f40b3c78b6d9fmindyp public void setUseSoftwareLayer(boolean useSoftware) { 124afc9b365dc9199ee9b2a1e598b8f40b3c78b6d9fmindyp mUseSoftwareLayer = useSoftware; 125afc9b365dc9199ee9b2a1e598b8f40b3c78b6d9fmindyp } 126afc9b365dc9199ee9b2a1e598b8f40b3c78b6d9fmindyp 127afc9b365dc9199ee9b2a1e598b8f40b3c78b6d9fmindyp /** 12830bcfe7b69f9d8e0cad2ee62dae9d3571cd0d88bAndy Huang * Notifies the {@link ConversationWebView} that it has become visible. It can use this signal 12930bcfe7b69f9d8e0cad2ee62dae9d3571cd0d88bAndy Huang * to switch between software and hardware layer. 130afc9b365dc9199ee9b2a1e598b8f40b3c78b6d9fmindyp */ 13130bcfe7b69f9d8e0cad2ee62dae9d3571cd0d88bAndy Huang public void onRenderComplete() { 13230bcfe7b69f9d8e0cad2ee62dae9d3571cd0d88bAndy Huang if (mUseSoftwareLayer) { 133afc9b365dc9199ee9b2a1e598b8f40b3c78b6d9fmindyp // Schedule to switch from software layer to hardware layer in 1s. 13430bcfe7b69f9d8e0cad2ee62dae9d3571cd0d88bAndy Huang postDelayed(mNotifyPageRenderedInHardwareLayer, mWebviewInitialDelay); 135afc9b365dc9199ee9b2a1e598b8f40b3c78b6d9fmindyp } 136afc9b365dc9199ee9b2a1e598b8f40b3c78b6d9fmindyp } 137f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang 13830bcfe7b69f9d8e0cad2ee62dae9d3571cd0d88bAndy Huang public void onUserVisibilityChanged(boolean visible) { 13930bcfe7b69f9d8e0cad2ee62dae9d3571cd0d88bAndy Huang mVisible = visible; 14030bcfe7b69f9d8e0cad2ee62dae9d3571cd0d88bAndy Huang } 14130bcfe7b69f9d8e0cad2ee62dae9d3571cd0d88bAndy Huang 14202f9d18a54072db8d86c524f9c09e508092ddd7cAndy Huang private ScaleGestureDetector mScaleDetector; 14302f9d18a54072db8d86c524f9c09e508092ddd7cAndy Huang 14423014705ca9872cd5004a1aa76e83ae260165ecaAndy Huang private final int mViewportWidth; 14523014705ca9872cd5004a1aa76e83ae260165ecaAndy Huang private final float mDensity; 14623014705ca9872cd5004a1aa76e83ae260165ecaAndy Huang 147f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang private final Set<ScrollListener> mScrollListeners = 148f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang new CopyOnWriteArraySet<ScrollListener>(); 149f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang 150632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang /** 151632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang * True when WebView is handling a touch-- in between POINTER_DOWN and 152632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang * POINTER_UP/POINTER_CANCEL. 153632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang */ 154632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang private boolean mHandlingTouch; 155ce8565b3605c2ce47c75e259f387cd4955f017daAndy Huang private boolean mIgnoringTouch; 156632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang 157b334c9035e9b7a38766bb66c29da2208525d1e11Paul Westbrook private static final String LOG_TAG = LogTag.getLogTag(); 158632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang 159f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang public ConversationWebView(Context c) { 160f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang this(c, null); 161f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang } 162f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang 163f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang public ConversationWebView(Context c, AttributeSet attrs) { 164f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang super(c, attrs); 16523014705ca9872cd5004a1aa76e83ae260165ecaAndy Huang 16630bcfe7b69f9d8e0cad2ee62dae9d3571cd0d88bAndy Huang final Resources r = getResources(); 16730bcfe7b69f9d8e0cad2ee62dae9d3571cd0d88bAndy Huang mViewportWidth = r.getInteger(R.integer.conversation_webview_viewport_px); 16830bcfe7b69f9d8e0cad2ee62dae9d3571cd0d88bAndy Huang mWebviewInitialDelay = r.getInteger(R.integer.webview_initial_delay); 16930bcfe7b69f9d8e0cad2ee62dae9d3571cd0d88bAndy Huang mDensity = r.getDisplayMetrics().density; 170f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang } 171f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang 172f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang @Override 173f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang public void addScrollListener(ScrollListener l) { 174f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang mScrollListeners.add(l); 175f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang } 176f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang 177f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang @Override 178f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang public void removeScrollListener(ScrollListener l) { 179f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang mScrollListeners.remove(l); 180f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang } 181f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang 18202f9d18a54072db8d86c524f9c09e508092ddd7cAndy Huang public void setOnScaleGestureListener(OnScaleGestureListener l) { 18302f9d18a54072db8d86c524f9c09e508092ddd7cAndy Huang if (l == null) { 18402f9d18a54072db8d86c524f9c09e508092ddd7cAndy Huang mScaleDetector = null; 18502f9d18a54072db8d86c524f9c09e508092ddd7cAndy Huang } else { 18602f9d18a54072db8d86c524f9c09e508092ddd7cAndy Huang mScaleDetector = new ScaleGestureDetector(getContext(), l); 18702f9d18a54072db8d86c524f9c09e508092ddd7cAndy Huang } 18802f9d18a54072db8d86c524f9c09e508092ddd7cAndy Huang } 18956d83850db72592a16f4e6ee9e0d59b60ec0824aMark Wei 19056d83850db72592a16f4e6ee9e0d59b60ec0824aMark Wei @Override 191f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang protected void onScrollChanged(int l, int t, int oldl, int oldt) { 192f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang super.onScrollChanged(l, t, oldl, oldt); 193f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang 194f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang for (ScrollListener listener : mScrollListeners) { 195f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang listener.onNotifierScroll(l, t); 196f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang } 197f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang } 198f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang 199bb56a1512559a5f024ba213c4bdcfe3d9d9387deAndy Huang @Override 200bb56a1512559a5f024ba213c4bdcfe3d9d9387deAndy Huang public boolean onTouchEvent(MotionEvent ev) { 201632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang final int action = ev.getActionMasked(); 202bb56a1512559a5f024ba213c4bdcfe3d9d9387deAndy Huang 203632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang switch (action) { 204632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang case MotionEvent.ACTION_DOWN: 205632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang mHandlingTouch = true; 206632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang break; 207632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang case MotionEvent.ACTION_POINTER_DOWN: 208632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang LogUtils.d(LOG_TAG, "WebView disabling intercepts: POINTER_DOWN"); 209632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang requestDisallowInterceptTouchEvent(true); 210ce8565b3605c2ce47c75e259f387cd4955f017daAndy Huang if (mScaleDetector != null) { 211ce8565b3605c2ce47c75e259f387cd4955f017daAndy Huang mIgnoringTouch = true; 212ce8565b3605c2ce47c75e259f387cd4955f017daAndy Huang final MotionEvent fakeCancel = MotionEvent.obtain(ev); 213ce8565b3605c2ce47c75e259f387cd4955f017daAndy Huang fakeCancel.setAction(MotionEvent.ACTION_CANCEL); 214ce8565b3605c2ce47c75e259f387cd4955f017daAndy Huang super.onTouchEvent(fakeCancel); 215ce8565b3605c2ce47c75e259f387cd4955f017daAndy Huang } 216632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang break; 217632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang case MotionEvent.ACTION_CANCEL: 218632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang case MotionEvent.ACTION_UP: 219632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang mHandlingTouch = false; 220ce8565b3605c2ce47c75e259f387cd4955f017daAndy Huang mIgnoringTouch = false; 221632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang break; 222bb56a1512559a5f024ba213c4bdcfe3d9d9387deAndy Huang } 223bb56a1512559a5f024ba213c4bdcfe3d9d9387deAndy Huang 224ce8565b3605c2ce47c75e259f387cd4955f017daAndy Huang final boolean handled = mIgnoringTouch || super.onTouchEvent(ev); 22502f9d18a54072db8d86c524f9c09e508092ddd7cAndy Huang 22602f9d18a54072db8d86c524f9c09e508092ddd7cAndy Huang if (mScaleDetector != null) { 22702f9d18a54072db8d86c524f9c09e508092ddd7cAndy Huang mScaleDetector.onTouchEvent(ev); 22802f9d18a54072db8d86c524f9c09e508092ddd7cAndy Huang } 22902f9d18a54072db8d86c524f9c09e508092ddd7cAndy Huang 23002f9d18a54072db8d86c524f9c09e508092ddd7cAndy Huang return handled; 231632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang } 232632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang 233632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang public boolean isHandlingTouch() { 234632721e6b3a9ba8c476456f2e0fb1b564561e0b5Andy Huang return mHandlingTouch; 235bb56a1512559a5f024ba213c4bdcfe3d9d9387deAndy Huang } 236f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang 23723014705ca9872cd5004a1aa76e83ae260165ecaAndy Huang public int getViewportWidth() { 23823014705ca9872cd5004a1aa76e83ae260165ecaAndy Huang return mViewportWidth; 23923014705ca9872cd5004a1aa76e83ae260165ecaAndy Huang } 24023014705ca9872cd5004a1aa76e83ae260165ecaAndy Huang 24123014705ca9872cd5004a1aa76e83ae260165ecaAndy Huang /** 24223014705ca9872cd5004a1aa76e83ae260165ecaAndy Huang * Similar to {@link #getScale()}, except that it returns the initially expected scale, as 24323014705ca9872cd5004a1aa76e83ae260165ecaAndy Huang * determined by the ratio of actual screen pixels to logical HTML pixels. 24423014705ca9872cd5004a1aa76e83ae260165ecaAndy Huang * <p>This assumes that we are able to control the logical HTML viewport with a meta-viewport 24523014705ca9872cd5004a1aa76e83ae260165ecaAndy Huang * tag. 24623014705ca9872cd5004a1aa76e83ae260165ecaAndy Huang */ 24723014705ca9872cd5004a1aa76e83ae260165ecaAndy Huang public float getInitialScale() { 24823014705ca9872cd5004a1aa76e83ae260165ecaAndy Huang // an HTML meta-viewport width of "device-width" and unspecified (medium) density means 24923014705ca9872cd5004a1aa76e83ae260165ecaAndy Huang // that the default scale is effectively the screen density. 25023014705ca9872cd5004a1aa76e83ae260165ecaAndy Huang return mDensity; 25123014705ca9872cd5004a1aa76e83ae260165ecaAndy Huang } 25223014705ca9872cd5004a1aa76e83ae260165ecaAndy Huang 25323014705ca9872cd5004a1aa76e83ae260165ecaAndy Huang public int screenPxToWebPx(int screenPx) { 25423014705ca9872cd5004a1aa76e83ae260165ecaAndy Huang return (int) (screenPx / getInitialScale()); 25523014705ca9872cd5004a1aa76e83ae260165ecaAndy Huang } 25623014705ca9872cd5004a1aa76e83ae260165ecaAndy Huang 25723014705ca9872cd5004a1aa76e83ae260165ecaAndy Huang public int webPxToScreenPx(int webPx) { 25823014705ca9872cd5004a1aa76e83ae260165ecaAndy Huang return (int) (webPx * getInitialScale()); 25923014705ca9872cd5004a1aa76e83ae260165ecaAndy Huang } 26023014705ca9872cd5004a1aa76e83ae260165ecaAndy Huang 2612b24e995cfcdb6ab0579b2fbcccb399a53632395Mark Wei public float screenPxToWebPxError(int screenPx) { 2622b24e995cfcdb6ab0579b2fbcccb399a53632395Mark Wei return screenPx / getInitialScale() - screenPxToWebPx(screenPx); 2632b24e995cfcdb6ab0579b2fbcccb399a53632395Mark Wei } 2642b24e995cfcdb6ab0579b2fbcccb399a53632395Mark Wei 2652b24e995cfcdb6ab0579b2fbcccb399a53632395Mark Wei public float webPxToScreenPxError(int webPx) { 2662b24e995cfcdb6ab0579b2fbcccb399a53632395Mark Wei return webPx * getInitialScale() - webPxToScreenPx(webPx); 2672b24e995cfcdb6ab0579b2fbcccb399a53632395Mark Wei } 26802f9d18a54072db8d86c524f9c09e508092ddd7cAndy Huang 269f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang} 270