From 9ae7acbdf14f4b12bd502e0b1128186685441559 Mon Sep 17 00:00:00 2001 From: Martin Yankov Date: Tue, 4 Dec 2018 09:55:14 +0200 Subject: [PATCH] fix(listview): incorrect layout when scroll --- .../ui-tests-app/issues/issue-ng-repo-1626.ts | 31 +++++++++++++++++++ .../issues/issue-ng-repo-1626.xml | 28 +++++++++++++++++ tns-core-modules/ui/core/view/view-common.ts | 7 ++++- tns-core-modules/ui/core/view/view.d.ts | 8 ++++- tns-core-modules/ui/core/view/view.ios.ts | 2 +- .../ui/list-view/list-view.ios.ts | 2 ++ 6 files changed, 75 insertions(+), 3 deletions(-) create mode 100644 apps/app/ui-tests-app/issues/issue-ng-repo-1626.ts create mode 100644 apps/app/ui-tests-app/issues/issue-ng-repo-1626.xml diff --git a/apps/app/ui-tests-app/issues/issue-ng-repo-1626.ts b/apps/app/ui-tests-app/issues/issue-ng-repo-1626.ts new file mode 100644 index 0000000000..f52d419ffd --- /dev/null +++ b/apps/app/ui-tests-app/issues/issue-ng-repo-1626.ts @@ -0,0 +1,31 @@ +import { fromObject } from "tns-core-modules/data/observable"; + +export function onLoaded(args) { + const page = args.object; + page.bindingContext = fromObject({ + items: [ + { id: 1, name: "Ter Stegen", role: "Goalkeeper" }, + { id: 3, name: "Piqué", role: "Defender" }, + { id: 4, name: "I. Rakitic", role: "Midfielder" }, + { id: 5, name: "Sergio", role: "Midfielder" }, + { id: 6, name: "Denis Suárez", role: "Midfielder\nSecond line for the sake of testing" }, + { id: 7, name: "Arda", role: "Midfielder" }, + { id: 8, name: "A. Iniesta", role: "Midfielder" }, + { id: 9, name: "Suárez", role: "Forward" }, + { id: 10, name: "Messi", role: "Forward" }, + { id: 11, name: "Neymar", role: "Forward\nSecond line for the sake of testing" }, + { id: 12, name: "Rafinha", role: "Midfielder\nSecond line for the sake of testing" }, + { id: 13, name: "Cillessen", role: "Goalkeeper\nSecond line for the sake of testing" }, + { id: 14, name: "Mascherano", role: "Defender" }, + { id: 17, name: "Paco Alcácer", role: "Forward" }, + { id: 18, name: "Jordi Alba", role: "Defender\nSecond line for the sake of testing" }, + { id: 19, name: "Digne", role: "Defender" }, + { id: 20, name: "Sergi Roberto", role: "Midfielder\nSecond line for the sake of testing" }, + { id: 21, name: "André Gomes", role: "Midfielder\nSecond line for the sake of testing" }, + { id: 22, name: "Aleix Vidal", role: "Midfielder" }, + { id: 23, name: "Umtiti", role: "Defender" }, + { id: 24, name: "Mathieu", role: "Defender" }, + { id: 25, name: "Masip", role: "Goalkeeper" }, + ] + }); +} \ No newline at end of file diff --git a/apps/app/ui-tests-app/issues/issue-ng-repo-1626.xml b/apps/app/ui-tests-app/issues/issue-ng-repo-1626.xml new file mode 100644 index 0000000000..b681a2c022 --- /dev/null +++ b/apps/app/ui-tests-app/issues/issue-ng-repo-1626.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tns-core-modules/ui/core/view/view-common.ts b/tns-core-modules/ui/core/view/view-common.ts index 64ebfa13ab..48625c0683 100644 --- a/tns-core-modules/ui/core/view/view-common.ts +++ b/tns-core-modules/ui/core/view/view-common.ts @@ -6,7 +6,8 @@ import { import { ViewBase, Property, booleanConverter, EventData, layout, - getEventOrGestureName, traceEnabled, traceWrite, traceCategories + getEventOrGestureName, traceEnabled, traceWrite, traceCategories, + InheritedProperty } from "../view-base"; import { HorizontalAlignment, VerticalAlignment, Visibility, Length, PercentLength } from "../../styling/style-properties"; @@ -589,6 +590,7 @@ export abstract class ViewCommon extends ViewBase implements ViewDefinition { public isEnabled: boolean; public isUserInteractionEnabled: boolean; public iosOverflowSafeArea: boolean; + public iosOverflowSafeAreaEnabled: boolean; get isLayoutValid(): boolean { return this._isLayoutValid; @@ -1032,3 +1034,6 @@ isUserInteractionEnabledProperty.register(ViewCommon); export const iosOverflowSafeAreaProperty = new Property({ name: "iosOverflowSafeArea", defaultValue: false, valueConverter: booleanConverter }); iosOverflowSafeAreaProperty.register(ViewCommon); + +export const iosOverflowSafeAreaEnabledProperty = new InheritedProperty({ name: "iosOverflowSafeAreaEnabled", defaultValue: true, valueConverter: booleanConverter }); +iosOverflowSafeAreaEnabledProperty.register(ViewCommon); diff --git a/tns-core-modules/ui/core/view/view.d.ts b/tns-core-modules/ui/core/view/view.d.ts index 83efcd1842..d638efc1ee 100644 --- a/tns-core-modules/ui/core/view/view.d.ts +++ b/tns-core-modules/ui/core/view/view.d.ts @@ -3,7 +3,7 @@ */ /** */ /// Include global typings -import { ViewBase, Property, EventData, Color } from "../view-base"; +import { ViewBase, Property, InheritedProperty, EventData, Color } from "../view-base"; import { Animation, AnimationDefinition, AnimationPromise } from "../../animation"; import { HorizontalAlignment, VerticalAlignment, Visibility, Length, PercentLength } from "../../styling/style-properties"; import { GestureTypes, GestureEventData, GesturesObserver } from "../../gestures"; @@ -349,6 +349,11 @@ export abstract class View extends ViewBase { */ iosOverflowSafeArea: boolean; + /** + * Enables or disables the iosOverflowSafeArea property for all children. This property is iOS specific. Default value: true + */ + iosOverflowSafeAreaEnabled: boolean; + /** * Gets is layout is valid. This is a read-only property. */ @@ -797,6 +802,7 @@ export const originYProperty: Property; export const isEnabledProperty: Property; export const isUserInteractionEnabledProperty: Property; export const iosOverflowSafeAreaProperty: Property; +export const iosOverflowSafeAreaEnabledProperty: InheritedProperty; export namespace ios { /** diff --git a/tns-core-modules/ui/core/view/view.ios.ts b/tns-core-modules/ui/core/view/view.ios.ts index 5f93e773fe..be5374f771 100644 --- a/tns-core-modules/ui/core/view/view.ios.ts +++ b/tns-core-modules/ui/core/view/view.ios.ts @@ -243,7 +243,7 @@ export class View extends ViewCommon { return null; } - if (!this.iosOverflowSafeArea) { + if (!this.iosOverflowSafeArea || !this.iosOverflowSafeAreaEnabled) { return ios.shrinkToSafeArea(this, frame); } else if (this.nativeViewProtected && this.nativeViewProtected.window) { return ios.expandBeyondSafeArea(this, frame); diff --git a/tns-core-modules/ui/list-view/list-view.ios.ts b/tns-core-modules/ui/list-view/list-view.ios.ts index 896e076fda..da0b0cb2c9 100644 --- a/tns-core-modules/ui/list-view/list-view.ios.ts +++ b/tns-core-modules/ui/list-view/list-view.ios.ts @@ -95,6 +95,7 @@ class DataSource extends NSObject implements UITableViewDataSource { let width = layout.getMeasureSpecSize(owner.widthMeasureSpec); let rowHeight = owner._effectiveRowHeight; let cellHeight = rowHeight > 0 ? rowHeight : owner.getHeight(indexPath.row); + cellView.iosOverflowSafeAreaEnabled = false; View.layoutChild(owner, cellView, 0, 0, width, cellHeight); } } @@ -389,6 +390,7 @@ export class ListView extends ListViewBase { let cellHeight = rowHeight > 0 ? rowHeight : this.getHeight(childView._listViewItemIndex); if (cellHeight) { let width = layout.getMeasureSpecSize(this.widthMeasureSpec); + childView.iosOverflowSafeAreaEnabled = false; View.layoutChild(this, childView, 0, 0, width, cellHeight); } });