"Frame"クラスは、異なるページ間のナビゲーションのために責任がある論理ユニットを表します。 アプリケーションは、ビジネスロジックと要件に応じて、単一または複数のFrameインスタンスを持つことができます。
フレームにはdefaultPageプロパティが設定されている必要があります(必須)。 defaultPageの値として渡されたページは、フレームの初期化時にロードされます。 このidプロパティを使用して、フレームインスタンスへの参照を取得できます。
<Frame id="root-frame" defaultPage="main-page"/>
複数のフレームインスタンスを使用して、より複雑なアプリケーション構造を作成できます。たとえば、タブ項目ごとに異なるフレームを使用しながらTabViewを作成できます。
<TabView>
<TabViewItem title="First">
<Frame id="firstFrame" defaultPage="home/home-page" />
</TabViewItem>
<TabViewItem title="Second">
<Frame id="secondFrame" defaultPage="second/second-page" />
</TabViewItem>
</TabView>
NativeScriptのナビゲーションは、FrameAPIに基づいており、目的のフレームのnavigateメソッドを使用しています。 Frameインスタンスへの参照を取得するには、次のメソッドまたはプロパティを使用する必要があります。
const topmost = require("tns-core-modules/ui/frame").topmost;
const topmostFrame = topmost();
import { Frame, topmost } from "tns-core-modules/ui/frame";
const topmostFrame: Frame = topmost();
<Frame id="root-frame" defaultPage="main-page"/>
const getFrameById = require("tns-core-modules/ui/frame").getFrameById;
const currentFrame = getFrameById("root-frame");
import { getFrameById } from "tns-core-modules/ui/frame";
const currentFrame: Frame = getFrameById("root-frame");
function onTap(args) {
const button = args.object;
const page = button.page;
const myFrame = page.frame;
myFrame.navigate("secondary-page");
}
exports.onTap = onTap;
import { Button } from "tns-core-modules/ui/button";
import { Page } from "tns-core-modules/ui/page";
export function onTap(args) {
const button: Button = args.object;
const page: Page = button.page;
const myFrame: Frame = page.frame;
myFrame.navigate("secondary-page");
}
アプリケーションのデフォルト(初期)ページを読み込むには、Frame要素のdefaultPageプロパティを使用します。 以下の例では、アプリケーションは<project-folder>/app/home/first-page.xml内にあるページを読み込みます。
<Frame id="my-frame-id" defaultPage="home/first-page"/>
ページ間を移動するには、目的のFrameインスタンスの"navigate"メソッドを使用できます。
const getFrameById = require("tns-core-modules/ui/frame").getFrameById;
// Example using `getFrameById(frameId)` to get a `Frame` reference
// As an alternative, we could use `topmost()` method or `page.frame` property
const frame = getFrameById("my-frame-id");
frame.navigate("home/second-page");
import { getFrameById } from "tns-core-modules/ui/frame";
// Example using `getFrameById(frameId)` to get a `Frame` reference
// As an alternative, we could use `topmost()` method or `page.frame` property
const frame = getFrameById("my-frame-id");
frame.navigate("home/second-page");
navigateメソッドは"NavigationEntry"オブジェクトを受け入れます。
const frame = getFrameById("my-frame-id");
const navigationEntry = {
moduleName: "home/second-page",
context: { info: "something you want to pass to your page" },
animated: false
};
frame.navigate(navigationEntry);
const frame = getFrameById("my-frame-id");
// import { NavigationEntry } from "tns-core-modules/ui/frame";
const navigationEntry: NavigationEntry = {
moduleName: "home/second-page",
context: { info: "something you want to pass to your page" },
animated: false
};
frame.navigate(navigationEntry);
以下にNavigaitonEntryプロパティの完全なリストを示します。これらはすべてオプションです。 moduleNameもオプションですが、代わりにcreateを使用して、動的に作成されたページを渡すことができます。
プロパティ | 型 | 説明 |
---|---|---|
animated | boolean | アニメーションを使用して新しいページにナビゲートする場合はtrue、そうでない場合はfalse。 |
backstackVisible | boolean | ナビゲーションをバックスタックに記録する場合はtrue、そうでない場合はfalse。 パラメーターがfalseに設定されている場合、ページは表示されますが、一度そこからナビゲートすると、元のページに戻ることはできません。 |
bindingContext | any | ナビゲートするページのバインディングコンテキストになるオブジェクト。オプション。 |
clearHistory | boolean | ナビゲーション履歴をクリアする場合はtrue、そうでない場合はfalse。ログインページから移動するときに非常に便利です。 |
context | any | ページのonNavigatedToコールバックに渡されるオブジェクト。通常、これはページ間でデータを渡すために使用されます。オプション。 |
create | function | Viewインスタンスの作成に使用される関数。オプション。 |
moduleName | string | ロードするViewインスタンスを含むモジュールの名前。オプション。 |
transition | NavigationTransition | すべてのプラットフォームのオプションのナビゲーション遷移を指定します。指定されない場合、デフォルトのプラットフォーム遷移が使用されます。 |
transitionAndroid | NavigationTransition | Androidのオプションのナビゲーション遷移を指定します。指定されない場合、デフォルトのプラットフォーム遷移が使用されます。 |
transitioniOS | NavigationTransition | iOSのオプションのナビゲーション遷移を指定します。指定されない場合、デフォルトのプラットフォーム遷移が使用されます。 |
ナビゲーションを履歴に追加せずにページに遷移できます。 NavigationEntryのbackstackVisibleプロパティをfalseに設定します。 プロパティが false に設定されている場合、ページは表示されますが、一度そこから他のページへ遷移すると、元のページに戻ることはできません。
const frame = getFrameById("my-frame-id");
const navigationEntry = {
moduleName: "home/second-page",
backstackVisible: false
};
frame.navigate(navigationEntry);
const frame = getFrameById("my-frame-id");
// import { NavigationEntry } from "tns-core-modules/ui/frame";
const navigationEntry: NavigationEntry = {
moduleName: "home/second-page",
backstackVisible: false
};
frame.navigate(navigationEntry);
新しいページに移動して、ナビゲーション履歴全体を完全にクリアするか否かを決定できます。 NavigationEntryのclearHistoryプロパティをtrueに設定します。 これにより、ユーザーは以前にアクセスしたページに戻ることができなくなります。 これは、複数ページの認証プロセスがあり、ユーザーが正常にログインしてアプリケーションの開始ページにリダイレクトされたら、認証ページをクリアする場合に非常に便利です。
const frame = getFrameById("my-frame-id");
const navigationEntry = {
moduleName: "home/second-page",
clearHistory: true
};
frame.navigate(navigationEntry);
const frame = getFrameById("my-frame-id");
// import { NavigationEntry } from "tns-core-modules/ui/frame";
const navigationEntry: NavigationEntry = {
moduleName: "home/second-page",
clearHistory: true
};
frame.navigate(navigationEntry);
デフォルトでは、すべてのナビゲーションがアニメーション化され、それぞれのプラットフォームのデフォルトの遷移方法(iOSではUINavigationControllerトランジション、AndroidではFragmentトランジション)が使用されます。 遷移タイプを変更するには、NavigationEntryのnavigationTransitionプロパティを、 "NavigationTransition"インターフェイスに準拠するオブジェクトに設定します。 NavigationTransitionインタフェースは、4つのオプションのプロパティがあります。
const frame = getFrameById("my-frame-id");
const navigationEntry = {
moduleName: "home/second-page",
animated: true,
// Set up a transition property on page navigation.
transition: {
name: "slide",
duration: 380,
curve: "easeIn"
}
};
frame.navigate(navigationEntry);
const frame = getFrameById("my-frame-id");
// import { NavigationEntry } from "tns-core-modules/ui/frame";
// import { AnimationCurve } from "tns-core-modules/ui/enums";
const navigationEntry: NavigationEntry = {
moduleName: "home/second-page",
animated: true,
// Set up a transition property on page navigation.
transition: {
name: "slide",
duration: 380,
curve: AnimationCurve.easeIn
}
};
frame.navigate(navigationEntry);
すべてのフレーム内遷移のデフォルトの遷移方法を指定するには、フレームの遷移時にトランジションプロパティを設定します。
// const getFrameById = require("tns-core-modules/ui/frame").getFrameById;
// const myFrame = getFrameById("firstFrame");
myFrame.transition = { name: "flip" };
myFrame.navigate("main-page");
// const getFrameById = require("tns-core-modules/ui/frame").getFrameById;
// const frame = getFrameById("firstFrame");
frame.transition = { name: "flip" };
frame.navigate("main-page");
アプリ全体のすべてのナビゲーションにデフォルトの遷移方法を指定するには、Frameクラスの静的プロパティdefaultTransitionを設定します。
// const frameModule = require("tns-core-modules/ui/frame");
frameModule.Frame.defaultTransition = { name: "fade" };
// import * as frameModule from "tns-core-modules/ui/frame";
frameModule.Frame.defaultTransition = { name: "fade" };
プラットフォームごとに異なる遷移方法を指定するには、NavigationEntryのtransitioniOSおよびtransitionAndroidプロパティを使用します。
const navigationEntry = {
moduleName: "main-page",
animated: true,
// Set up platform specific transitions.
transitioniOS: {
name: "curl",
duration: 380,
curve: "easeIn"
},
transitionAndroid: {
name: "explode",
duration: 300,
curve: "easeOut"
}
};
const frame = getFrameById("my-frame");
frame.navigate(navigationEntry);
const navigationEntry: NavigationEntry = {
moduleName: "main-page",
animated: true,
// Set up platform specific transitions.
transitioniOS: {
name: "curl",
duration: 380,
curve: AnimationCurve.easeInOut
},
transitionAndroid: {
name: "explode",
duration: 300,
curve: AnimationCurve.spring
}
};
const frame = getFrameById("my-frame");
frame.navigate(navigationEntry);
nameプロパティを定義済みの遷移のいずれかに設定する代わりに、NavigationTransitionのインスタンスプロパティをTransitionから継承するクラスのインスタンスに設定できます。 プラットフォーム固有のコードを記述して遷移をアニメーション化することにより、カスタムのユーザー定義の遷移を作成できます。 そのためには、Transitionクラスから継承し、プラットフォームごとに1つのメソッドをオーバーライドする必要があります。 プラットフォーム固有のコードがあるため、コードを2つの別々のファイルに分ける必要があります。 例として、スケールアフィン変換を使用して、表示されているページを拡大しながら表示されていないページを縮小するカスタムトランジションを以下に示します。
custom-transition.android.js/ts
const transition = require("tns-core-modules/ui/transition");
const floatType = java.lang.Float.class.getField("TYPE").get(null);
const CustomTransition = (function (_super) {
__extends(CustomTransition, _super);
function CustomTransition() {
_super.apply(this, arguments);
}
CustomTransition.prototype.createAndroidAnimator = function(transitionType) {
const scaleValues = java.lang.reflect.Array.newInstance(floatType, 2);
switch (transitionType) {
case transition.AndroidTransitionType.enter:
case transition.AndroidTransitionType.popEnter:
scaleValues[0] = 0;
scaleValues[1] = 1;
break;
case transition.AndroidTransitionType.exit:
case transition.AndroidTransitionType.popExit:
scaleValues[0] = 1;
scaleValues[1] = 0;
break;
default:
break;
}
const objectAnimators = java.lang.reflect.Array.newInstance(android.animation.Animator.class, 2);
objectAnimators[0] = android.animation.ObjectAnimator.ofFloat(null, "scaleX", scaleValues);
objectAnimators[1] = android.animation.ObjectAnimator.ofFloat(null, "scaleY", scaleValues);
const animatorSet = new android.animation.AnimatorSet();
animatorSet.playTogether(objectAnimators);
const duration = this.getDuration();
if (duration !== undefined) {
animatorSet.setDuration(duration);
}
animatorSet.setInterpolator(this.getCurve());
return animatorSet;
};
return CustomTransition;
})(transition.Transition);
exports.CustomTransition = CustomTransition;
import { Transition, AndroidTransitionType } from "tns-core-modules/ui/transition";
export class CustomTransition extends Transition {
public createAndroidAnimator(transitionType: string): android.animation.Animator {
const scaleValues = (<any>Array).create("float", 2);
switch (transitionType) {
case AndroidTransitionType.enter:
case AndroidTransitionType.popEnter:
scaleValues[0] = 0;
scaleValues[1] = 1;
break;
case AndroidTransitionType.exit:
case AndroidTransitionType.popExit:
scaleValues[0] = 1;
scaleValues[1] = 0;
break;
default:
break;
}
const objectAnimators = (<any>Array).create(android.animation.Animator, 2);
objectAnimators[0] = android.animation.ObjectAnimator.ofFloat(null, "scaleX", scaleValues);
objectAnimators[1] = android.animation.ObjectAnimator.ofFloat(null, "scaleY", scaleValues);
const animatorSet = new android.animation.AnimatorSet();
animatorSet.playTogether(objectAnimators);
const duration = this.getDuration();
if (duration !== undefined) {
animatorSet.setDuration(duration);
}
animatorSet.setInterpolator(this.getCurve());
return animatorSet;
}
}
custom-transition.ios.js/ts
// const transition = require("tns-core-modules/ui/transition");
const CustomTransitionIOS = (function (_super) {
__extends(CustomTransition, _super);
function CustomTransition() {
_super.apply(this, arguments);
}
CustomTransition.prototype.animateIOSTransition = function(containerView, fromView, toView, operation, completion) {
toView.transform = CGAffineTransformMakeScale(0, 0);
fromView.transform = CGAffineTransformIdentity;
switch (operation) {
case UINavigationControllerOperation.UINavigationControllerOperationPush:
containerView.insertSubviewAboveSubview(toView, fromView);
break;
case UINavigationControllerOperation.UINavigationControllerOperationPop:
containerView.insertSubviewBelowSubview(toView, fromView);
break;
default:
break;
}
const duration = this.getDuration();
const curve = this.getCurve();
UIView.animateWithDurationAnimationsCompletion(duration, () => {
UIView.setAnimationCurve(curve);
toView.transform = CGAffineTransformIdentity;
fromView.transform = CGAffineTransformMakeScale(0, 0);
}, completion);
};
return CustomTransitionIOS;
})(transition.Transition);
exports.CustomTransitionIOS = CustomTransitionIOS;
// import { Transition } from "tns-core-modules/ui/transition";
declare let UINavigationControllerOperation: any; // or use tns-platform-declarations
export class CustomTransitionIOS extends Transition {
public animateIOSTransition(containerView: UIView,
fromView: UIView,
toView: UIView,
operation: UINavigationControllerOperation,
completion: (finished: boolean) => void): void {
const originalToViewTransform = toView.transform;
const originalFromViewTransform = fromView.transform;
// http://stackoverflow.com/questions/216076/uiview-scale-to-0-using-cgaffinetransformmakescale
const scaleTransform = CGAffineTransformMakeScale(0.0001, 0.0001);
toView.transform = scaleTransform;
fromView.transform = CGAffineTransformIdentity;
switch (operation) {
case UINavigationControllerOperation.UINavigationControllerOperationPush:
containerView.insertSubviewAboveSubview(toView, fromView);
break;
case UINavigationControllerOperation.UINavigationControllerOperationPop:
containerView.insertSubviewBelowSubview(toView, fromView);
break;
default:
break;
}
const duration = this.getDuration();
const curve = this.getCurve();
UIView.animateWithDurationAnimationsCompletion(duration, () => {
UIView.setAnimationCurve(curve);
toView.transform = CGAffineTransformIdentity;
fromView.transform = scaleTransform;
}, (finished: boolean) => {
toView.transform = originalToViewTransform;
fromView.transform = originalFromViewTransform;
completion(finished);
});
}
}
各フレームは、ナビゲーションスタックでユーザーがアクセスしたページを追跡します。 前のページに戻るに"goBack"は、現在のフレームインスタンスのメソッドを使用する必要があります。 バックナビゲーションが可能であることを確認するには、"canGoBackboolean"プロパティを使用します。
// const getFrameById = require("tns-core-modules/ui/frame").getFrameById;
const myFrame = getFrameById("my-frame");
myFrame.goBack();
// import { getFrameById } from "tns-core-modules/ui/frame";
const myFrame = getFrameById("my-frame");
myFrame.goBack();
より動的な画面遷移方法は、ナビゲートしたいページのインスタンスを返す関数を提供することにより実行できます。
const frame = getFrameById("my-frame-id");
frame.navigate({
create: () => {
const stack = new StackLayout();
const label = new Label();
label.text = "Hello, world!";
stack.addChild(label);
const page = new Page();
page.content = stack;
return page;
}
});
const frame = getFrameById("my-frame-id");
frame.navigate({
create: () => {
const stack = new StackLayout();
const label = new Label();
label.text = "Hello, world!";
stack.addChild(label);
const page = new Page();
page.content = stack;
return page;
}
});
別のページに移動すると、NavigationEntryオブジェクトを使用してページにコンテキストを渡すことができます。 NavigationEntry には、次の2つの異なる(オプションの)プロパティがあります。
context
プロパティ
exports.onNavigate = function(args) {
const button = args.object;
const page = button.page;
const frame = page.frame;
const navEntryWithContext = {
moduleName: "home/second-page",
context: {
name: "John",
age: 25,
isProgramer: true
}
};
frame.navigate(navEntryWithContext);
};
import { EventData } from "tns-core-modules/data/observable";
import { Button } from "tns-core-modules/ui/button";
import { Page } from "tns-core-modules/ui/page";
import { Frame, NavigationEntry } from "tns-core-modules/ui/frame";
export function onNavigate(args: EventData) {
let button = <Button>args.object;
let page = <Page>button.page;
let frame = <Frame>page.frame;
let navEntryWithContext: NavigationEntry = {
moduleName: "home/second-ts-page",
context: {
name: "John",
age: 25,
isProgramer: true
}
};
frame.navigate(navEntryWithContext);
}
bindingContext
プロパティ
const navEntryWithBindingContext = {
moduleName: "home/second-ts-page",
// when using bindingContext the landing page will automatically
// receive and set this object as page.bindingContext with navigatedTo event
bindingContext: {
name: "John",
age: 25,
isProgramer: true
}
};
const navEntryWithBindingContext: NavigationEntry = {
moduleName: "home/second-ts-page",
// when using bindingContext the landing page will automatically
// receive and set this object as page.bindingContext with navigatedTo event
bindingContext: {
name: "John",
age: 25,
isProgramer: true
}
};
両方のプロパティは、ナビゲート中にコンテキストを渡すために使用されますが、bindingContextプロパティはランディングページのバインディングコンテキストを自動的に割り当てます。
bindingContextで送信されたコンテキストは、ナビゲートされた(ランディング)ページのバインディングコンテキストとして自動的に割り当てられます。 contextプロパティを介して送信されたコンテキストの取得は、2つの異なるアプローチで実現できます。
function onNavigatedTo(args) {
const page = args.object;
const navigationContext = page.navigationContext;
// The navigation event arguments are of type NavigatedData and provide another way to grab the passed context
const context = args.context;
page.bindingContext = navigationContext;
}
exports.onNavigatedTo = onNavigatedTo;
import { Page, NavigatedData } from "tns-core-modules/ui/page";
// Event handler for Page "navigatedTo" event attached in details-page.xml e.g.
export function onNavigatedTo(args: NavigatedData): void {
const page: Page = <Page>args.object;
const navigationContext = page.navigationContext;
// The navigation event arguments are of type NavigatedData and provide another way to grab the passed context
const context = args.context;
page.bindingContext = navigationContext;
}
actionBarVisibilityは、現在のフレームのiOSのナビゲーションバーとAndroidのアクションバーの可視性を制御するプロパティです。 フレームに直接設定する必要があり、auto、never、alwaysの3つのオプション値があります。
auto
- これはデフォルトのactionBarVisibility値であり、各PageのActionBarの可視性を個別に指定できます。never
- この値は、現在のFrameのActionBarを非表示にします。always
- これは、ActionBarコンポーネントが常に現在のFrameに対して表示されることを指定します。
PageにActionBarが宣言されていない場合、デフォルトのアクションバーが表示されます。<Frame id="my-frame-id" actionBarVisibility="never" defaultPage="home/home-page"/>