blob: 5ee3fdfc3e4a48fd17bd0ca3843ee4e138586b4d [file] [log] [blame]
// Copyright 2019 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.weblayer.demo;
import android.content.Context;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentTransaction;
import android.text.InputType;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.inputmethod.EditorInfo;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.TextView;
import android.widget.TextView.OnEditorActionListener;
import org.chromium.weblayer.BrowserController;
import org.chromium.weblayer.BrowserFragmentController;
import org.chromium.weblayer.BrowserObserver;
import org.chromium.weblayer.Profile;
import org.chromium.weblayer.WebLayer;
/**
* Activity for managing the Demo Shell.
*/
public class WebLayerAnimationDemoActivity extends FragmentActivity {
private static final String TAG = "AnimationDemo";
private static final boolean USE_WEBVIEW = false;
private Profile mProfile;
private final BrowserFragmentController mBrowserFragmentControllers[] =
new BrowserFragmentController[4];
private final ContainerFrameLayout mContainerViews[] = new ContainerFrameLayout[4];
private final MyWebView mWebViews[] = new MyWebView[4];
private FrameLayout mMainView;
public static class ContainerFrameLayout extends FrameLayout {
private final BrowserFragmentController mFragmentController;
private int mIndex;
private boolean mInterceptTouchEvent;
public ContainerFrameLayout(Context context, BrowserFragmentController fragmentController,
int index) {
super(context);
mFragmentController = fragmentController;
mIndex = index;
}
public BrowserFragmentController getFragmentController() {
return mFragmentController;
}
public void setInterceptTouchEvent(boolean intercept) {
mInterceptTouchEvent = intercept;
}
public int getIndex() {
return mIndex;
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return mInterceptTouchEvent;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (!mInterceptTouchEvent) return super.onTouchEvent(event);
if (event.getAction() == KeyEvent.ACTION_UP) {
performClick();
}
return true;
}
}
private static class MyWebView extends WebView {
private int mIndex;
private boolean mInterceptTouchEvent;
public MyWebView(Context context, int index) {
super(context);
mIndex = index;
}
public void setInterceptTouchEvent(boolean intercept) {
mInterceptTouchEvent = intercept;
}
public int getIndex() {
return mIndex;
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return mInterceptTouchEvent;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (!mInterceptTouchEvent) return super.onTouchEvent(event);
if (event.getAction() == KeyEvent.ACTION_UP) {
performClick();
}
return true;
}
}
private void createNewFragment(int index) {
mBrowserFragmentControllers[index] = mProfile.createBrowserFragmentController(this);
final BrowserController controller = mBrowserFragmentControllers[index]
.getBrowserController();
ContainerFrameLayout container =
new ContainerFrameLayout(this, mBrowserFragmentControllers[index],
index);
mContainerViews[index] = container;
int viewId = View.generateViewId();
container.setId(viewId);
mMainView.addView(container);
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.add(viewId, mBrowserFragmentControllers[index].getFragment());
transaction.commit();
EditText urlView = new EditText(this);
urlView.setSelectAllOnFocus(true);
urlView.setInputType(InputType.TYPE_TEXT_VARIATION_URI);
urlView.setImeOptions(EditorInfo.IME_ACTION_GO);
// The background of the top-view must be opaque, otherwise it bleeds through to the
// cc::Layer that mirrors the contents of the top-view.
urlView.setBackgroundColor(0xFFa9a9a9);
urlView.setOnEditorActionListener(new OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if ((actionId != EditorInfo.IME_ACTION_GO)
&& (event == null || event.getKeyCode() != KeyEvent.KEYCODE_ENTER
|| event.getAction() != KeyEvent.ACTION_DOWN)) {
return false;
}
String url = urlView.getText().toString();
controller.getNavigationController().navigate(Uri.parse(sanitizeUrl(url)));
return true;
}
});
mBrowserFragmentControllers[index].setTopView(urlView);
controller.addObserver(new BrowserObserver() {
@Override
public void visibleUrlChanged(Uri uri) {
urlView.setText(uri.toString());
}
});
}
@Override
protected void onCreate(final Bundle savedInstanceState) {
if (USE_WEBVIEW) {
super.onCreate(savedInstanceState);
FrameLayout mainView = new FrameLayout(this);
mMainView = mainView;
setContentView(mainView);
for (int i = 0; i < 3; ++i) {
mWebViews[i] = new MyWebView(this, i);
mWebViews[i].setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView webView, String url) {
return false;
}
});
mMainView.addView(mWebViews[i]);
WebSettings settings = mWebViews[i].getSettings();
settings.setJavaScriptEnabled(true);
// Default layout behavior for chrome on android.
settings.setUseWideViewPort(true);
settings.setLoadWithOverviewMode(true);
settings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.TEXT_AUTOSIZING);
}
} else {
// Only call init for main process.
WebLayer webLayer = null;
try {
webLayer = WebLayer.create(getApplication()).get();
} catch (Exception e) {
throw new RuntimeException("failed loading WebLayer", e);
}
super.onCreate(savedInstanceState);
FrameLayout mainView = new FrameLayout(this);
mMainView = mainView;
setContentView(mainView);
mProfile = webLayer.createProfile(null);
createNewFragment(0);
createNewFragment(1);
createNewFragment(2);
mBrowserFragmentControllers[0].getBrowserController().getNavigationController()
.navigate(Uri.parse(sanitizeUrl("https://www.google.com")));
mBrowserFragmentControllers[1].getBrowserController().getNavigationController()
.navigate(Uri.parse(sanitizeUrl("https://en.wikipedia.org")));
mBrowserFragmentControllers[2].getBrowserController().getNavigationController()
.navigate(Uri.parse(sanitizeUrl("https://www.chromium.org")));
}
}
@Override
protected void onDestroy() {
for (int i = 0; i < mBrowserFragmentControllers.length; ++i) {
BrowserFragmentController fragment = mBrowserFragmentControllers[i];
if (fragment != null) fragment.destroy();
mBrowserFragmentControllers[i] = null;
}
if (mProfile != null) mProfile.destroy();
super.onDestroy();
}
@Override
protected void onStart() {
super.onStart();
}
@Override
protected void onResume() {
super.onResume();
if (USE_WEBVIEW) {
mWebViews[0].post(() -> {
mWebViews[0].loadUrl("https://www.google.com");
mWebViews[1].loadUrl("https://en.wikipedia.org");
mWebViews[2].loadUrl("https://www.chromium.org");
for (int i = 0; i < 3; ++i) {
mWebViews[i].setOnClickListener(new OnClickImpl());
animateDown(mWebViews[i]);
}
});
} else {
mContainerViews[0].setOnClickListener(new OnClickImpl());
mContainerViews[1].setOnClickListener(new OnClickImpl());
mContainerViews[2].setOnClickListener(new OnClickImpl());
mContainerViews[0].post(() -> {
mBrowserFragmentControllers[0].setSupportsEmbedding(true).addCallback(
(Boolean result) -> animateDown(mContainerViews[0]));
mBrowserFragmentControllers[1].setSupportsEmbedding(true).addCallback(
(Boolean result) -> animateDown(mContainerViews[1]));
mBrowserFragmentControllers[2].setSupportsEmbedding(true).addCallback(
(Boolean result) -> animateDown(mContainerViews[2]));
});
}
}
private ContainerFrameLayout mFullscreenContainer;
private MyWebView mFullscreenWebView;
public class OnClickImpl implements View.OnClickListener {
@Override
public void onClick(View v) {
if (USE_WEBVIEW) {
MyWebView webview = (MyWebView) v;
if (mFullscreenWebView == webview) return;
mMainView.removeView(webview);
mMainView.addView(webview, 0);
if (mFullscreenWebView != null) {
animateDown(mFullscreenWebView);
}
animateUp(webview);
mFullscreenWebView = webview;
} else {
ContainerFrameLayout container = (ContainerFrameLayout) v;
if (mFullscreenContainer == container) return;
// Move to back by bringing others to the front.
// This avoids detaching and reattaching any views.
for (int i = 0; i < 3; ++i) {
if (mContainerViews[i] == container) continue;
mMainView.bringChildToFront(mContainerViews[i]);
}
if (mFullscreenContainer != null) {
animateDown(mFullscreenContainer);
}
animateUp(container);
mFullscreenContainer = container;
}
}
}
private static void animateDown(ContainerFrameLayout container) {
// Start animation after fullying switched from SurfaceView to TextureView.
int index = container.getIndex();
container.getFragmentController().setSupportsEmbedding(true)
.addCallback((Boolean result) -> {
container.animate()
.scaleX(1.0f / 3)
.scaleY(1.0f / 3)
.translationX(-container.getWidth() / 3.0f
+ (container.getWidth() / 3.0f * index))
.translationY(container.getHeight() / 3.0f)
.alpha(0.8f)
.setDuration(500);
container.setInterceptTouchEvent(true);
});
}
private static void animateUp(ContainerFrameLayout container) {
container.animate()
.scaleX(1.0f)
.scaleY(1.0f)
.translationX(0)
.translationY(0)
.alpha(1.0f)
.setDuration(500)
.withEndAction(() -> {
container.getFragmentController().setSupportsEmbedding(false);
container.setInterceptTouchEvent(false);
});
}
private static void animateDown(MyWebView webview) {
int index = webview.getIndex();
webview.animate()
.scaleX(1.0f / 3)
.scaleY(1.0f / 3)
.translationX(-webview.getWidth() / 3.0f + (webview.getWidth() / 3.0f * index))
.translationY(webview.getHeight() / 3.0f)
.alpha(0.8f)
.setDuration(500);
webview.setInterceptTouchEvent(true);
}
private static void animateUp(MyWebView webview) {
webview.animate()
.scaleX(1.0f)
.scaleY(1.0f)
.translationX(0)
.translationY(0)
.alpha(1.0f)
.setDuration(500);
webview.setInterceptTouchEvent(false);
}
/**
* Given an URL, this performs minimal sanitizing to ensure it will be valid.
* @param url The url to be sanitized.
* @return The sanitized URL.
*/
public static String sanitizeUrl(String url) {
if (url == null) return null;
if (url.startsWith("www.") || url.indexOf(":") == -1) url = "http://" + url;
return url;
}
}