diff options
author | mkosiba@chromium.org <mkosiba@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-01-11 16:36:47 +0000 |
---|---|---|
committer | mkosiba@chromium.org <mkosiba@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-01-11 16:36:47 +0000 |
commit | ea1d5f036926ae0c19f98daf211c5076ee50f5c3 (patch) | |
tree | f84b03d144e9d0dd99103312bf63d9762e22d9fd /android_webview/java | |
parent | 2c035f1fe7843d469ce09162f83ce13434c3bc89 (diff) | |
download | chromium_src-ea1d5f036926ae0c19f98daf211c5076ee50f5c3.zip chromium_src-ea1d5f036926ae0c19f98daf211c5076ee50f5c3.tar.gz chromium_src-ea1d5f036926ae0c19f98daf211c5076ee50f5c3.tar.bz2 |
[android_webview] Add onMeasure support.
This change makes it possible for the AwContents embeddder
to implement the android.view.View#onMeasure method.
A content size change listener is added to ContentViewCore
to support the wrap_content layout mode. The layout
logic is encapsulated in AwLayoutSizer class.
BUG=None
TEST=AndroidWebViewTests
Java-only change, passes on the trybots.
NOTRY=true
Review URL: https://chromiumcodereview.appspot.com/11529016
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@176370 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'android_webview/java')
-rw-r--r-- | android_webview/java/src/org/chromium/android_webview/AwContents.java | 29 | ||||
-rw-r--r-- | android_webview/java/src/org/chromium/android_webview/AwLayoutSizer.java | 96 |
2 files changed, 122 insertions, 3 deletions
diff --git a/android_webview/java/src/org/chromium/android_webview/AwContents.java b/android_webview/java/src/org/chromium/android_webview/AwContents.java index 93a78d4..3d51cb7 100644 --- a/android_webview/java/src/org/chromium/android_webview/AwContents.java +++ b/android_webview/java/src/org/chromium/android_webview/AwContents.java @@ -82,6 +82,10 @@ public class AwContents { * dispatching of view methods through the containing view. */ public interface InternalAccessDelegate extends ContentViewCore.InternalAccessDelegate { + /** + * @see View#setMeasuredDimension(int, int) + */ + void setMeasuredDimension(int measuredWidth, int measuredHeight); } private int mNativeAwContents; @@ -90,7 +94,8 @@ public class AwContents { private AwContentsClient mContentsClient; private AwContentsIoThreadClient mIoThreadClient; private InterceptNavigationDelegateImpl mInterceptNavigationDelegate; - private ContentViewCore.InternalAccessDelegate mInternalAccessAdapter; + private InternalAccessDelegate mInternalAccessAdapter; + private final AwLayoutSizer mLayoutSizer; // This can be accessed on any thread after construction. See AwContentsIoThreadClient. private final AwSettings mSettings; private final ClientCallbackHandler mClientCallbackHandler; @@ -271,9 +276,21 @@ public class AwContents { } } + private class AwLayoutSizerDelegate implements AwLayoutSizer.Delegate { + @Override + public void requestLayout() { + mContainerView.requestLayout(); + } + + @Override + public void setMeasuredDimension(int measuredWidth, int measuredHeight) { + mInternalAccessAdapter.setMeasuredDimension(measuredWidth, measuredHeight); + } + } + // TODO(kristianm): Delete this when privateBrowsing parameter is removed in Android public AwContents(ViewGroup containerView, - ContentViewCore.InternalAccessDelegate internalAccessAdapter, + InternalAccessDelegate internalAccessAdapter, AwContentsClient contentsClient, NativeWindow nativeWindow, boolean privateBrowsing, boolean isAccessFromFileURLsGrantedByDefault) { @@ -289,7 +306,7 @@ public class AwContents { * TODO(benm): Remove the nativeWindow parameter. */ public AwContents(ViewGroup containerView, - ContentViewCore.InternalAccessDelegate internalAccessAdapter, + InternalAccessDelegate internalAccessAdapter, AwContentsClient contentsClient, NativeWindow nativeWindow, boolean isAccessFromFileURLsGrantedByDefault) { @@ -309,6 +326,8 @@ public class AwContents { new AwNativeWindow(mContainerView.getContext()), isAccessFromFileURLsGrantedByDefault); mContentViewCore.setContentViewClient(mContentsClient); + mLayoutSizer = new AwLayoutSizer(new AwLayoutSizerDelegate()); + mContentViewCore.setContentSizeChangeListener(mLayoutSizer); mContentsClient.installWebContentsObserver(mContentViewCore); mSettings = new AwSettings(mContentViewCore.getContext()); @@ -379,6 +398,10 @@ public class AwContents { } } + public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + mLayoutSizer.onMeasure(widthMeasureSpec, heightMeasureSpec); + } + public int findAllSync(String searchString) { if (mNativeAwContents == 0) return 0; return nativeFindAllSync(mNativeAwContents, searchString); diff --git a/android_webview/java/src/org/chromium/android_webview/AwLayoutSizer.java b/android_webview/java/src/org/chromium/android_webview/AwLayoutSizer.java new file mode 100644 index 0000000..c698ade --- /dev/null +++ b/android_webview/java/src/org/chromium/android_webview/AwLayoutSizer.java @@ -0,0 +1,96 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.android_webview; + +import android.util.Pair; +import android.view.View.MeasureSpec; +import android.view.View; + +import org.chromium.content.browser.ContentViewCore; + +/** + * Helper methods used to manage the layout of the View that contains AwContents. + */ +public class AwLayoutSizer implements ContentViewCore.ContentSizeChangeListener { + // These are used to prevent a re-layout if the content size changes within a dimension that is + // fixed by the view system. + private boolean mWidthMeasurementIsFixed; + private boolean mHeightMeasurementIsFixed; + + // Size of the rendered content, as reported by native. + private int mContentHeight; + private int mContentWidth; + + // Callback object for interacting with the View. + Delegate mDelegate; + + public interface Delegate { + void requestLayout(); + void setMeasuredDimension(int measuredWidth, int measuredHeight); + } + + public AwLayoutSizer(Delegate delegate) { + mDelegate = delegate; + } + + /** + * Update the contents size. + * This should be called whenever the content size changes (due to DOM manipulation or page + * load, for example). + */ + @Override + public void onContentSizeChanged(int width, int height) { + boolean layoutNeeded = (mContentWidth != width && !mWidthMeasurementIsFixed) || + (mContentHeight != height && !mHeightMeasurementIsFixed); + + mContentWidth = width; + mContentHeight = height; + + if (layoutNeeded) { + mDelegate.requestLayout(); + } + } + + /** + * Calculate the size of the view. + * This is designed to be used to implement the android.view.View#onMeasure() method. + */ + public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int heightMode = MeasureSpec.getMode(heightMeasureSpec); + int heightSize = MeasureSpec.getSize(heightMeasureSpec); + int widthMode = MeasureSpec.getMode(widthMeasureSpec); + int widthSize = MeasureSpec.getSize(widthMeasureSpec); + + int measuredHeight = heightSize; + int measuredWidth = widthSize; + + // Always use the given size unless unspecified. This matches WebViewClassic behavior. + mWidthMeasurementIsFixed = (widthMode != MeasureSpec.UNSPECIFIED); + // Freeze the height if an exact size is given by the parent or if the content size has + // exceeded the maximum size specified by the parent. + // TODO(mkosiba): Actually we'd like the reduction in content size to cause the WebView to + // shrink back again but only as a result of a page load. + mHeightMeasurementIsFixed = (heightMode == MeasureSpec.EXACTLY) || + (heightMode == MeasureSpec.AT_MOST && mContentHeight > heightSize); + + if (!mHeightMeasurementIsFixed) { + measuredHeight = mContentHeight; + } + + if (!mWidthMeasurementIsFixed) { + measuredWidth = mContentWidth; + } + + if (measuredHeight < mContentHeight) { + measuredHeight |= View.MEASURED_STATE_TOO_SMALL; + } + + if (measuredWidth < mContentWidth) { + measuredWidth |= View.MEASURED_STATE_TOO_SMALL; + } + + mDelegate.setMeasuredDimension(measuredWidth, measuredHeight); + } +} |