UIScrollViews will now report 'scroll' events and the background in ios will adjust added layers (#4762)

This commit is contained in:
Panayot Cankov
2017-08-29 10:25:45 +03:00
committed by SvetoslavTsenov
parent 3fd65cce9f
commit 12c0199fb5
18 changed files with 413 additions and 22 deletions

4
.gitignore vendored
View File

@ -51,4 +51,6 @@ apps/lib/
apps/hooks/
apps/node_modules/
package-lock.json
package-lock.json
.nsbuildinfo

View File

@ -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;
}

View File

@ -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;
}

View File

@ -0,0 +1,4 @@
export function onNavigatingTo(args) {
const page = args.object;
page.bindingContext = ["The quick", "brown fox", "jumped over", "the", "lazy dog."];
}

View File

@ -0,0 +1,55 @@
<Page xmlns="http://schemas.nativescript.org/tns.xsd" navigatingTo="onNavigatingTo" class="page">
<Page.actionBar>
<ActionBar title="My App" icon="" class="action-bar">
</ActionBar>
</Page.actionBar>
<StackLayout>
<StackLayout class="p-10" row="0">
<Label text="Default style = scrolls out of container" class="body m-b-10" />
<ListView items="{{ $value }}" height="40">
<ListView.itemTemplate>
<Label text="{{ $value }}" />
</ListView.itemTemplate>
</ListView>
</StackLayout>
<StackLayout class="p-10" row="1">
<Label text="Adding border changes the height but fixes scrolling" textWrap="true" class="body m-b-10" />
<ListView items="{{ $value }}" height="40" class="bordered">
<ListView.itemTemplate>
<Label text="{{ $value }}" />
</ListView.itemTemplate>
</ListView>
</StackLayout>
<StackLayout class="p-10" row="2">
<Label text="border-radius" class="body m-b-10" />
<ListView items="{{ $value }}" class="bordered fixed-height border-radius">
<ListView.itemTemplate>
<Label text="{{ $value }}" />
</ListView.itemTemplate>
</ListView>
</StackLayout>
<StackLayout class="p-10" row="2">
<Label text="border-radius = weird" class="body m-b-10" />
<ListView items="{{ $value }}" class="bordered fixed-height border-radius-nonuniform">
<ListView.itemTemplate>
<Label text="{{ $value }}" />
</ListView.itemTemplate>
</ListView>
</StackLayout>
<StackLayout class="p-10" row="3">
<Label text="border-width = weird" class="body m-b-10" />
<ListView items="{{ $value }}" class="bordered-nonuniform fixed-height">
<ListView.itemTemplate>
<Label text="{{ $value }}" />
</ListView.itemTemplate>
</ListView>
</StackLayout>
</StackLayout>
</Page>

View File

@ -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");

View File

@ -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 = <Page>args.object;
const wrapLayout = <WrapLayout>page.getViewById("wrapLayoutWithExamples");
page.bindingContext = new SubMainPageViewModel(wrapLayout, loadExamples());
}
export function loadExamples() {
const examples = new Map<string, string>();
examples.set("scrolling-and-sizing", "scroll-view/scrolling-and-sizing");
return examples;
}

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Page loaded="pageLoaded">
<ScrollView orientation="vertical" row="1">
<WrapLayout id="wrapLayoutWithExamples"/>
</ScrollView>
</Page>

View File

@ -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;
}

View File

