Skip to content

perf(ios): gridlayout optimizations #10582

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions apps/ui/src/grid-layout/grid-layout-page.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { EventData, GestureStateTypes, PanGestureEventData, Page, View, ScrollView, GridLayout } from '@nativescript/core';

var page;
export function pageLoaded(args: EventData) {
page = <Page>args.object;
}

let currentDeltaY = 0;
export function panLayout(args: PanGestureEventData) {
const view = <View>args.object;
const scrollView = <ScrollView>view.parent;

if (args.state === GestureStateTypes.began) {
currentDeltaY = 0;
scrollView.isScrollEnabled = false;
} else if (args.state === GestureStateTypes.changed) {
const diff = args.deltaY - currentDeltaY;
view.translateY += diff;
currentDeltaY = args.deltaY;
} else if (args.state === GestureStateTypes.ended) {
scrollView.isScrollEnabled = true;
}
}

let isShowingGridLayout: boolean = true;

export function showHide() {
let gridContainer = page.getViewById('grid-container');
isShowingGridLayout = !isShowingGridLayout;

if (!isShowingGridLayout) {
console.info('hiding grid');
gridContainer.visibility = 'hidden';
} else {
console.info('showing grid');
gridContainer.visibility = 'visible';
}
}
79 changes: 79 additions & 0 deletions apps/ui/src/grid-layout/grid-layout-page.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
<Page xmlns="http://schemas.nativescript.org/tns.xsd" loaded="pageLoaded" class="page">
<ScrollView id="grid-layout" height="100%">
<GridLayout height="80%" backgroundColor="red" rows="auto auto">
<StackLayout backgroundColor="green">
<Button backgroundColor="mediumblue" color="#fff" height="42" width="170" fontSize="20" tap="showHide" text="Toggle Show/Hide"></Button>
</StackLayout>
<StackLayout row="1">
<GridLayout id="grid-container" columns="* auto * 45 * * *" rows="* auto 50" height="400">
<StackLayout col="0" row="0" backgroundColor='maroon'>
<Label text="TNT" color="#fff" fontSize="22"/>
</StackLayout>
<StackLayout col="1" row="0" backgroundColor="blue">
<Label text="DAM" color="#fff" fontSize="22"/>
</StackLayout>
<StackLayout col="2" row="0" backgroundColor="salmon">
<Label text="BAR" color="#fff" fontSize="22"/>
</StackLayout>
<StackLayout col="3" row="0" backgroundColor="olive">
<Label text="OLD" color="#fff" fontSize="22"/>
</StackLayout>
<StackLayout col="4" row="0" backgroundColor="cyan">
<Label text="OUR" color="#fff" fontSize="22"/>
</StackLayout>
<StackLayout col="5" row="0" backgroundColor="darkcyan">
<Label text="THE" color="#fff" fontSize="22"/>
</StackLayout>
<StackLayout col="6" row="0" backgroundColor="limegreen">
<Label text="PER" color="#fff" fontSize="22"/>
</StackLayout>

<StackLayout col="0" row="1" backgroundColor='sandybrown'>
<Label text="ROW" color="#fff" fontSize="22"/>
</StackLayout>
<StackLayout col="1" row="1" backgroundColor="teal">
<Label text="WIP" color="#fff" fontSize="22"/>
</StackLayout>
<StackLayout col="2" row="1" backgroundColor="salmon">
<Label text="HIP" color="#fff" fontSize="22"/>
</StackLayout>
<StackLayout col="3" row="1" backgroundColor="sienna">
<Label text="LIP" color="#fff" fontSize="22"/>
</StackLayout>
<StackLayout col="4" row="1" backgroundColor="red">
<Label text="SON" color="#fff" fontSize="22"/>
</StackLayout>
<StackLayout col="5" row="1" backgroundColor="darkcyan">
<Label text="MOO" color="#fff" fontSize="22"/>
</StackLayout>
<StackLayout col="6" row="1" backgroundColor="purple">
<Label text="DID" color="#fff" fontSize="22"/>
</StackLayout>

