feat: Add methods to get the root view and set a different root view at run time (#5386)

* feat: add option to set a different root view at run time

* feat: expose application getRootView method

* refactor: Introduce ViewEntry interface

* fix: Respect root view rturned from launch event in Android

* refactor: getRootView() code + caching root view per activity.

* refactor: add app-root.xml in apps

* refactor: http test made async
This commit is contained in:
Martin Yankov
2018-02-09 16:04:20 +02:00
committed by Alexander Vakrilov
parent 0c8275fa06
commit b113b0021a
11 changed files with 227 additions and 123 deletions

View File

@@ -2,6 +2,8 @@
require("globals");
import { Observable, EventData } from "../data/observable";
// types
import { View } from "../ui/core/view";
import {
trace as profilingTrace,
time,

View File

@@ -13,7 +13,8 @@ import { profile } from "../profiling";
// First reexport so that app module is initialized.
export * from "./application-common";
import { NavigationEntry } from "../ui/frame";
// types
import { NavigationEntry, View, AndroidActivityCallbacks } from "../ui/frame";
const ActivityCreated = "activityCreated";
const ActivityDestroyed = "activityDestroyed";
@@ -53,7 +54,7 @@ export class AndroidApplication extends Observable implements AndroidApplication
if (this.nativeApp === nativeApp) {
return;
}
if (this.nativeApp) {
throw new Error("application.android already initialized.");
}
@@ -148,10 +149,35 @@ export function run(entry?: NavigationEntry | string) {
start(entry);
}
const CALLBACKS = "_callbacks";
export function _resetRootView(entry?: NavigationEntry | string) {
const activity = androidApp.foregroundActivity;
if (!activity) {
throw new Error("Cannot find android activity.");
}
mainEntry = typeof entry === "string" ? { moduleName: entry } : entry;
const callbacks: AndroidActivityCallbacks = activity[CALLBACKS];
callbacks.resetActivityContent(activity);
}
export function getMainEntry() {
return mainEntry;
}
export function getRootView() {
// Use start activity as a backup when foregroundActivity is still not set
// in cases when we are getting the root view before activity.onResumed event is fired
const activity = androidApp.foregroundActivity || androidApp.startActivity;
if (!activity) {
return undefined;
}
const callbacks: AndroidActivityCallbacks = activity[CALLBACKS];
return callbacks ? callbacks.getRootView() : undefined;
}
export function getNativeApplication(): android.app.Application {
// Try getting it from module - check whether application.android.init has been explicitly called
let nativeApp = androidApp.nativeApp;
@@ -202,11 +228,11 @@ function initLifecycleCallbacks() {
}
});
const notifyActivityCreated = profile("notifyActivityCreated", function(activity: android.app.Activity, savedInstanceState: android.os.Bundle) {
const notifyActivityCreated = profile("notifyActivityCreated", function (activity: android.app.Activity, savedInstanceState: android.os.Bundle) {
androidApp.notify(<AndroidActivityBundleEventData>{ eventName: ActivityCreated, object: androidApp, activity, bundle: savedInstanceState });
});
const subscribeForGlobalLayout = profile("subscribeForGlobalLayout", function(activity: android.app.Activity) {
const subscribeForGlobalLayout = profile("subscribeForGlobalLayout", function (activity: android.app.Activity) {
const rootView = activity.getWindow().getDecorView().getRootView();
let onGlobalLayoutListener = new android.view.ViewTreeObserver.OnGlobalLayoutListener({
onGlobalLayout() {

View File

@@ -116,6 +116,11 @@ export interface CssChangedEventData extends EventData {
*/
export function getMainEntry(): NavigationEntry;
/**
* Get current application root view.
*/
export function getRootView(): View;
/**
* Get application level static resources.
*/
@@ -178,6 +183,12 @@ export function start(entry?: NavigationEntry | string);
*/
export function run(entry?: NavigationEntry | string);
/**
* Call this method to change the root view of your application. Important: Your application must already be running.
* This method won't create Frame as root view.
*/
export function _resetRootView(entry?: NavigationEntry | string);
//@private
/**
* Internal method use to check if a root Frame should be automatically created as root view.

View File

@@ -100,6 +100,10 @@ class IOSApplication implements IOSApplicationDefinition {
}
}
get rootView() : View {
return this._rootView;
}
public addNotificationObserver(notificationName: string, onReceiveCallback: (notification: NSNotification) => void): NotificationObserver {
const observer = NotificationObserver.initWithCallback(onReceiveCallback);
utils.ios.getter(NSNotificationCenter, NSNotificationCenter.defaultCenter).addObserverSelectorNameObject(observer, "onReceive", notificationName, null);
@@ -263,6 +267,10 @@ export function getMainEntry() {
return mainEntry;
}
export function getRootView() {
return iosApp.rootView;
}
// NOTE: for backwards compatibility. Remove for 4.0.0.
let createRootFrame = true;
let started: boolean = false;
@@ -296,6 +304,12 @@ export function run(entry?: string | NavigationEntry) {
start(entry);
}
export function _resetRootView(entry?: NavigationEntry | string) {
createRootFrame = false;
mainEntry = typeof entry === "string" ? { moduleName: entry } : entry;
iosApp.setWindowContent();
}
export function getNativeApplication(): UIApplication {
return iosApp.nativeApp;
}