@ -0,0 +1,65 @@
<Page xmlns="http://schemas.nativescript.org/tns.xsd" navigatingTo="onNavigatingTo" class="page">
<Page.actionBar>
<ActionBar title="My App" icon="" class="action-bar">
</ActionBar>
</Page.actionBar>
<StackLayout>
<StackLayout class="p-10" row="0">
<Label text="Default style = scrolls out of container" class="body m-b-10" />
<ScrollView height="40">
<StackLayout>
<GridLayout width="30" height="30" backgroundColor="red" />
<GridLayout width="30" height="30" backgroundColor="yellow" />
<GridLayout width="30" height="30" backgroundColor="green" />
</StackLayout>
</ScrollView>
</StackLayout>
<StackLayout class="p-10" row="1">
<Label text="Adding border changes the height but fixes scrolling" textWrap="true" class="body m-b-10" />
<ScrollView class="bordered" height="40">
<StackLayout>
<GridLayout width="30" height="30" backgroundColor="red" />
<GridLayout width="30" height="30" backgroundColor="yellow" />
<GridLayout width="30" height="30" backgroundColor="green" />
</StackLayout>
</ScrollView>
</StackLayout>
<StackLayout class="p-10" row="2">
<Label text="border-radius" class="body m-b-10" />
<ScrollView class="bordered fixed-height border-radius">
<StackLayout>
<GridLayout width="30" height="30" backgroundColor="red" />
<GridLayout width="30" height="30" backgroundColor="yellow" />
<GridLayout width="30" height="30" backgroundColor="green" />
</StackLayout>
</ScrollView>
</StackLayout>
<StackLayout class="p-10" row="2">
<Label text="border-radius = weird" class="body m-b-10" />
<ScrollView class="bordered fixed-height border-radius-nonuniform">
<StackLayout>
<GridLayout width="30" height="30" backgroundColor="red" />
<GridLayout width="30" height="30" backgroundColor="yellow" />
<GridLayout width="30" height="30" backgroundColor="green" />
</StackLayout>
</ScrollView>
</StackLayout>
<StackLayout class="p-10" row="3">
<Label text="border-width = weird" class="body m-b-10" />
<ScrollView class="bordered-nonuniform fixed-height">
<StackLayout>
<GridLayout width="30" height="30" backgroundColor="red" />
<GridLayout width="30" height="30" backgroundColor="yellow" />
<GridLayout width="30" height="30" backgroundColor="green" />
</StackLayout>
</ScrollView>
</StackLayout>
</StackLayout>
</Page>

View File

@ -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;
}

View File

@ -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;
}

View File

@ -0,0 +1,35 @@
<Page xmlns="http://schemas.nativescript.org/tns.xsd" navigatingTo="onNavigatingTo" class="page">
<Page.actionBar>
<ActionBar title="My App" icon="" class="action-bar">
</ActionBar>
</Page.actionBar>
<StackLayout>
<StackLayout class="p-10" row="0">
<Label text="Default style = scrolls out of container" class="body m-b-10" />
<TextView hint="Add your comment..." />
</StackLayout>
<StackLayout class="p-10" row="1">
<Label text="Adding border changes the height but fixes scrolling" textWrap="true" class="body m-b-10" />
<TextView hint="Add your comment..." class="bordered" />
</StackLayout>
<StackLayout class="p-10" row="2">
<Label text="border-radius" class="body m-b-10" />
<TextView hint="Add your comment..." class="bordered fixed-height border-radius" />
</StackLayout>
<StackLayout class="p-10" row="2">
<Label text="border-radius = weird" class="body m-b-10" />
<TextView hint="Add your comment..." class="bordered fixed-height border-radius-nonuniform" />
</StackLayout>
<StackLayout class="p-10" row="3">
<Label text="border-width = weird" class="body m-b-10" />
<TextView hint="Add your comment..." class="bordered-nonuniform fixed-height" />
</StackLayout>
</StackLayout>
</Page>

View File

@ -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";

View File

@ -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

View File

@ -17,7 +17,7 @@ class UIScrollViewDelegateImpl extends NSObject implements UIScrollViewDelegate
if (owner) {
owner.notify(<ScrollEventData>{
object: owner,
eventName: ScrollViewBase.scrollEvent,
eventName: "scroll",
scrollX: owner.horizontalOffset,
scrollY: owner.verticalOffset
});

View File

@ -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 = <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 = <View>args.object;
const nativeView = view.nativeViewProtected;
if (nativeView instanceof UIScrollView) {
adjustLayersForScrollView(<any>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(<any>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;
}

View File

@ -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<TextView>;
@ -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(<ScrollEventData>{
object: owner,
eventName: "scroll",
scrollX: contentOffset.x,
scrollY: contentOffset.y
});
}
}
}
export class TextView extends EditableTextBase implements TextViewDefinition {