Basic changes to get embedded video working.

Add the ViewManager class to handle child views within a WebView. This class
attaches and removes the views in the UI thread. It also scales the layout
params based on the scale of the WebView.
This commit is contained in:
Patrick Scott
2009-07-02 08:56:10 -04:00
parent 3042bb6238
commit 0a5ce01eda
3 changed files with 177 additions and 26 deletions

View File

@@ -24,6 +24,7 @@ import android.os.Looper;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.webkit.ViewManager.ChildView;
import android.widget.MediaController;
import android.widget.VideoView;
@@ -46,8 +47,6 @@ class HTML5VideoViewProxy extends Handler {
// The singleton instance.
private static HTML5VideoViewProxy sInstance;
// The VideoView driven via this proxy.
private VideoView mVideoView;
// The context object used to initialize the VideoView and the
// MediaController.
private Context mContext;
@@ -61,12 +60,6 @@ class HTML5VideoViewProxy extends Handler {
super(Looper.getMainLooper());
// Save the context object.
mContext = context;
// Send a message to the UI thread to create the VideoView.
// This need to be done on the UI thread, or else the
// event Handlers used by the VideoView and MediaController
// will be attached to the wrong thread.
Message message = obtainMessage(INIT);
sendMessage(message);
}
@Override
@@ -74,25 +67,22 @@ class HTML5VideoViewProxy extends Handler {
// This executes on the UI thread.
switch (msg.what) {
case INIT:
ChildView child = (ChildView) msg.obj;
// Create the video view and set a default controller.
mVideoView = new VideoView(mContext);
mVideoView.setMediaController(new MediaController(mContext));
VideoView v = new VideoView(mContext);
// This is needed because otherwise there will be a black square
// stuck on the screen.
v.setWillNotDraw(false);
v.setMediaController(new MediaController(mContext));
child.mView = v;
break;
case PLAY:
// Check if the fullscreen video view is currently playing.
// If it is, ignore the message.
if (!mVideoView.isPlaying()) {
HashMap<String, Object> map =
HashMap<String, Object> map =
(HashMap<String, Object>) msg.obj;
String url = (String) map.get("url");
WebView webview = (WebView) map.get("webview");
WebChromeClient client = webview.getWebChromeClient();
if (client != null) {
mVideoView.setVideoURI(Uri.parse(url));
mVideoView.start();
client.onShowCustomView(mVideoView);
}
}
String url = (String) map.get("url");
VideoView view = (VideoView) map.get("view");
view.setVideoURI(Uri.parse(url));
view.start();
break;
}
}
@@ -102,16 +92,35 @@ class HTML5VideoViewProxy extends Handler {
* @param url is the URL of the video stream.
* @param webview is the WebViewCore that is requesting the playback.
*/
public void play(String url, WebViewCore webviewCore) {
public void play(String url, ChildView child) {
// We need to know the webview that is requesting the playback.
Message message = obtainMessage(PLAY);
HashMap<String, Object> map = new HashMap();
map.put("url", url);
map.put("webview", webviewCore.getWebView());
map.put("view", child.mView);
message.obj = map;
sendMessage(message);
}
public ChildView createView(WebViewCore core) {
WebView w = core.getWebView();
if (w == null) {
return null;
}
ChildView child = w.mViewManager.createView();
sendMessage(obtainMessage(INIT, child));
return child;
}
public void attachView(ChildView child, int x, int y, int width,
int height) {
child.attachView(x, y, width, height);
}
public void removeView(ChildView child) {
child.removeView();
}
/**
* The factory for HTML5VideoViewProxy instances. Right now,
* it only produces a singleton.

View File

@@ -0,0 +1,129 @@
/*
* Copyright (C) 2009 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 android.webkit;
import android.content.Context;
import android.view.View;
import android.widget.AbsoluteLayout;
import java.util.ArrayList;
class ViewManager {
private final WebView mWebView;
private final ArrayList<ChildView> mChildren = new ArrayList<ChildView>();
private boolean mHidden;
class ChildView {
int x;
int y;
int width;
int height;
View mView; // generic view to show
ChildView() {
}
void setBounds(int x, int y, int width, int height) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
void attachView(int x, int y, int width, int height) {
if (mView == null) {
return;
}
setBounds(x, y, width, height);
final AbsoluteLayout.LayoutParams lp =
new AbsoluteLayout.LayoutParams(ctv(width), ctv(height),
ctv(x), ctv(y));
mWebView.mPrivateHandler.post(new Runnable() {
public void run() {
// This method may be called multiple times. If the view is
// already attached, just set the new LayoutParams,
// otherwise attach the view and add it to the list of
// children.
if (mView.getParent() != null) {
mView.setLayoutParams(lp);
} else {
mWebView.addView(mView, lp);
mChildren.add(ChildView.this);
}
}
});
}
void removeView() {
if (mView == null) {
return;
}
mWebView.mPrivateHandler.post(new Runnable() {
public void run() {
mWebView.removeView(mView);
mChildren.remove(ChildView.this);
}
});
}
}
ViewManager(WebView w) {
mWebView = w;
}
ChildView createView() {
return new ChildView();
}
// contentToView shorthand.
private int ctv(int val) {
return mWebView.contentToView(val);
}
void scaleAll() {
for (ChildView v : mChildren) {
View view = v.mView;
AbsoluteLayout.LayoutParams lp =
(AbsoluteLayout.LayoutParams) view.getLayoutParams();
lp.width = ctv(v.width);
lp.height = ctv(v.height);
lp.x = ctv(v.x);
lp.y = ctv(v.y);
view.setLayoutParams(lp);
}
}
void hideAll() {
if (mHidden) {
return;
}
for (ChildView v : mChildren) {
v.mView.setVisibility(View.GONE);
}
mHidden = true;
}
void showAll() {
if (!mHidden) {
return;
}
for (ChildView v : mChildren) {
v.mView.setVisibility(View.VISIBLE);
}
mHidden = false;
}
}

View File

@@ -308,6 +308,9 @@ public class WebView extends AbsoluteLayout
// more key events.
private int mTextGeneration;
// Used by WebViewCore to create child views.
/* package */ final ViewManager mViewManager;
// The list of loaded plugins.
private static PluginList sPluginList;
@@ -710,6 +713,8 @@ public class WebView extends AbsoluteLayout
mDatabase = WebViewDatabase.getInstance(context);
mScroller = new Scroller(context);
mViewManager = new ViewManager(this);
mZoomButtonsController = new ZoomButtonsController(this);
mZoomButtonsController.setOnZoomListener(mZoomListener);
// ZoomButtonsController positions the buttons at the bottom, but in
@@ -1688,7 +1693,7 @@ public class WebView extends AbsoluteLayout
return Math.round(x * mInvActualScale);
}
private int contentToView(int x) {
/*package*/ int contentToView(int x) {
return Math.round(x * mActualScale);
}
@@ -1779,6 +1784,9 @@ public class WebView extends AbsoluteLayout
mActualScale = scale;
mInvActualScale = 1 / scale;
// Scale all the child views
mViewManager.scaleAll();
// as we don't have animation for scaling, don't do animation
// for scrolling, as it causes weird intermediate state
// pinScrollTo(Math.round(sx), Math.round(sy));
@@ -2716,6 +2724,8 @@ public class WebView extends AbsoluteLayout
- (width >> 1), (int) (scrollFrame.centerY()
* mActualScale) - (height >> 1));
mTouchMode = TOUCH_DONE_MODE;
// Show all the child views once we are done.
mViewManager.showAll();
} else {
mTouchMode = SCROLL_ZOOM_OUT;
}
@@ -2879,6 +2889,8 @@ public class WebView extends AbsoluteLayout
mTouchMode = TOUCH_DONE_MODE;
return;
}
// Hide the child views while in this mode.
mViewManager.hideAll();
startZoomScrollOut();
mTouchMode = SCROLL_ZOOM_ANIMATION_OUT;
invalidate();
@@ -3625,6 +3637,7 @@ public class WebView extends AbsoluteLayout
@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
super.onScrollChanged(l, t, oldl, oldt);
sendOurVisibleRect();
}