Chromium Code Reviews| Index: android_webview/java/src/org/chromium/android_webview/AwViewAndroidDelegate.java |
| diff --git a/android_webview/java/src/org/chromium/android_webview/AwViewAndroidDelegate.java b/android_webview/java/src/org/chromium/android_webview/AwViewAndroidDelegate.java |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..12c0f8f4ea48d02fd5a638778d9cc18b98dbcccb |
| --- /dev/null |
| +++ b/android_webview/java/src/org/chromium/android_webview/AwViewAndroidDelegate.java |
| @@ -0,0 +1,146 @@ |
| +// Copyright 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.view.View; |
| +import android.view.ViewGroup; |
| +import android.widget.FrameLayout; |
| + |
| +import org.chromium.base.VisibleForTesting; |
| +import org.chromium.content.browser.RenderCoordinates; |
| +import org.chromium.ui.base.ViewAndroidDelegate; |
| +import org.chromium.ui.gfx.DeviceDisplayInfo; |
| + |
| +import java.lang.ref.WeakReference; |
| +import java.util.LinkedHashMap; |
| +import java.util.Map; |
| +import java.util.Map.Entry; |
| + |
| +/** |
| + * Implementation of the abstract class {@link ViewAndroidDelegate} for WebView. |
| + */ |
| +public class AwViewAndroidDelegate extends ViewAndroidDelegate { |
| + /** |
| + * The current container view. This view can be updated with |
| + * {@link #updateCurrentContainerView()}. This needs to be a WeakReference |
| + * because ViewAndroidDelegate is held strongly native side, which otherwise |
| + * indefinitely prevents Android WebView from being garbage collected. |
| + */ |
| + private WeakReference<ViewGroup> mContainerView; |
|
boliu
2016/07/27 16:20:26
I don't see why WeakReference is needed here actua
Jinsuk Kim
2016/07/29 06:09:13
In fact there was another strong ref in native sid
|
| + |
| + /** |
| + * List of anchor views stored in the order in which they were acquired mapped |
| + * to their position. |
| + */ |
| + private final Map<View, Position> mAnchorViews = new LinkedHashMap<>(); |
| + |
| + private final RenderCoordinates mRenderCoordinates; |
| + |
| + /** |
| + * Represents the position of an anchor view. |
| + */ |
| + @VisibleForTesting |
| + private static class Position { |
| + public final float mX; |
| + public final float mY; |
| + public final float mWidth; |
| + public final float mHeight; |
| + public final int mLeftMargin; |
| + public final int mTopMargin; |
| + |
| + public Position(float x, float y, float width, float height, int leftMargin, |
| + int topMargin) { |
| + mX = x; |
| + mY = y; |
| + mWidth = width; |
| + mHeight = height; |
| + mLeftMargin = leftMargin; |
| + mTopMargin = topMargin; |
| + } |
| + } |
| + |
| + AwViewAndroidDelegate(ViewGroup containerView, RenderCoordinates renderCoordinates) { |
| + mContainerView = new WeakReference<>(containerView); |
| + mRenderCoordinates = renderCoordinates; |
| + } |
| + |
| + @Override |
| + public View acquireView() { |
| + ViewGroup containerView = mContainerView.get(); |
| + if (containerView == null) return null; |
| + View anchorView = new View(containerView.getContext()); |
| + containerView.addView(anchorView); |
| + // |mAnchorViews| will be updated with the right view position in |setViewPosition|. |
| + mAnchorViews.put(anchorView, null); |
| + return anchorView; |
| + } |
| + |
| + @Override |
| + public void removeView(View anchorView) { |
| + mAnchorViews.remove(anchorView); |
| + ViewGroup containerView = mContainerView.get(); |
| + if (containerView != null) { |
| + containerView.removeView(anchorView); |
| + } |
| + } |
| + |
| + /** |
| + * Updates the current container view to which this class delegates. Existing anchor views |
| + * are transferred from the old to the new container view. |
| + */ |
| + public void updateCurrentContainerView(ViewGroup containerView) { |
| + ViewGroup oldContainerView = mContainerView.get(); |
| + mContainerView = new WeakReference<>(containerView); |
| + for (Entry<View, Position> entry : mAnchorViews.entrySet()) { |
| + View anchorView = entry.getKey(); |
| + Position position = entry.getValue(); |
| + if (oldContainerView != null) { |
| + oldContainerView.removeView(anchorView); |
| + } |
| + containerView.addView(anchorView); |
| + if (position != null) { |
| + float scale = (float) DeviceDisplayInfo.create(containerView.getContext()) |
| + .getDIPScale(); |
| + setViewPosition(anchorView, position.mX, position.mY, |
| + position.mWidth, position.mHeight, scale, |
| + position.mLeftMargin, position.mTopMargin); |
| + } |
| + } |
| + } |
| + |
| + @SuppressWarnings("deprecation") // AbsoluteLayout |
| + @Override |
| + public void setViewPosition(View anchorView, float x, float y, float width, float height, |
| + float scale, int leftMargin, int topMargin) { |
| + ViewGroup containerView = getContainerView(); |
| + if (!mAnchorViews.containsKey(anchorView) || containerView == null) return; |
| + |
| + mAnchorViews.put(anchorView, new Position(x, y, width, height, leftMargin, topMargin)); |
| + |
| + if (containerView instanceof FrameLayout) { |
| + super.setViewPosition(anchorView, x, y, width, height, scale, leftMargin, topMargin); |
| + return; |
| + } |
| + // This fixes the offset due to a difference in |
| + // scrolling model of WebView vs. Chrome. |
| + // TODO(sgurun) fix this to use mContainerViewAtCreation.getScroll[X/Y]() |
| + // as it naturally accounts for scroll differences between |
| + // these models. |
| + leftMargin += mRenderCoordinates.getScrollXPixInt(); |
| + topMargin += mRenderCoordinates.getScrollYPixInt(); |
| + |
| + int scaledWidth = Math.round(width * scale); |
| + int scaledHeight = Math.round(height * scale); |
| + android.widget.AbsoluteLayout.LayoutParams lp = |
| + new android.widget.AbsoluteLayout.LayoutParams( |
| + scaledWidth, scaledHeight, leftMargin, topMargin); |
| + anchorView.setLayoutParams(lp); |
| + } |
| + |
| + @Override |
| + protected ViewGroup getContainerView() { |
| + return mContainerView.get(); |
| + } |
| +} |