diff --git a/.gitignore b/.gitignore
index d92483fd2..76eff7cd8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -51,4 +51,6 @@ apps/lib/
apps/hooks/
apps/node_modules/
-package-lock.json
\ No newline at end of file
+package-lock.json
+
+.nsbuildinfo
\ No newline at end of file
diff --git a/apps/app/ui-tests-app/list-view/main-page.ts b/apps/app/ui-tests-app/list-view/main-page.ts
index 62a5e1649..eaae1317f 100644
--- a/apps/app/ui-tests-app/list-view/main-page.ts
+++ b/apps/app/ui-tests-app/list-view/main-page.ts
@@ -16,6 +16,7 @@ export function loadExamples() {
examples.set("bindings", "list-view/listview-binding");
examples.set("listview-bg-separator-color", "list-view/listview-bg-separator-color");
examples.set("csslv", "list-view/csslv");
+ examples.set("scrolling-and-sizing", "list-view/scrolling-and-sizing");
return examples;
}
diff --git a/apps/app/ui-tests-app/list-view/scrolling-and-sizing.css b/apps/app/ui-tests-app/list-view/scrolling-and-sizing.css
new file mode 100644
index 000000000..93fbd189e
--- /dev/null
+++ b/apps/app/ui-tests-app/list-view/scrolling-and-sizing.css
@@ -0,0 +1,47 @@
+.p-10 {
+ padding: 10 20 10 20;
+}
+
+.m-b-10 {
+ margin-bottom: 10;
+}
+
+.page {
+ background-color: #F2F2F2;
+}
+
+TextView {
+ background-color: #FFF;
+}
+
+.bordered {
+ border-width: 5;
+ border-color: green;
+}
+
+.fixed-height {
+ height: 55;
+}
+
+.border-radius {
+ border-radius: 15;
+}
+
+.border-radius-nonuniform {
+ border-radius: 10 20 30 40;
+}
+
+.bordered-nonuniform {
+ border-top-color: red;
+ border-right-color: green;
+ border-bottom-color: blue;
+ border-left-color: purple;
+ border-top-width: 5;
+ border-right-width: 10;
+ border-bottom-width: 15;
+ border-left-width: 20;
+}
+
+.body {
+ font-size: 11;
+}
\ No newline at end of file
diff --git a/apps/app/ui-tests-app/list-view/scrolling-and-sizing.ts b/apps/app/ui-tests-app/list-view/scrolling-and-sizing.ts
new file mode 100644
index 000000000..243209898
--- /dev/null
+++ b/apps/app/ui-tests-app/list-view/scrolling-and-sizing.ts
@@ -0,0 +1,4 @@
+export function onNavigatingTo(args) {
+ const page = args.object;
+ page.bindingContext = ["The quick", "brown fox", "jumped over", "the", "lazy dog."];
+}
\ No newline at end of file
diff --git a/apps/app/ui-tests-app/list-view/scrolling-and-sizing.xml b/apps/app/ui-tests-app/list-view/scrolling-and-sizing.xml
new file mode 100644
index 000000000..071bc44da
--- /dev/null
+++ b/apps/app/ui-tests-app/list-view/scrolling-and-sizing.xml
@@ -0,0 +1,55 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/apps/app/ui-tests-app/main-page.ts b/apps/app/ui-tests-app/main-page.ts
index 6658f10ba..b030a14d3 100644
--- a/apps/app/ui-tests-app/main-page.ts
+++ b/apps/app/ui-tests-app/main-page.ts
@@ -25,6 +25,7 @@ export function pageLoaded(args: EventData) {
examples.set("modalview", "modal-view/modal-view");
examples.set("page", "page/main-page");
examples.set("perf", "perf/main-page");
+ examples.set("scroll-view", "scroll-view/main-page");
examples.set("segStyle", "segmented-bar/all");
examples.set("search-bar", "search-bar/main-page");
examples.set("tab-view", "tab-view/main-page");
diff --git a/apps/app/ui-tests-app/scroll-view/main-page.ts b/apps/app/ui-tests-app/scroll-view/main-page.ts
new file mode 100644
index 000000000..116a1d77d
--- /dev/null
+++ b/apps/app/ui-tests-app/scroll-view/main-page.ts
@@ -0,0 +1,16 @@
+import { EventData } from "tns-core-modules/data/observable";
+import { SubMainPageViewModel } from "../sub-main-page-view-model";
+import { WrapLayout } from "tns-core-modules/ui/layouts/wrap-layout";
+import { Page } from "tns-core-modules/ui/page";
+
+export function pageLoaded(args: EventData) {
+ const page = args.object;
+ const wrapLayout = page.getViewById("wrapLayoutWithExamples");
+ page.bindingContext = new SubMainPageViewModel(wrapLayout, loadExamples());
+}
+
+export function loadExamples() {
+ const examples = new Map();
+ examples.set("scrolling-and-sizing", "scroll-view/scrolling-and-sizing");
+ return examples;
+}
\ No newline at end of file
diff --git a/apps/app/ui-tests-app/scroll-view/main-page.xml b/apps/app/ui-tests-app/scroll-view/main-page.xml
new file mode 100644
index 000000000..33306f0d0
--- /dev/null
+++ b/apps/app/ui-tests-app/scroll-view/main-page.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/apps/app/ui-tests-app/scroll-view/scrolling-and-sizing.css b/apps/app/ui-tests-app/scroll-view/scrolling-and-sizing.css
new file mode 100644
index 000000000..fa1a2c8f0
--- /dev/null
+++ b/apps/app/ui-tests-app/scroll-view/scrolling-and-sizing.css
@@ -0,0 +1,47 @@
+.p-10 {
+ padding: 10 20 10 20;
+}
+
+.m-b-10 {
+ margin-bottom: 10;
+}
+
+.page {
+ background-color: #F2F2F2;
+}
+
+ScrollView {
+ background-color: #FFF;
+}
+
+.bordered {
+ border-width: 5;
+ border-color: green;
+}
+
+.fixed-height {
+ height: 55;
+}
+
+.border-radius {
+ border-radius: 15;
+}
+
+.border-radius-nonuniform {
+ border-radius: 10 20 30 40;
+}
+
+.bordered-nonuniform {
+ border-top-color: red;
+ border-right-color: green;
+ border-bottom-color: blue;
+ border-left-color: purple;
+ border-top-width: 5;
+ border-right-width: 10;
+ border-bottom-width: 15;
+ border-left-width: 20;
+}
+
+.body {
+ font-size: 11;
+}
\ No newline at end of file
diff --git a/apps/app/ui-tests-app/scroll-view/scrolling-and-sizing.xml b/apps/app/ui-tests-app/scroll-view/scrolling-and-sizing.xml
new file mode 100644
index 000000000..da25a263c
--- /dev/null
+++ b/apps/app/ui-tests-app/scroll-view/scrolling-and-sizing.xml
@@ -0,0 +1,65 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/apps/app/ui-tests-app/text-view/main-page.ts b/apps/app/ui-tests-app/text-view/main-page.ts
index 71372d5d9..3581cc0ba 100644
--- a/apps/app/ui-tests-app/text-view/main-page.ts
+++ b/apps/app/ui-tests-app/text-view/main-page.ts
@@ -14,5 +14,6 @@ export function loadExamples() {
examples.set("text-view-border", "text-view/text-view-border");
examples.set("text-view-hint-color", "text-view/text-view-hint-color");
examples.set("hint-text-color", "text-view/hint-text-color");
+ examples.set("scrolling-and-sizing", "text-view/scrolling-and-sizing");
return examples;
}
\ No newline at end of file
diff --git a/apps/app/ui-tests-app/text-view/scrolling-and-sizing.css b/apps/app/ui-tests-app/text-view/scrolling-and-sizing.css
new file mode 100644
index 000000000..93fbd189e
--- /dev/null
+++ b/apps/app/ui-tests-app/text-view/scrolling-and-sizing.css
@@ -0,0 +1,47 @@
+.p-10 {
+ padding: 10 20 10 20;
+}
+
+.m-b-10 {
+ margin-bottom: 10;
+}
+
+.page {
+ background-color: #F2F2F2;
+}
+
+TextView {
+ background-color: #FFF;
+}
+
+.bordered {
+ border-width: 5;
+ border-color: green;
+}
+
+.fixed-height {
+ height: 55;
+}
+
+.border-radius {
+ border-radius: 15;
+}
+
+.border-radius-nonuniform {
+ border-radius: 10 20 30 40;
+}
+
+.bordered-nonuniform {
+ border-top-color: red;
+ border-right-color: green;
+ border-bottom-color: blue;
+ border-left-color: purple;
+ border-top-width: 5;
+ border-right-width: 10;
+ border-bottom-width: 15;
+ border-left-width: 20;
+}
+
+.body {
+ font-size: 11;
+}
\ No newline at end of file
diff --git a/apps/app/ui-tests-app/text-view/scrolling-and-sizing.xml b/apps/app/ui-tests-app/text-view/scrolling-and-sizing.xml
new file mode 100644
index 000000000..f47be58b2
--- /dev/null
+++ b/apps/app/ui-tests-app/text-view/scrolling-and-sizing.xml
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tns-core-modules/ui/core/view/view.ios.ts b/tns-core-modules/ui/core/view/view.ios.ts
index d1bee883b..ee84ee907 100644
--- a/tns-core-modules/ui/core/view/view.ios.ts
+++ b/tns-core-modules/ui/core/view/view.ios.ts
@@ -437,7 +437,10 @@ export class View extends ViewCommon {
_setNativeClipToBounds() {
let backgroundInternal = this.style.backgroundInternal;
- this.nativeViewProtected.clipsToBounds = backgroundInternal.hasBorderWidth() || backgroundInternal.hasBorderRadius();
+ this.nativeViewProtected.clipsToBounds =
+ this.nativeViewProtected instanceof UIScrollView ||
+ backgroundInternal.hasBorderWidth() ||
+ backgroundInternal.hasBorderRadius();
}
}
View.prototype._nativeBackgroundState = "unset";
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 20af23d7e..acf2e5e0e 100644
--- a/tns-core-modules/ui/list-view/list-view.ios.ts
+++ b/tns-core-modules/ui/list-view/list-view.ios.ts
@@ -1,4 +1,5 @@
-import { ItemEventData } from ".";
+import { ScrollEventData } from "../scroll-view";
+import { ItemEventData } from ".";
import {
ListViewBase, View, KeyedTemplate, Length, Observable, Color,
separatorColorProperty, itemTemplatesProperty, layout, EventData
diff --git a/tns-core-modules/ui/scroll-view/scroll-view.ios.ts b/tns-core-modules/ui/scroll-view/scroll-view.ios.ts
index 12961667e..f7c0f6465 100644
--- a/tns-core-modules/ui/scroll-view/scroll-view.ios.ts
+++ b/tns-core-modules/ui/scroll-view/scroll-view.ios.ts
@@ -17,7 +17,7 @@ class UIScrollViewDelegateImpl extends NSObject implements UIScrollViewDelegate
if (owner) {
owner.notify({
object: owner,
- eventName: ScrollViewBase.scrollEvent,
+ eventName: "scroll",
scrollX: owner.horizontalOffset,
scrollY: owner.verticalOffset
});
diff --git a/tns-core-modules/ui/styling/background.ios.ts b/tns-core-modules/ui/styling/background.ios.ts
index baf32fa7d..f1a4de3c1 100644
--- a/tns-core-modules/ui/styling/background.ios.ts
+++ b/tns-core-modules/ui/styling/background.ios.ts
@@ -1,3 +1,5 @@
+import { ScrollEventData } from "../scroll-view";
+
import { Background as BackgroundDefinition } from "./background";
import { View, Point } from "../core/view";
import { Color } from "../../color";
@@ -10,15 +12,15 @@ export * from "./background-common";
interface NativeView extends UIView {
hasNonUniformBorder: boolean;
- borderLayer: CAShapeLayer;
+ borderLayer: CALayer;
hasBorderMask: boolean;
borderOriginalMask: CALayer;
- topBorderLayer: CAShapeLayer;
- rightBorderLayer: CAShapeLayer;
- bottomBorderLayer: CAShapeLayer;
- leftBorderLayer: CAShapeLayer;
+ topBorderLayer: CALayer;
+ rightBorderLayer: CALayer;
+ bottomBorderLayer: CALayer;
+ leftBorderLayer: CALayer;
}
interface Rect {
@@ -37,11 +39,15 @@ export module ios {
const nativeView = view.nativeViewProtected;
if (nativeView.hasNonUniformBorder) {
+ unsubscribeFromScrollNotifications(view);
clearNonUniformBorders(nativeView);
}
- if (background.hasUniformBorderColor() && background.hasBorderRadius()) {
+ const hasNonUniformBorderWidths = background.hasBorderWidth() && !background.hasUniformBorder();
+ const hasNonUniformBorderRadiuses = background.hasBorderRadius() && !background.hasUniformBorderRadius();
+ if (background.hasUniformBorderColor() && (hasNonUniformBorderWidths || hasNonUniformBorderRadiuses)) {
drawUniformColorNonUniformBorders(nativeView, background);
+ subscribeForScrollNotifications(view);
} else if (background.hasUniformBorder()) {
const layer = nativeView.layer;
const borderColor = background.getUniformBorderColor();
@@ -52,6 +58,7 @@ export module ios {
layer.cornerRadius = Math.min(Math.min(renderSize.width / 2, renderSize.height / 2), cornerRadius);
} else {
drawNoRadiusNonUniformBorders(nativeView, background);
+ subscribeForScrollNotifications(view);
}
// Clip-path should be called after borders are applied.
@@ -69,6 +76,42 @@ export module ios {
}
}
+function onScroll(this: void, args: ScrollEventData): void {
+ const view = args.object;
+ const nativeView = view.nativeViewProtected;
+ if (nativeView instanceof UIScrollView) {
+ adjustLayersForScrollView(nativeView);
+ }
+}
+
+function adjustLayersForScrollView(nativeView: UIScrollView & NativeView) {
+ const layer = nativeView.borderLayer;
+ if (layer instanceof CALayer) {
+ // Compensates with transition for the background layers for scrolling in ScrollView based controls.
+ CATransaction.begin();
+ CATransaction.setValueForKey(kCFBooleanTrue, kCATransactionDisableActions);
+ const offset = nativeView.contentOffset;
+ const transform = { a: 1, b: 0, c: 0, d: 1, tx: offset.x, ty: offset.y };
+ layer.setAffineTransform(transform);
+ if (nativeView.layer.mask) {
+ nativeView.layer.mask.setAffineTransform(transform);
+ }
+ CATransaction.commit();
+ }
+}
+
+function unsubscribeFromScrollNotifications(view: View) {
+ if (view.nativeViewProtected instanceof UIScrollView) {
+ view.off("scroll", onScroll);
+ }
+}
+function subscribeForScrollNotifications(view: View) {
+ if (view.nativeViewProtected instanceof UIScrollView) {
+ view.on("scroll", onScroll);
+ adjustLayersForScrollView(view.nativeViewProtected);
+ }
+}
+
function clearNonUniformBorders(nativeView: NativeView): void {
if (nativeView.borderLayer) {
nativeView.borderLayer.removeFromSuperlayer();
@@ -507,12 +550,15 @@ function drawUniformColorNonUniformBorders(nativeView: NativeView, background: B
}
function drawNoRadiusNonUniformBorders(nativeView: NativeView, background: BackgroundDefinition) {
- const layer = nativeView.layer;
- layer.borderColor = undefined;
- layer.borderWidth = 0;
- layer.cornerRadius = 0;
+ const borderLayer = CALayer.layer();
+ nativeView.layer.addSublayer(borderLayer);
+ nativeView.borderLayer = borderLayer;
- const layerBounds = layer.bounds;
+ borderLayer.borderColor = undefined;
+ borderLayer.borderWidth = 0;
+ borderLayer.cornerRadius = 0;
+
+ const layerBounds = nativeView.layer.bounds;
const layerOrigin = layerBounds.origin;
const layerSize = layerBounds.size;
@@ -555,7 +601,7 @@ function drawNoRadiusNonUniformBorders(nativeView: NativeView, background: Backg
topBorderLayer.fillColor = background.borderTopColor.ios.CGColor;
topBorderLayer.path = topBorderPath;
- layer.addSublayer(topBorderLayer);
+ borderLayer.addSublayer(topBorderLayer);
nativeView.topBorderLayer = topBorderLayer;
hasNonUniformBorder = true;
}
@@ -573,7 +619,7 @@ function drawNoRadiusNonUniformBorders(nativeView: NativeView, background: Backg
rightBorderLayer.fillColor = background.borderRightColor.ios.CGColor;
rightBorderLayer.path = rightBorderPath;
- layer.addSublayer(rightBorderLayer);
+ borderLayer.addSublayer(rightBorderLayer);
nativeView.rightBorderLayer = rightBorderLayer;
hasNonUniformBorder = true;
}
@@ -591,7 +637,7 @@ function drawNoRadiusNonUniformBorders(nativeView: NativeView, background: Backg
bottomBorderLayer.fillColor = background.borderBottomColor.ios.CGColor;
bottomBorderLayer.path = bottomBorderPath;
- layer.addSublayer(bottomBorderLayer);
+ borderLayer.addSublayer(bottomBorderLayer);
nativeView.bottomBorderLayer = bottomBorderLayer;
hasNonUniformBorder = true;
}
@@ -609,7 +655,7 @@ function drawNoRadiusNonUniformBorders(nativeView: NativeView, background: Backg
leftBorderLayer.fillColor = background.borderLeftColor.ios.CGColor;
leftBorderLayer.path = leftBorderPath;
- layer.addSublayer(leftBorderLayer);
+ borderLayer.addSublayer(leftBorderLayer);
nativeView.leftBorderLayer = leftBorderLayer;
hasNonUniformBorder = true;
}
diff --git a/tns-core-modules/ui/text-view/text-view.ios.ts b/tns-core-modules/ui/text-view/text-view.ios.ts
index 9bd944fe0..dcf9b6960 100644
--- a/tns-core-modules/ui/text-view/text-view.ios.ts
+++ b/tns-core-modules/ui/text-view/text-view.ios.ts
@@ -1,4 +1,5 @@
-import { TextView as TextViewDefinition } from ".";
+import { ScrollEventData } from "../scroll-view";
+import { TextView as TextViewDefinition } from ".";
import {
EditableTextBase, editableProperty, hintProperty, textProperty, colorProperty, placeholderColorProperty,
borderTopWidthProperty, borderRightWidthProperty, borderBottomWidthProperty, borderLeftWidthProperty,
@@ -9,8 +10,8 @@ import { profile } from "../../profiling";
export * from "../editable-text-base";
-class UITextViewDelegateImpl extends NSObject implements UITextViewDelegate {
- public static ObjCProtocols = [UITextViewDelegate];
+class UITextViewDelegateImpl extends NSObject implements UIScrollViewDelegate, UITextViewDelegate {
+ public static ObjCProtocols = [UITextViewDelegate, UIScrollViewDelegate];
private _owner: WeakRef;
@@ -76,6 +77,19 @@ class UITextViewDelegateImpl extends NSObject implements UITextViewDelegate {
return true;
}
+
+ public scrollViewDidScroll(sv: UIScrollView): void {
+ const owner = this._owner.get();
+ if (owner) {
+ const contentOffset = owner.nativeViewProtected.contentOffset;
+ owner.notify({
+ object: owner,
+ eventName: "scroll",
+ scrollX: contentOffset.x,
+ scrollY: contentOffset.y
+ });
+ }
+ }
}
export class TextView extends EditableTextBase implements TextViewDefinition {