<StackLayout col="0" row="2" backgroundColor='silver'>
<Label text="VID" color="#fff" fontSize="22"/>
</StackLayout>
<StackLayout col="1" row="2" backgroundColor="peru">
<Label text="FOR" color="#fff" fontSize="22"/>
</StackLayout>
<StackLayout col="2" row="2" backgroundColor="seagreen">
<Label text="LOB" color="#fff" fontSize="22"/>
</StackLayout>
<StackLayout col="3" row="2" backgroundColor="olivedrab">
<Label text="MIN" color="#fff" fontSize="22"/>
</StackLayout>
<StackLayout col="4" row="2" backgroundColor="orchid">
<Label text="BIN" color="#fff" fontSize="22"/>
</StackLayout>
<StackLayout col="5" row="2" backgroundColor="orangered">
<Label text="END" color="#fff" fontSize="22"/>
</StackLayout>
<StackLayout col="6" row="2" backgroundColor="navy">
<Label text="ACE" color="#fff" fontSize="22"/>
</StackLayout>

</GridLayout>
</StackLayout>
</GridLayout>
</ScrollView>
</Page>
1 change: 1 addition & 0 deletions apps/ui/src/main-page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ export function pageLoaded(args: EventData) {
examples.set('nested-frames', 'nested-frames/main-page');
examples.set('media-queries', 'media-queries/main-page');
examples.set('screen-qualifiers', 'screen-qualifiers/main-page');
examples.set('grid-layout', 'grid-layout/grid-layout-page');
page.bindingContext = new MainPageViewModel(wrapLayout, examples);

const parent = page.getViewById('parentLayout');
Expand Down
147 changes: 75 additions & 72 deletions packages/core/ui/layouts/grid-layout/index.ios.ts
Original file line number Diff line number Diff line change
Expand Up @@ -410,54 +410,61 @@ class MeasureHelper {
}

public addMeasureSpec(measureSpec: MeasureSpecs): void {
// Get column stats
let size = measureSpec.getColumnIndex() + measureSpec.getColumnSpan();
for (let i = measureSpec.getColumnIndex(); i < size; i++) {
const columnGroup: ItemGroup = this.columns[i];
if (columnGroup.getIsAuto()) {
measureSpec.autoColumnsCount++;
} else if (columnGroup.getIsStar()) {
measureSpec.starColumnsCount += columnGroup.rowOrColumn.value;
} else if (columnGroup.getIsAbsolute()) {
measureSpec.pixelWidth += layout.toDevicePixels(columnGroup.rowOrColumn.value);
const columnIndex = measureSpec.getColumnIndex();
const rowIndex = measureSpec.getRowIndex();
const columnSpan = measureSpec.getColumnSpan();
const rowSpan = measureSpec.getRowSpan();

const updateMeasureSpecCounts = (group: ItemGroup, measureSpec: MeasureSpecs, isColumn: boolean) => {
if (group.getIsAuto()) {
isColumn ? measureSpec.autoColumnsCount++ : measureSpec.autoRowsCount++;
} else if (group.getIsStar()) {
if (isColumn) {
measureSpec.starColumnsCount += group.rowOrColumn.value;
} else {
measureSpec.starRowsCount += group.rowOrColumn.value;
}
} else if (group.getIsAbsolute()) {
if (isColumn) {
measureSpec.pixelWidth += layout.toDevicePixels(group.rowOrColumn.value);
} else {
measureSpec.pixelHeight += layout.toDevicePixels(group.rowOrColumn.value);
}
}
}
};

if (measureSpec.autoColumnsCount > 0 && measureSpec.starColumnsCount === 0) {
// Determine which auto columns are affected by this element
for (let i = measureSpec.getColumnIndex(); i < size; i++) {
const columnGroup: ItemGroup = this.columns[i];
if (columnGroup.getIsAuto()) {
columnGroup.measureToFix++;
const updateAutoGroups = (index: number, size: number, groups: ItemGroup[], measureSpec: MeasureSpecs, isColumn: boolean) => {
for (let i = index; i < size; i++) {
const group: ItemGroup = groups[i];
if (group.getIsAuto()) {
group.measureToFix++;
}
}
};

// Process columns
let size = columnIndex + columnSpan;
for (let i = columnIndex; i < size; i++) {
updateMeasureSpecCounts(this.columns[i], measureSpec, true);
}

// Get row stats
size = measureSpec.getRowIndex() + measureSpec.getRowSpan();
for (let i = measureSpec.getRowIndex(); i < size; i++) {
const rowGroup: ItemGroup = this.rows[i];
if (rowGroup.getIsAuto()) {
measureSpec.autoRowsCount++;
} else if (rowGroup.getIsStar()) {
measureSpec.starRowsCount += rowGroup.rowOrColumn.value;
} else if (rowGroup.getIsAbsolute()) {
measureSpec.pixelHeight += layout.toDevicePixels(rowGroup.rowOrColumn.value);
}
if (measureSpec.autoColumnsCount > 0 && measureSpec.starColumnsCount === 0) {
updateAutoGroups(columnIndex, size, this.columns, measureSpec, true);
}

// Process rows
size = rowIndex + rowSpan;
for (let i = rowIndex; i < size; i++) {
updateMeasureSpecCounts(this.rows[i], measureSpec, false);
}

if (measureSpec.autoRowsCount > 0 && measureSpec.starRowsCount === 0) {
// Determine which auto rows are affected by this element
for (let i = measureSpec.getRowIndex(); i < size; i++) {
const rowGroup: ItemGroup = this.rows[i];
if (rowGroup.getIsAuto()) {
rowGroup.measureToFix++;
}
}
updateAutoGroups(rowIndex, size, this.rows, measureSpec, false);
}

this.columns[measureSpec.getColumnIndex()].children.push(measureSpec);
this.rows[measureSpec.getRowIndex()].children.push(measureSpec);
// Add measureSpec to children
this.columns[columnIndex].children.push(measureSpec);
this.rows[rowIndex].children.push(measureSpec);
}

public clearMeasureSpecs(): void {
Expand All @@ -479,25 +486,25 @@ class MeasureHelper {
}

init(): void {
const rows = this.rows.length;
if (rows === 0) {
this.singleRowGroup.setIsLengthInfinity(this.infinityHeight);
this.rows.push(this.singleRowGroup);
this.fakeRowAdded = true;
} else if (rows > 1 && this.fakeRowAdded) {
this.rows.splice(0, 1);
this.fakeRowAdded = false;
}

const cols = this.columns.length;
if (cols === 0) {
this.fakeColumnAdded = true;
this.singleColumnGroup.setIsLengthInfinity(this.infinityWidth);
this.columns.push(this.singleColumnGroup);
} else if (cols > 1 && this.fakeColumnAdded) {
this.columns.splice(0, 1);
this.fakeColumnAdded = false;
}
const handleSingleGroup = (groups: ItemGroup[], singleGroup: ItemGroup, infinityLength: boolean, fakeGroupAdded: boolean, setFakeGroupAdded: (value: boolean) => void): void => {
const length = groups.length;
if (length === 0) {
singleGroup.setIsLengthInfinity(infinityLength);
groups.push(singleGroup);
setFakeGroupAdded(true);
} else if (length > 1 && fakeGroupAdded) {
groups.splice(0, 1);
setFakeGroupAdded(false);
}
};

handleSingleGroup(this.rows, this.singleRowGroup, this.infinityHeight, this.fakeRowAdded, (value) => {
this.fakeRowAdded = value;
});

handleSingleGroup(this.columns, this.singleColumnGroup, this.infinityWidth, this.fakeColumnAdded, (value) => {
this.fakeColumnAdded = value;
});

MeasureHelper.initList(this.rows);
MeasureHelper.initList(this.columns);
Expand All @@ -515,25 +522,21 @@ class MeasureHelper {
measureSpec.measured = true;
}

if (measureSpec.autoColumnsCount > 0 && measureSpec.starColumnsCount === 0) {
const size = measureSpec.getColumnIndex() + measureSpec.getColumnSpan();
for (let i = measureSpec.getColumnIndex(); i < size; i++) {
const columnGroup: ItemGroup = this.columns[i];
if (columnGroup.getIsAuto()) {
columnGroup.currentMeasureToFixCount++;
const updateCurrentMeasureToFixCount = (index: number, span: number, groups: ItemGroup[], autoCount: number, starCount: number) => {
if (autoCount > 0 && starCount === 0) {
const size = index + span;
for (let i = index; i < size; i++) {
const group = groups[i];
if (group.getIsAuto()) {
group.currentMeasureToFixCount++;
}
}
}
}
};

if (measureSpec.autoRowsCount > 0 && measureSpec.starRowsCount === 0) {
const size = measureSpec.getRowIndex() + measureSpec.getRowSpan();
for (let i = measureSpec.getRowIndex(); i < size; i++) {
const rowGroup: ItemGroup = this.rows[i];
if (rowGroup.getIsAuto()) {
rowGroup.currentMeasureToFixCount++;
}
}
}
updateCurrentMeasureToFixCount(measureSpec.getColumnIndex(), measureSpec.getColumnSpan(), this.columns, measureSpec.autoColumnsCount, measureSpec.starColumnsCount);

updateCurrentMeasureToFixCount(measureSpec.getRowIndex(), measureSpec.getRowSpan(), this.rows, measureSpec.autoRowsCount, measureSpec.starRowsCount);
}

private fixColumns(): void {
Expand Down
Loading