Skip to content

Commit 8b6c6eb

Browse files
authored
feat(ios): SplitView UI component (#10942)
1 parent 8fea9e5 commit 8b6c6eb

21 files changed

+842
-54
lines changed

apps/toolbox/src/app-root.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,8 @@
11
<Frame defaultPage="main-page">
22
</Frame>
3+
4+
<!-- Test SplitView
5+
Must be root component of the app to work properly
6+
-->
7+
<!-- <Frame defaultPage="split-view/split-view-root">
8+
</Frame> -->

apps/toolbox/src/main.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1-
import { Application } from '@nativescript/core';
1+
import { Application, SplitView } from '@nativescript/core';
22

3-
Application.run({ moduleName: 'app-root' });
3+
// Application.run({ moduleName: 'app-root' });
4+
5+
SplitView.SplitStyle = 'triple';
6+
Application.run({ moduleName: 'split-view/split-view-root' });

apps/toolbox/src/pages/list-page-model-sticky.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { Observable, Dialogs, DialogStrings, View, EventData, SearchEventData } from '@nativescript/core';
2+
import { getItemCallbacks } from '../split-view/split-view-root';
23
type CountryListType = Array<{ title: string; items: Array<{ name: string; code: string; flag: string; isVisible?: boolean }> }>;
34
export class ListPageModelSticky extends Observable {
45
countries: CountryListType = [
@@ -1380,11 +1381,14 @@ export class ListPageModelSticky extends Observable {
13801381
}
13811382

13821383
componentsItemTap(args): void {
1383-
Dialogs.alert({
1384-
title: 'Want to play?',
1385-
message: 'Nothing to see here yet. Feel free to add more examples to play around.',
1386-
okButtonText: DialogStrings.OK,
1387-
});
1384+
const letter = this.countries[args.section];
1385+
console.log('Tapped on category: ' + letter.title);
1386+
if (letter.items?.length) {
1387+
const country = letter.items[args.index];
1388+
console.log('Tapped on country: ' + country.name);
1389+
// used in splitview demo
1390+
getItemCallbacks().forEach((callback) => callback(`${country.name} was selected.`));
1391+
}
13881392
}
13891393

13901394
itemLoading(args: EventData): void {

apps/toolbox/src/pages/list-page-sticky.xml

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
<Page xmlns="http://schemas.nativescript.org/tns.xsd" navigatingTo="navigatingTo" actionBarHidden="false" androidOverflowEdge="bottom">
2-
<Page.actionBar>
3-
<ActionBar>
4-
<Label text="Components" class="header"/>
5-
</ActionBar>
6-
</Page.actionBar>
2+
<ActionBar title="Countries">
3+
</ActionBar>
74

85
<GridLayout backgroundColor="#efefef">
96
<ListView class="list-group" items="{{ countries }}" itemTap="{{ componentsItemTap }} " separatorColor="#00000000" itemTemplateSelector="{{ selectItemTemplate }}" stickyHeader="true" sectioned="true" stickyHeaderTopPadding="false" stickyHeaderTemplate="<GridLayout><Label text='{{ title }}' fontSize='18' fontWeight='bold' color='#009bff' padding='8 0 8 12' borderBottomWidth='1' borderBottomColor='#ccc' borderTopWidth='1' borderTopColor='#ccc' backgroundColor='#fff' /></GridLayout>" stickyHeaderHeight="45" itemLoading="{{ itemLoading }}" showSearch="true" searchAutoHide="true" searchChange="{{ onSearchTextChange }}">
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { Observable, EventData, Page, SplitView, ItemEventData } from '@nativescript/core';
2+
import { getItemCallbacks } from './split-view-root';
3+
let page: Page;
4+
5+
export function navigatingTo(args: EventData) {
6+
page = <Page>args.object;
7+
page.bindingContext = new SplitViewPrimaryModel();
8+
}
9+
10+
export class SplitViewPrimaryModel extends Observable {
11+
items: string[] = [];
12+
13+
constructor() {
14+
super();
15+
this.items = Array.from({ length: 20 }, (_, i) => `Item ${i + 1}`);
16+
}
17+
18+
onItemTap(args: ItemEventData) {
19+
console.log('args.index', args.index);
20+
SplitView.getInstance()?.showSecondary();
21+
getItemCallbacks().forEach((callback) => callback(this.items[args.index]));
22+
}
23+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<Page xmlns="http://schemas.nativescript.org/tns.xsd" navigatingTo="navigatingTo" class="page">
2+
<ActionBar title="Primary View" class="action-bar" iosLargeTitle="true"></ActionBar>
3+
4+
<!-- Primary column (master) -->
5+
<GridLayout rows="auto,*">
6+
<!-- <Label text="Primary" marginBottom="12" marginLeft="8" fontSize="22" fontWeight="bold" /> -->
7+
<ListView row="1" items="{{ items }}" itemTap="{{ onItemTap }}" backgroundColor="white">
8+
<ListView.itemTemplate>
9+
<GridLayout padding="12">
10+
<Label text="{{ $value }}" fontSize="18" />
11+
</GridLayout>
12+
</ListView.itemTemplate>
13+
</ListView>
14+
</GridLayout>
15+
16+
</Page>
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { Observable, EventData, Page } from '@nativescript/core';
2+
let page: Page;
3+
4+
export function navigatingTo(args: EventData) {
5+
page = <Page>args.object;
6+
page.bindingContext = new SplitViewModel();
7+
}
8+
9+
export class SplitViewModel extends Observable {}
10+
11+
let itemCallbacks: Array<(item: any) => void> = [];
12+
export function setItemCallbacks(changeItem: Array<(item: any) => void>) {
13+
itemCallbacks.push(...changeItem);
14+
}
15+
export function getItemCallbacks() {
16+
return itemCallbacks;
17+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<SplitView xmlns="http://schemas.nativescript.org/tns.xsd" displayMode="twoBesideSecondary" splitBehavior="tile" preferredPrimaryColumnWidthFraction="0.25" preferredSupplementaryColumnWidthFraction="0.33"
2+
preferredInspectorColumnWidthFraction="0.20">
3+
<Frame splitRole="primary" defaultPage="split-view/split-view-primary">
4+
5+
</Frame>
6+
7+
<Frame splitRole="secondary" defaultPage="split-view/split-view-secondary">
8+
9+
</Frame>
10+
11+
<Frame splitRole="supplementary" defaultPage="split-view/split-view-supplement">
12+
13+
</Frame>
14+
15+
<Frame splitRole="inspector" defaultPage="pages/list-page-sticky">
16+
17+
</Frame>
18+
19+
</SplitView>
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { Observable, EventData, Page, SplitView } from '@nativescript/core';
2+
import { setItemCallbacks } from './split-view-root';
3+
let page: Page;
4+
5+
export function navigatingTo(args: EventData) {
6+
page = <Page>args.object;
7+
page.bindingContext = new SplitViewSecondaryModel();
8+
}
9+
10+
export class SplitViewSecondaryModel extends Observable {
11+
selectedItem = `Select an item from Primary.`;
12+
showInspectorButton = false;
13+
14+
constructor() {
15+
super();
16+
setItemCallbacks([this.changeItem.bind(this)]);
17+
SplitView.getInstance().on('inspectorChange', (args: any) => {
18+
console.log('inspectorChange', args.data?.showing);
19+
this.showInspectorButton = !args.data?.showing;
20+
this.notifyPropertyChange('showInspectorButton', this.showInspectorButton);
21+
});
22+
}
23+
toggle() {
24+
SplitView.getInstance()?.showPrimary();
25+
}
26+
27+
toggleInspector() {
28+
SplitView.getInstance()?.showInspector();
29+
}
30+
31+
changeItem(item: any) {
32+
this.selectedItem = item;
33+
this.notifyPropertyChange('selectedItem', item);
34+
}
35+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<Page xmlns="http://schemas.nativescript.org/tns.xsd" navigatingTo="navigatingTo" class="page">
2+
<ActionBar title="Secondary View" class="action-bar">
3+
</ActionBar>
4+
<!-- Secondary column (detail) -->
5+
<StackLayout class="p-16">
6+
<Label text="Secondary" marginBottom="12" fontSize="22" fontWeight="bold" />
7+
<Label text="{{ selectedItem }}" textWrap="true" tap="{{toggle}}" />
8+
<Label text="Show Inspector" tap="{{toggleInspector}}" class="m-t-10 font-weight-bold" visibility="{{ showInspectorButton ? 'visible' : 'collapsed' }}" />
9+
</StackLayout>
10+
11+
</Page>

0 commit comments

Comments
 (0)