fix padding on text-view & text-field (#3758)

* fix padding on text-view & text-field
text-base is now snapshotable
view.android is now snapshotable

* createNativeView returns the nativeView for android
Fix image tests
Implement test for image loaded from res://
EffectivePaddings updated when nativeView have some from its native theme
This commit is contained in:
Hristo Hristov
2017-03-09 16:09:53 +02:00
committed by GitHub
parent a4809fed16
commit 1d49f5f3c3
42 changed files with 269 additions and 236 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

View File

@ -86,7 +86,8 @@ application.on(application.lowMemoryEvent, function (args: application.Applicati
application.on(application.uncaughtErrorEvent, function (args: application.UnhandledErrorEventData) {
console.log("NativeScriptError: " + args.error);
console.log(args.error.stack);
console.log((<any>args.error).nativeException);
console.log((<any>args.error).stackTrace);
});
// Android activity events

View File

@ -16,10 +16,9 @@ import * as ImageSourceModule from "image-source";
import * as ViewModule from "ui/core/view";
import * as helper from "../helper";
import * as ObservableModule from "data/observable";
import * as fs from "file-system";
import * as color from "color";
const imagePath = fs.path.join(__dirname, "../../logo.png");
const imagePath = "~/logo.png";
if (isAndroid) {
const imageModule = require("ui/image");
@ -33,19 +32,16 @@ export const test_Image_Members = function () {
TKUnit.assert(image.isLoading === false, "Image.isLoading is default value should be false.");
};
/* TODO: We need a way to programmatically add an image to resources and then load it from, otherwise we do not know if there is such resource in the target native app.
export const test_settingImageSource = function () {
export const test_setting_src_to_resource = function () {
// >> img-create
const image = new ImageModule.Image();
image.imageSource = ImageSourceModule.fromResource("logo");
image.src = "res://icon";
// << img-create
const testFunc = function (views: Array<ViewModule.View>) {
const testImage = <ImageModule.Image> views[0];
const desiredSize = testImage._measureNativeView(new geometry.Size(100, 100));
const width = desiredSize.width;
const height = desiredSize.height;
const testFunc = function (views: Array<ViewModule.View>) {
TKUnit.waitUntilReady(() => image.isLayoutValid);
const width = image.getMeasuredWidth();
const height = image.getMeasuredHeight();
TKUnit.assert(width > 0, "Width should be greater than 0.");
TKUnit.assert(height > 0, "Height should be greater than 0.");
@ -53,7 +49,6 @@ export const test_settingImageSource = function () {
helper.buildUIAndRunTest(image, testFunc);
}
*/
const IMAGE_LOADED_EVENT = "isLoadingChange";
@ -105,7 +100,7 @@ export const test_SettingImageSrcToURL_async = function (done) {
runImageTestAsync(image, image.src, done);
};
export const test_SettingImageSrcToFileWithinApp_sync = function () {
export const test_SettingImageSrcToFileWithinApp_sync = function () {
// >> img-create-local
const image = new ImageModule.Image();
image.src = "~/logo.png";
@ -174,7 +169,6 @@ export const __test_SettingImageSrcTwiceMustNotMismatch = function (done) {
export const test_SettingStretch_AspectFit = function () {
// >> img-set-stretch
const image = new ImageModule.Image();
image.imageSource = ImageSourceModule.fromFile(imagePath);
// There are 4 modes of stretching none, fill, aspectFill, aspectFit
// The default value is aspectFit.
// Image stretch can be set by using ImageModule.stretch enum.
@ -182,17 +176,10 @@ export const test_SettingStretch_AspectFit = function () {
// << img-set-stretch
const testFunc = function (views: Array<ViewModule.View>) {
const testImage = <ImageModule.Image>views[0];
if (image.android) {
const actualScaleType = testImage.android.getScaleType();
const expectedScaleType = android.widget.ImageView.ScaleType.FIT_CENTER;
TKUnit.assertEqual(actualScaleType, expectedScaleType, "actualScaleType");
}
else if (image.ios) {
const actualContentMode = testImage.ios.contentMode;
const expectedContentMode = UIViewContentMode.ScaleAspectFit;
TKUnit.assertEqual(actualContentMode, expectedContentMode, "actualContentMode");
TKUnit.assertEqual(image.android.getScaleType(), android.widget.ImageView.ScaleType.FIT_CENTER);
} else if (image.ios) {
TKUnit.assertEqual(image.ios.contentMode, UIViewContentMode.ScaleAspectFit);
}
};
@ -201,20 +188,11 @@ export const test_SettingStretch_AspectFit = function () {
export const test_SettingStretch_Default = function () {
const image = new ImageModule.Image();
image.imageSource = ImageSourceModule.fromFile(imagePath);
const testFunc = function (views: Array<ViewModule.View>) {
const testImage = <ImageModule.Image>views[0];
if (image.android) {
const actualScaleType = testImage.android.getScaleType();
const expectedScaleType = android.widget.ImageView.ScaleType.FIT_CENTER;
TKUnit.assert(actualScaleType === expectedScaleType, "Expected: " + expectedScaleType + ", Actual: " + actualScaleType);
}
else if (image.ios) {
const actualContentMode = testImage.ios.contentMode;
const expectedContentMode = UIViewContentMode.ScaleAspectFit;
TKUnit.assert(actualContentMode === expectedContentMode, "Expected: " + expectedContentMode + ", Actual: " + actualContentMode);
TKUnit.assertEqual(image.android.getScaleType(), android.widget.ImageView.ScaleType.FIT_CENTER);
} else if (image.ios) {
TKUnit.assertEqual(image.ios.contentMode, UIViewContentMode.ScaleAspectFit);
}
};
@ -223,21 +201,13 @@ export const test_SettingStretch_Default = function () {
export const test_SettingStretch_AspectFill = function () {
const image = new ImageModule.Image();
image.imageSource = ImageSourceModule.fromFile(imagePath);
image.stretch = "aspectFill";
const testFunc = function (views: Array<ViewModule.View>) {
const testImage = <ImageModule.Image>views[0];
if (image.android) {
const actualScaleType = testImage.android.getScaleType();
const expectedScaleType = android.widget.ImageView.ScaleType.CENTER_CROP;
TKUnit.assert(actualScaleType === expectedScaleType, "Expected: " + expectedScaleType + ", Actual: " + actualScaleType);
}
else if (image.ios) {
const actualContentMode = testImage.ios.contentMode;
const expectedContentMode = UIViewContentMode.ScaleAspectFill;
TKUnit.assert(actualContentMode === expectedContentMode, "Expected: " + expectedContentMode + ", Actual: " + actualContentMode);
TKUnit.assertEqual(image.android.getScaleType(), android.widget.ImageView.ScaleType.CENTER_CROP);
} else if (image.ios) {
TKUnit.assertEqual(image.ios.contentMode, UIViewContentMode.ScaleAspectFill);
}
};
@ -246,21 +216,14 @@ export const test_SettingStretch_AspectFill = function () {
export const test_SettingStretch_Fill = function () {
const image = new ImageModule.Image();
image.imageSource = ImageSourceModule.fromFile(imagePath);
image.stretch = "fill";
const testFunc = function (views: Array<ViewModule.View>) {
const testImage = <ImageModule.Image>views[0];
if (image.android) {
const actualScaleType = testImage.android.getScaleType();
const expectedScaleType = android.widget.ImageView.ScaleType.FIT_XY;
TKUnit.assert(actualScaleType === expectedScaleType, "Expected: " + expectedScaleType + ", Actual: " + actualScaleType);
}
else if (image.ios) {
const actualContentMode = testImage.ios.contentMode;
const expectedContentMode = UIViewContentMode.ScaleToFill;
TKUnit.assert(actualContentMode === expectedContentMode, "Expected: " + expectedContentMode + ", Actual: " + actualContentMode);
TKUnit.assertEqual(image.android.getScaleType(), android.widget.ImageView.ScaleType.FIT_XY);
} else if (image.ios) {
TKUnit.assertEqual(image.ios.contentMode, UIViewContentMode.ScaleToFill);
}
};
@ -269,21 +232,13 @@ export const test_SettingStretch_Fill = function () {
export const test_SettingStretch_none = function () {
const image = new ImageModule.Image();
image.imageSource = ImageSourceModule.fromFile(imagePath);
image.stretch = "none";
const testFunc = function (views: Array<ViewModule.View>) {
const testImage = <ImageModule.Image>views[0];
if (image.android) {
const actualScaleType = testImage.android.getScaleType();
const expectedScaleType = android.widget.ImageView.ScaleType.MATRIX;
TKUnit.assert(actualScaleType === expectedScaleType, "Expected: " + expectedScaleType + ", Actual: " + actualScaleType);
}
else if (image.ios) {
const actualContentMode = testImage.ios.contentMode;
const expectedContentMode = UIViewContentMode.TopLeft;
TKUnit.assert(actualContentMode === expectedContentMode, "Expected: " + expectedContentMode + ", Actual: " + actualContentMode);
TKUnit.assertEqual(image.android.getScaleType(), android.widget.ImageView.ScaleType.MATRIX);
} else if (image.ios) {
TKUnit.assertEqual(image.ios.contentMode, UIViewContentMode.TopLeft);
}
};
@ -375,7 +330,7 @@ export const test_DimensionsAreRoundedAfterScale = function () {
export const test_tintColor = function () {
const colorRed = new color.Color("red");
const image = new ImageModule.Image();
image.imageSource = ImageSourceModule.fromFile(imagePath);
image.src = imagePath;
const testFunc = function (views: Array<ViewModule.View>) {
const testImage = <ImageModule.Image>views[0];

View File

@ -87,6 +87,7 @@ export class MyButton extends Button implements def.MyButton {
public _createNativeView() {
this._layout = new NativeButton(this._context, this);
return this._layout;
}
public measureCount: number = 0;
@ -140,6 +141,7 @@ export class MyStackLayout extends StackLayout implements def.MyStackLayout {
public _createNativeView() {
this._layout = new NativeStackLayout(this._context, this);
return this._layout;
}
public measureCount: number = 0;
@ -193,6 +195,7 @@ export class MyGridLayout extends GridLayout implements def.MyGridLayout {
public _createNativeView() {
this._layout = new NativeGridLayout(this._context, this);
return this._layout;
}
public measureCount: number = 0;

View File

@ -137,9 +137,10 @@ export class ActionBar extends ActionBarBase {
public _createNativeView() {
initializeMenuItemClickListener();
this._toolbar = new android.support.v7.widget.Toolbar(this._context);
const toolbar = this._toolbar = new android.support.v7.widget.Toolbar(this._context);
this._menuItemClickListener = this._menuItemClickListener || new MenuItemClickListener(this);
this._toolbar.setOnMenuItemClickListener(this._menuItemClickListener);
return toolbar;
}
public onLoaded() {

View File

@ -6,9 +6,10 @@ export class ActivityIndicator extends ActivityIndicatorBase {
_progressBar: android.widget.ProgressBar;
public _createNativeView() {
this._progressBar = new android.widget.ProgressBar(this._context);
const progressBar = this._progressBar = new android.widget.ProgressBar(this._context);
this._progressBar.setVisibility(android.view.View.INVISIBLE);
this._progressBar.setIndeterminate(true);
return progressBar;
}
get android(): android.widget.ProgressBar {

View File

@ -36,7 +36,6 @@ function initializeClickListener(): void {
export class Button extends ButtonBase {
_button: android.widget.Button;
private _highlightedHandler: (args: TouchGestureEventData) => void;
private _defaultNativePadding: android.graphics.Rect;
get android(): android.widget.Button {
return this._button;
@ -44,18 +43,9 @@ export class Button extends ButtonBase {
public _createNativeView() {
initializeClickListener();
this._button = new android.widget.Button(this._context);
const button = this._button = new android.widget.Button(this._context);
this._button.setOnClickListener(new ClickListener(this));
// Unlike all other widgets, the Button has padding 30 36 30 36 in device pixels.
let result = new android.graphics.Rect();
this._button.getBackground().getPadding(result);
this._defaultNativePadding = result;
this.effectivePaddingTop = this._defaultNativePadding.top;
this.effectivePaddingRight = this._defaultNativePadding.right;
this.effectivePaddingBottom = this._defaultNativePadding.bottom;
this.effectivePaddingLeft = this._defaultNativePadding.left;
return button;
}
@PseudoClassHandler("normal", "highlighted", "pressed", "active")
@ -77,33 +67,29 @@ export class Button extends ButtonBase {
}
}
//PaddingTop
get [paddingTopProperty.native](): Length {
return { value: this._defaultNativePadding.top, unit: "px" }
return { value: this._defaultPaddingTop, unit: "px" }
}
set [paddingTopProperty.native](value: Length) {
org.nativescript.widgets.ViewHelper.setPaddingTop(this.nativeView, Length.toDevicePixels(value, 0) + Length.toDevicePixels(this.style.borderTopWidth, 0));
}
//PaddingRight
get [paddingRightProperty.native](): Length {
return { value: this._defaultNativePadding.right, unit: "px" }
return { value: this._defaultPaddingRight, unit: "px" }
}
set [paddingRightProperty.native](value: Length) {
org.nativescript.widgets.ViewHelper.setPaddingRight(this.nativeView, Length.toDevicePixels(value, 0) + Length.toDevicePixels(this.style.borderRightWidth, 0));
}
//PaddingBottom
get [paddingBottomProperty.native](): Length {
return { value: this._defaultNativePadding.bottom, unit: "px" }
return { value: this._defaultPaddingBottom, unit: "px" }
}
set [paddingBottomProperty.native](value: Length) {
org.nativescript.widgets.ViewHelper.setPaddingBottom(this.nativeView, Length.toDevicePixels(value, 0) + Length.toDevicePixels(this.style.borderBottomWidth, 0));
}
//PaddingLeft
get [paddingLeftProperty.native](): Length {
return { value: this._defaultNativePadding.left, unit: "px" }
return { value: this._defaultPaddingLeft, unit: "px" }
}
set [paddingLeftProperty.native](value: Length) {
org.nativescript.widgets.ViewHelper.setPaddingLeft(this.nativeView, Length.toDevicePixels(value, 0) + Length.toDevicePixels(this.style.borderLeftWidth, 0));

View File

@ -64,6 +64,10 @@ export abstract class ViewBase extends Observable {
_oldTop: number;
_oldRight: number;
_oldBottom: number;
_defaultPaddingTop: number;
_defaultPaddingRight: number;
_defaultPaddingBottom: number;
_defaultPaddingLeft: number;
//@endprivate
public effectiveMinWidth: number;
@ -180,7 +184,7 @@ export abstract class ViewBase extends Observable {
public cssPseudoClasses: Set<string>;
public _goToVisualState(state: string): void;
public _applyXmlAttribute(attribute, value): boolean;
public _applyXmlAttribute(attribute, value): boolean;
public setInlineStyle(style: string): void;
_context: any /* android.content.Context */;
@ -200,7 +204,7 @@ export abstract class ViewBase extends Observable {
/**
* Creates a native view
*/
_createNativeView(): void;
_createNativeView(): Object;
/**
* Clean up references to the native view.

View File

@ -3,14 +3,14 @@ import { ViewBase as ViewBaseDefinition } from "ui/core/view-base";
import { Page } from "ui/page";
import { SelectorCore } from "ui/styling/css-selector";
import { Order, FlexGrow, FlexShrink, FlexWrapBefore, AlignSelf } from "ui/layouts/flexbox-layout";
import { Length } from "../../styling/style-properties";
import { KeyframeAnimation } from "ui/animation/keyframe-animation";
// Types.
import { Property, InheritedProperty, Style, clearInheritedProperties, propagateInheritableProperties, propagateInheritableCssProperties, resetCSSProperties, initNativeView, resetNativeView } from "../properties";
import { Property, InheritedProperty, Style, clearInheritedProperties, propagateInheritableProperties, propagateInheritableCssProperties, resetCSSProperties, initNativeView, resetNativeView, _isSet } from "../properties";
import { Binding, BindingOptions, Observable, WrappedValue, PropertyChangeData, traceEnabled, traceWrite, traceCategories, traceNotifyEvent } from "ui/core/bindable";
import { isIOS, isAndroid } from "platform";
import { layout } from "utils/utils";
import { Length, paddingTopProperty, paddingRightProperty, paddingBottomProperty, paddingLeftProperty } from "../../styling/style-properties";
// TODO: Remove this import!
import * as types from "utils/types";
@ -156,6 +156,11 @@ export class ViewBase extends Observable implements ViewBaseDefinition {
public effectiveBorderBottomWidth: number;
public effectiveBorderLeftWidth: number;
public _defaultPaddingTop: number;
public _defaultPaddingRight: number;
public _defaultPaddingBottom: number;
public _defaultPaddingLeft: number;
constructor() {
super();
this._domId = viewIdCounter++;
@ -544,8 +549,8 @@ export class ViewBase extends Observable implements ViewBaseDefinition {
}
}
public _createNativeView() {
//
public _createNativeView(): Object {
return undefined;
}
public _disposeNativeView() {
@ -575,9 +580,40 @@ export class ViewBase extends Observable implements ViewBaseDefinition {
this._context = context;
traceNotifyEvent(this, "_onContextChanged");
// TODO: refactor createUI to return native view
this._createNativeView();
this.nativeView = (<any>this)._nativeView;
if (isAndroid) {
const native: any = this._createNativeView();
const nativeView: android.view.View = this.nativeView = native;
if (nativeView) {
let result: android.graphics.Rect = (<any>nativeView).defaultPaddings;
if (result === undefined) {
result = org.nativescript.widgets.ViewHelper.getPadding(nativeView);
(<any>nativeView).defaultPaddings = result;
}
this._defaultPaddingTop = result.top;
this._defaultPaddingRight = result.right;
this._defaultPaddingBottom = result.bottom;
this._defaultPaddingLeft = result.left;
const style = this.style;
if (!_isSet(paddingTopProperty, style)) {
this.effectivePaddingTop = this._defaultPaddingTop;
}
if (!_isSet(paddingRightProperty, style)) {
this.effectivePaddingRight = this._defaultPaddingRight;
}
if (!_isSet(paddingBottomProperty, style)) {
this.effectivePaddingBottom = this._defaultPaddingBottom;
}
if (!_isSet(paddingLeftProperty, style)) {
this.effectivePaddingLeft = this._defaultPaddingLeft;
}
}
} else {
// TODO: Implement _createNativeView for iOS
this._createNativeView();
this.nativeView = (<any>this)._nativeView;
}
this._initNativeView();
@ -734,6 +770,10 @@ ViewBase.prototype.effectiveBorderTopWidth = 0;
ViewBase.prototype.effectiveBorderRightWidth = 0;
ViewBase.prototype.effectiveBorderBottomWidth = 0;
ViewBase.prototype.effectiveBorderLeftWidth = 0;
ViewBase.prototype._defaultPaddingTop = 0;
ViewBase.prototype._defaultPaddingRight = 0;
ViewBase.prototype._defaultPaddingBottom = 0;
ViewBase.prototype._defaultPaddingLeft = 0;
export const bindingContextProperty = new InheritedProperty<ViewBase, any>({ name: "bindingContext" });
bindingContextProperty.register(ViewBase);

View File

@ -662,10 +662,6 @@ export abstract class ViewCommon extends ViewBase implements ViewDefinition {
return { boundsChanged, sizeChanged };
}
public _createNativeView() {
//
}
public eachChild(callback: (child: ViewBase) => boolean): void {
this.eachChildView(<any>callback);
}

View File

@ -12,9 +12,9 @@ import {
import {
Length, PercentLength, Visibility, HorizontalAlignment, VerticalAlignment,
visibilityProperty, opacityProperty, horizontalAlignmentProperty, verticalAlignmentProperty,
minWidthProperty, minHeightProperty, widthProperty, heightProperty,
marginLeftProperty, marginTopProperty, marginRightProperty, marginBottomProperty,
rotateProperty, scaleXProperty, scaleYProperty, translateXProperty, translateYProperty,
minWidthProperty, minHeightProperty, widthProperty, heightProperty,
marginLeftProperty, marginTopProperty, marginRightProperty, marginBottomProperty,
rotateProperty, scaleXProperty, scaleYProperty, translateXProperty, translateYProperty,
zIndexProperty, backgroundInternalProperty
} from "ui/styling/style-properties";
@ -467,7 +467,8 @@ export class CustomLayoutView extends View implements CustomLayoutViewDefinition
}
public _createNativeView() {
this._viewGroup = new org.nativescript.widgets.ContentLayout(this._context);
const viewGroup = this._viewGroup = new org.nativescript.widgets.ContentLayout(this._context);
return viewGroup;
}
public _addViewToNativeVisualTree(child: ViewCommon, atIndex: number = -1): boolean {
@ -523,9 +524,17 @@ interface NativePercentLengthPropertyOptions {
setPixels: NativeSetter;
setPercent?: NativeSetter
}
function createNativePercentLengthProperty({ key, auto = 0, getPixels, setPixels, setPercent = percentNotSupported }: NativePercentLengthPropertyOptions) {
function createNativePercentLengthProperty(options: NativePercentLengthPropertyOptions) {
const { key, auto = 0 } = options;
let setPixels, getPixels, setPercent;
Object.defineProperty(View.prototype, key, {
get: function (this: View): PercentLength {
if (options) {
setPixels = options.setPixels;
getPixels = options.getPixels;
setPercent = options.setPercent || percentNotSupported;
options = null;
}
const value = getPixels(this.nativeView);
if (value == auto) { // tslint:disable-line
return "auto";
@ -534,6 +543,12 @@ function createNativePercentLengthProperty({ key, auto = 0, getPixels, setPixels
}
},
set: function (this: View, length: PercentLength) {
if (options) {
setPixels = options.setPixels;
getPixels = options.getPixels;
setPercent = options.setPercent || percentNotSupported;
options = null;
}
if (length == "auto") { // tslint:disable-line
setPixels(this.nativeView, auto);
} else if (typeof length === "number") {
@ -553,56 +568,56 @@ function createNativePercentLengthProperty({ key, auto = 0, getPixels, setPixels
createNativePercentLengthProperty({
key: marginTopProperty.native,
getPixels: org.nativescript.widgets.ViewHelper.getMarginTop,
setPixels: org.nativescript.widgets.ViewHelper.setMarginTop,
setPercent: org.nativescript.widgets.ViewHelper.setMarginTopPercent
get getPixels() { return org.nativescript.widgets.ViewHelper.getMarginTop },
get setPixels() { return org.nativescript.widgets.ViewHelper.setMarginTop },
get setPercent() { return org.nativescript.widgets.ViewHelper.setMarginTopPercent }
});
createNativePercentLengthProperty({
key: marginRightProperty.native,
getPixels: org.nativescript.widgets.ViewHelper.getMarginRight,
setPixels: org.nativescript.widgets.ViewHelper.setMarginRight,
setPercent: org.nativescript.widgets.ViewHelper.setMarginRightPercent
get getPixels() { return org.nativescript.widgets.ViewHelper.getMarginRight },
get setPixels() { return org.nativescript.widgets.ViewHelper.setMarginRight },
get setPercent() { return org.nativescript.widgets.ViewHelper.setMarginRightPercent }
});
createNativePercentLengthProperty({
key: marginBottomProperty.native,
getPixels: org.nativescript.widgets.ViewHelper.getMarginBottom,
setPixels: org.nativescript.widgets.ViewHelper.setMarginBottom,
setPercent: org.nativescript.widgets.ViewHelper.setMarginBottomPercent
get getPixels() { return org.nativescript.widgets.ViewHelper.getMarginBottom },
get setPixels() { return org.nativescript.widgets.ViewHelper.setMarginBottom },
get setPercent() { return org.nativescript.widgets.ViewHelper.setMarginBottomPercent }
});
createNativePercentLengthProperty({
key: marginLeftProperty.native,
getPixels: org.nativescript.widgets.ViewHelper.getMarginLeft,
setPixels: org.nativescript.widgets.ViewHelper.setMarginLeft,
setPercent: org.nativescript.widgets.ViewHelper.setMarginLeftPercent
get getPixels() { return org.nativescript.widgets.ViewHelper.getMarginLeft },
get setPixels() { return org.nativescript.widgets.ViewHelper.setMarginLeft },
get setPercent() { return org.nativescript.widgets.ViewHelper.setMarginLeftPercent }
});
createNativePercentLengthProperty({
key: widthProperty.native,
auto: android.view.ViewGroup.LayoutParams.MATCH_PARENT,
getPixels: org.nativescript.widgets.ViewHelper.getWidth,
setPixels: org.nativescript.widgets.ViewHelper.setWidth,
setPercent: org.nativescript.widgets.ViewHelper.setWidthPercent
auto: -1, //android.view.ViewGroup.LayoutParams.MATCH_PARENT,
get getPixels() { return org.nativescript.widgets.ViewHelper.getWidth },
get setPixels() { return org.nativescript.widgets.ViewHelper.setWidth },
get setPercent() { return org.nativescript.widgets.ViewHelper.setWidthPercent }
});
createNativePercentLengthProperty({
key: heightProperty.native,
auto: android.view.ViewGroup.LayoutParams.MATCH_PARENT,
getPixels: org.nativescript.widgets.ViewHelper.getHeight,
setPixels: org.nativescript.widgets.ViewHelper.setHeight,
setPercent: org.nativescript.widgets.ViewHelper.setHeightPercent
auto: -1, //android.view.ViewGroup.LayoutParams.MATCH_PARENT,
get getPixels() { return org.nativescript.widgets.ViewHelper.getHeight },
get setPixels() { return org.nativescript.widgets.ViewHelper.setHeight },
get setPercent() { return org.nativescript.widgets.ViewHelper.setHeightPercent }
});
createNativePercentLengthProperty({
key: "_minWidthNative",
getPixels: org.nativescript.widgets.ViewHelper.getMinWidth,
setPixels: org.nativescript.widgets.ViewHelper.setMinWidth
get getPixels() { return org.nativescript.widgets.ViewHelper.getMinWidth },
get setPixels() { return org.nativescript.widgets.ViewHelper.setMinWidth }
});
createNativePercentLengthProperty({
key: "_minHeightNative",
getPixels: org.nativescript.widgets.ViewHelper.getMinHeight,
setPixels: org.nativescript.widgets.ViewHelper.setMinHeight
get getPixels() { return org.nativescript.widgets.ViewHelper.getMinHeight },
get setPixels() { return org.nativescript.widgets.ViewHelper.setMinHeight }
});

View File

@ -60,10 +60,11 @@ export class DatePicker extends DatePickerBase {
public _createNativeView() {
initializeDateChangedListener();
this._android = new android.widget.DatePicker(this._context);
this._android.setCalendarViewShown(false);
const picker = this._android = new android.widget.DatePicker(this._context);
picker.setCalendarViewShown(false);
this._listener = this._listener = new DateChangedListener(this);
this._android.init(0, 0, 0, this._listener);
picker.init(0, 0, 0, this._listener);
return picker;
}
private updateNativeDate(): void {

View File

@ -134,14 +134,15 @@ export abstract class EditableTextBase extends EditableTextBaseCommon {
public _createNativeView() {
initializeEditTextListeners();
this._android = new android.widget.EditText(this._context);
const editText = this._android = new android.widget.EditText(this._context);
this._configureEditText();
this._keyListenerCache = this.android.getKeyListener();
this._keyListenerCache = editText.getKeyListener();
this._editTextListeners = this._editTextListeners || new EditTextListeners(this);
this._android.addTextChangedListener(this._editTextListeners);
this._android.setOnFocusChangeListener(this._editTextListeners);
this._android.setOnEditorActionListener(this._editTextListeners);
editText.addTextChangedListener(this._editTextListeners);
editText.setOnFocusChangeListener(this._editTextListeners);
editText.setOnEditorActionListener(this._editTextListeners);
return editText;
}
public _resetNativeView(force?: boolean) {

View File

@ -297,7 +297,7 @@ export class Frame extends FrameBase {
}
public _createNativeView() {
let root = new org.nativescript.widgets.ContentLayout(this._context);
const root = new org.nativescript.widgets.ContentLayout(this._context);
if (this._containerViewId < 0) {
this._containerViewId = android.view.View.generateViewId();
}
@ -305,6 +305,7 @@ export class Frame extends FrameBase {
this._android.rootViewGroup = root;
this._android.rootViewGroup.setId(this._containerViewId);
this._android.rootViewGroup.addOnAttachStateChangeListener(this._listener);
return root;
}
private onNativeViewAttachedToWindow(view: android.view.View): void {

View File

@ -12,10 +12,11 @@ export class HtmlView extends HtmlViewBase {
}
public _createNativeView() {
this._android = new android.widget.TextView(this._context);
const textView = this._android = new android.widget.TextView(this._context);
// This makes the html <a href...> work
this._android.setLinksClickable(true);
this._android.setMovementMethod(android.text.method.LinkMovementMethod.getInstance());
textView.setLinksClickable(true);
textView.setMovementMethod(android.text.method.LinkMovementMethod.getInstance());
return textView;
}
get [htmlProperty.native](): string {

View File

@ -65,7 +65,8 @@ export class Image extends ImageBase {
initImageCache(this._context);
}
this._android = new org.nativescript.widgets.ImageView(this._context);
const imageView = this._android = new org.nativescript.widgets.ImageView(this._context);
return imageView;
}
public _createImageSourceFromSrc() {

View File

@ -18,6 +18,7 @@ export class Label extends TextBase implements LabelDefinition {
}
public _createNativeView() {
this._android = new android.widget.TextView(this._context);
const textView = this._android = new android.widget.TextView(this._context);
return textView;
}
}

View File

@ -52,6 +52,7 @@ export class AbsoluteLayout extends AbsoluteLayoutBase {
}
public _createNativeView() {
this._layout = new org.nativescript.widgets.AbsoluteLayout(this._context);
const layout = this._layout = new org.nativescript.widgets.AbsoluteLayout(this._context);
return layout;
}
}

View File

@ -55,7 +55,8 @@ export class DockLayout extends DockLayoutBase {
}
public _createNativeView() {
this._layout = new org.nativescript.widgets.DockLayout(this._context);
const layout = this._layout = new org.nativescript.widgets.DockLayout(this._context);
return layout;
}
get [stretchLastChildProperty.native](): boolean {

View File

@ -135,7 +135,8 @@ export class FlexboxLayout extends FlexboxLayoutBase {
get _nativeView(): org.nativescript.widgets.FlexboxLayout { return this._layout; }
public _createNativeView() {
this._layout = new org.nativescript.widgets.FlexboxLayout(this._context);
const layout = this._layout = new org.nativescript.widgets.FlexboxLayout(this._context);
return layout;
}
get [flexDirectionProperty.native](): FlexDirection {

View File

@ -103,11 +103,12 @@ export class GridLayout extends GridLayoutBase {
}
public _createNativeView() {
this._layout = new org.nativescript.widgets.GridLayout(this._context);
const layout = this._layout = new org.nativescript.widgets.GridLayout(this._context);
// Update native GridLayout
this.getRows().forEach((itemSpec: ItemSpec, index, rows) => { this._onRowAdded(itemSpec); }, this);
this.getColumns().forEach((itemSpec: ItemSpec, index, rows) => { this._onColumnAdded(itemSpec); }, this);
return layout;
}
public _onRowAdded(itemSpec: ItemSpec) {

View File

@ -1,4 +1,4 @@
import {
import {
LayoutBaseCommon, clipToBoundsProperty,
paddingLeftProperty, paddingTopProperty, paddingRightProperty, paddingBottomProperty, Length
} from "./layout-base-common";
@ -25,33 +25,29 @@ export class LayoutBase extends LayoutBaseCommon {
console.warn(`clipToBounds with value false is not supported on Android. You can use this.android.getParent().setClipChildren(false) as an alternative`);
}
//PaddingTop
get [paddingTopProperty.native](): Length {
return { value: org.nativescript.widgets.ViewHelper.getPaddingTop(this.nativeView), unit: "px" };
return { value: this._defaultPaddingTop, unit: "px" }
}
set [paddingTopProperty.native](value: Length) {
org.nativescript.widgets.ViewHelper.setPaddingTop(this.nativeView, Length.toDevicePixels(value, 0) + Length.toDevicePixels(this.style.borderTopWidth, 0));
}
//PaddingRight
get [paddingRightProperty.native](): Length {
return { value: org.nativescript.widgets.ViewHelper.getPaddingRight(this.nativeView), unit: "px" };
return { value: this._defaultPaddingRight, unit: "px" }
}
set [paddingRightProperty.native](value: Length) {
org.nativescript.widgets.ViewHelper.setPaddingRight(this.nativeView, Length.toDevicePixels(value, 0) + Length.toDevicePixels(this.style.borderRightWidth, 0));
}
//PaddingBottom
get [paddingBottomProperty.native](): Length {
return { value: org.nativescript.widgets.ViewHelper.getPaddingBottom(this.nativeView), unit: "px" };
return { value: this._defaultPaddingBottom, unit: "px" }
}
set [paddingBottomProperty.native](value: Length) {
org.nativescript.widgets.ViewHelper.setPaddingBottom(this.nativeView, Length.toDevicePixels(value, 0) + Length.toDevicePixels(this.style.borderBottomWidth, 0));
}
//PaddingLeft
get [paddingLeftProperty.native](): Length {
return { value: org.nativescript.widgets.ViewHelper.getPaddingLeft(this.nativeView), unit: "px" };
return { value: this._defaultPaddingLeft, unit: "px" }
}
set [paddingLeftProperty.native](value: Length) {
org.nativescript.widgets.ViewHelper.setPaddingLeft(this.nativeView, Length.toDevicePixels(value, 0) + Length.toDevicePixels(this.style.borderLeftWidth, 0));

View File

@ -51,8 +51,9 @@ export class Layout extends LayoutBase implements LayoutDefinition {
public _createNativeView() {
initializeNativeViewGroup();
this._viewGroup = new NativeViewGroup(this._context);
const layout = this._viewGroup = new NativeViewGroup(this._context);
this._viewGroup[OWNER] = this;
return layout;
}
public _disposeNativeView() {

View File

@ -14,7 +14,8 @@ export class StackLayout extends StackLayoutBase {
}
public _createNativeView() {
this._layout = new org.nativescript.widgets.StackLayout(this._context);
const layout = this._layout = new org.nativescript.widgets.StackLayout(this._context);
return layout;
}
get [orientationProperty.native](): "horizontal" | "vertical" {

View File

@ -14,7 +14,8 @@ export class WrapLayout extends WrapLayoutBase {
}
public _createNativeView() {
this._layout = new org.nativescript.widgets.WrapLayout(this._context);
const layout = this._layout = new org.nativescript.widgets.WrapLayout(this._context);
return layout;
}
get [orientationProperty.native](): "horizontal" | "vertical" {

View File

@ -81,22 +81,21 @@ export class ListPicker extends ListPickerBase {
public _createNativeView() {
initializeNativeClasses();
this._android = new android.widget.NumberPicker(this._context);
const picker = this._android = new android.widget.NumberPicker(this._context);
let editText = getEditText(this._android);
this._editText = editText;
this._selectorWheelPaint = getSelectorWheelPaint(this._android);
this._selectorWheelPaint = getSelectorWheelPaint(picker);
this._android.setDescendantFocusability(android.widget.NumberPicker.FOCUS_BLOCK_DESCENDANTS);
this._android.setMinValue(0);
this._android.setMaxValue(0);
this._android.setValue(0);
picker.setDescendantFocusability(android.widget.NumberPicker.FOCUS_BLOCK_DESCENDANTS);
picker.setMinValue(0);
picker.setMaxValue(0);
picker.setValue(0);
this._formatter = this._formatter || new Formatter(this);
this._android.setFormatter(this._formatter);
picker.setFormatter(this._formatter);
this._valueChangedListener = this._valueChangedListener || new ValueChangeListener(this);
this._android.setOnValueChangedListener(this._valueChangedListener);
picker.setOnValueChangedListener(this._valueChangedListener);
if (editText) {
//Fix the disappearing selected item.
@ -107,8 +106,8 @@ export class ListPicker extends ListPickerBase {
editText.setText(" ", android.widget.TextView.BufferType.NORMAL);
}
this._android.setWrapSelectorWheel(false);
this.nativeView = this._android;
picker.setWrapSelectorWheel(false);
return picker;
}
private _fixNumberPickerRendering() {
@ -119,7 +118,7 @@ export class ListPicker extends ListPickerBase {
this._editText.setFilters([]);
this._editText.invalidate(); //Force the EditText to redraw
}
this.android.invalidate();
this._android.invalidate();
}
get [selectedIndexProperty.native](): number {

View File

@ -50,7 +50,7 @@ export class ListView extends ListViewBase {
public _createNativeView() {
initializeItemClickListener();
this._android = new android.widget.ListView(this._context);
const listView = this._android = new android.widget.ListView(this._context);
this._android.setDescendantFocusability(android.view.ViewGroup.FOCUS_AFTER_DESCENDANTS);
this.updateEffectiveRowHeight();
@ -66,6 +66,7 @@ export class ListView extends ListViewBase {
this._itemClickListener = this._itemClickListener || new ItemClickListener(this);
this.android.setOnItemClickListener(this._itemClickListener);
return listView;
}
get android(): android.widget.ListView {

View File

@ -1,4 +1,4 @@
import { View, PageBase, Color, actionBarHiddenProperty, statusBarStyleProperty, androidStatusBarBackgroundProperty, HorizontalAlignment, VerticalAlignment } from "./page-common";
import { View, PageBase, Color, actionBarHiddenProperty, statusBarStyleProperty, androidStatusBarBackgroundProperty } from "./page-common";
import { ActionBar } from "ui/action-bar";
import { GridLayout } from "ui/layouts/grid-layout";
import { DIALOG_FRAGMENT_TAG } from "./constants";
@ -35,8 +35,8 @@ function initializeDialogFragment() {
dialog.requestWindowFeature(android.view.Window.FEATURE_NO_TITLE);
// Hide actionBar and adjust alignment based on _fullscreen value.
this._owner.horizontalAlignment = this._fullscreen ? HorizontalAlignment.STRETCH : HorizontalAlignment.CENTER;
this._owner.verticalAlignment = this._fullscreen ? VerticalAlignment.STRETCH : VerticalAlignment.MIDDLE;
this._owner.horizontalAlignment = this._fullscreen ? "stretch" : "center";
this._owner.verticalAlignment = this._fullscreen ? "stretch" : "middle";
this._owner.actionBarHidden = true;
const nativeView = <android.view.View>this._owner._nativeView;
@ -103,10 +103,11 @@ export class Page extends PageBase {
}
public _createNativeView() {
this._grid = new org.nativescript.widgets.GridLayout(this._context);
const layout = this._grid = new org.nativescript.widgets.GridLayout(this._context);
this._grid.addRow(new org.nativescript.widgets.ItemSpec(1, org.nativescript.widgets.GridUnitType.auto));
this._grid.addRow(new org.nativescript.widgets.ItemSpec(1, org.nativescript.widgets.GridUnitType.star));
this.nativeView.setBackgroundColor(new Color("white").android);
return layout;
}
public _addViewToNativeVisualTree(child: View, atIndex?: number): boolean {

View File

@ -9,7 +9,8 @@ export class Placeholder extends View implements PlaceholderDefinition {
public _createNativeView() {
let args = <CreateViewEventData>{ eventName: Placeholder.creatingViewEvent, object: this, view: undefined, context: this._context };
this.notify(args);
this._android = <android.view.View>args.view;
const view = this._android = <android.view.View>args.view;
return view;
}
get android(): android.view.View {

View File

@ -11,7 +11,8 @@ export class Progress extends ProgressBase {
private _android: android.widget.ProgressBar;
public _createNativeView() {
this._android = new android.widget.ProgressBar(this._context, null, R_ATTR_PROGRESS_BAR_STYLE_HORIZONTAL);
const progressBar = this._android = new android.widget.ProgressBar(this._context, null, R_ATTR_PROGRESS_BAR_STYLE_HORIZONTAL);
return progressBar;
}
get android(): android.widget.ProgressBar {

View File

@ -29,7 +29,7 @@ export class ProxyViewContainer extends LayoutBase implements ProxyViewContainer
}
public _createNativeView() {
//
return undefined;
}
public _getNativeViewsCount(): number {

View File

@ -83,6 +83,7 @@ export class ScrollView extends ScrollViewBase {
}
this._android.setId(this._androidViewId);
return this._android;
}
public _onOrientationChanged() {

View File

@ -104,6 +104,7 @@ export class SearchBar extends SearchBarBase {
this._closeListener = this._closeListener || new CloseListener(this);
this._android.setOnCloseListener(this._closeListener);
return this._android;
}
get android(): android.widget.SearchView {

View File

@ -211,6 +211,7 @@ export class SegmentedBar extends SegmentedBarBase {
this._android.addView(tabHostLayout);
this._android.setup();
this._android.setOnTabChangedListener(this.listener);
return this._android;
}
get android(): android.widget.TabHost {

View File

@ -54,6 +54,7 @@ export class Slider extends SliderBase {
this.changeListener = this.changeListener || new SeekBarChangeListener(this);
this._android = new android.widget.SeekBar(this._context);
this._android.setOnSeekBarChangeListener(this.changeListener);
return this._android;
}
get android(): android.widget.SeekBar {

View File

@ -74,6 +74,7 @@ function loadCss(cssFile?: string): RuleSet[] {
application.on("cssChanged", onCssChanged);
application.on("livesync", onLiveSync);
application.on("launch", () => loadCss(application.getCssFileName()));
let pattern: RegExp = /('|")(.*?)\1/;
@ -371,5 +372,3 @@ class InlineSelector extends SelectorCore {
public ruleset: RuleSet;
public match(node: Node): boolean { return true; }
}
loadCss(application.getCssFileName());

View File

@ -45,6 +45,7 @@ export class Switch extends SwitchBase {
this._android = new android.widget.Switch(this._context);
this.listener = this.listener || new CheckedChangeListener(this);
this._android.setOnCheckedChangeListener(this.listener);
return this._android;
}
get [checkedProperty.native](): boolean {

View File

@ -307,6 +307,7 @@ export class TabView extends TabViewBase {
(<any>this._viewPager).addOnPageChangeListener(this._pageChagedListener);
this.nativeView = this._viewPager;
this._nativeView = this._viewPager;
return this._grid;
}
private setElevation() {

View File

@ -13,6 +13,59 @@ import { FontWeight, FontStyle } from "ui/styling/font";
export * from "./text-base-common";
interface TextTransformation {
new (owner: TextBase): android.text.method.TransformationMethod;
}
let TextTransformation: TextTransformation;
function initializeTextTransformation(): void {
if (TextTransformation) {
return;
}
@Interfaces([android.text.method.TransformationMethod])
class TextTransformationImpl extends android.text.method.ReplacementTransformationMethod implements android.text.method.TransformationMethod {
constructor(public textBase: TextBase) {
super();
return global.__native(this);
}
protected getOriginal(): native.Array<string> {
return convertStringToNativeCharArray(this.textBase.formattedText ? this.textBase.formattedText.toString() : this.textBase.text);
}
protected getReplacement(): native.Array<string> {
let replacementString: string = "";
const formattedText = this.textBase.formattedText;
const textTransform = this.textBase.textTransform;
if (formattedText) {
for (let i = 0, length = formattedText.spans.length; i < length; i++) {
let span = formattedText.spans.getItem(i);
replacementString += getTransformedText(span.text, textTransform);
}
}
else {
replacementString = getTransformedText(this.textBase.text, textTransform);
}
return convertStringToNativeCharArray(replacementString);
}
public getTransformation(charSeq: any, view: android.view.View): any {
const formattedText = this.textBase.formattedText;
if (formattedText) {
return createSpannableStringBuilder(formattedText);
}
else {
return getTransformedText(this.textBase.text, this.textBase.textTransform);
}
}
}
TextTransformation = TextTransformationImpl;
}
export class TextBase extends TextBaseCommon {
_nativeView: android.widget.TextView;
@ -30,10 +83,12 @@ export class TextBase extends TextBaseCommon {
return null;
}
set [formattedTextProperty.native](value: FormattedString) {
initializeTextTransformation();
let spannableStringBuilder = createSpannableStringBuilder(value);
this._nativeView.setText(<any>spannableStringBuilder);
textProperty.nativeValueChange(this, (value === null || value === undefined) ? '' : value.toString());
if (spannableStringBuilder && this._nativeView instanceof android.widget.Button &&
!(this._nativeView.getTransformationMethod() instanceof TextTransformation)) {
// Replace Android Button's default transformation (in case the developer has not already specified a text-transform) method
@ -50,6 +105,7 @@ export class TextBase extends TextBaseCommon {
return this._nativeView.getTransformationMethod();
}
set [textTransformProperty.native](value: TextTransform | android.text.method.TransformationMethod) {
initializeTextTransformation();
if (typeof value === "string") {
this._nativeView.setTransformationMethod(new TextTransformation(this));
} else {
@ -167,7 +223,6 @@ export class TextBase extends TextBaseCommon {
}
}
//LetterSpacing
get [letterSpacingProperty.native](): number {
return org.nativescript.widgets.ViewHelper.getLetterspacing(this._nativeView);
}
@ -175,78 +230,35 @@ export class TextBase extends TextBaseCommon {
org.nativescript.widgets.ViewHelper.setLetterspacing(this._nativeView, value);
}
//PaddingTop
get [paddingTopProperty.native](): Length {
return { value: org.nativescript.widgets.ViewHelper.getPaddingTop(this.nativeView), unit: "px" };
return { value: this._defaultPaddingTop, unit: "px" }
}
set [paddingTopProperty.native](value: Length) {
org.nativescript.widgets.ViewHelper.setPaddingTop(this.nativeView, Length.toDevicePixels(value, 0) + Length.toDevicePixels(this.style.borderTopWidth, 0));
}
//PaddingRight
get [paddingRightProperty.native](): Length {
return { value: org.nativescript.widgets.ViewHelper.getPaddingRight(this.nativeView), unit: "px" };
return { value: this._defaultPaddingRight, unit: "px" }
}
set [paddingRightProperty.native](value: Length) {
org.nativescript.widgets.ViewHelper.setPaddingRight(this.nativeView, Length.toDevicePixels(value, 0) + Length.toDevicePixels(this.style.borderRightWidth, 0));
}
//PaddingBottom
get [paddingBottomProperty.native](): Length {
return { value: org.nativescript.widgets.ViewHelper.getPaddingBottom(this.nativeView), unit: "px" };
return { value: this._defaultPaddingBottom, unit: "px" }
}
set [paddingBottomProperty.native](value: Length) {
org.nativescript.widgets.ViewHelper.setPaddingBottom(this.nativeView, Length.toDevicePixels(value, 0) + Length.toDevicePixels(this.style.borderBottomWidth, 0));
}
//PaddingLeft
get [paddingLeftProperty.native](): Length {
return { value: org.nativescript.widgets.ViewHelper.getPaddingLeft(this.nativeView), unit: "px" };
return { value: this._defaultPaddingLeft, unit: "px" }
}
set [paddingLeftProperty.native](value: Length) {
org.nativescript.widgets.ViewHelper.setPaddingLeft(this.nativeView, Length.toDevicePixels(value, 0) + Length.toDevicePixels(this.style.borderLeftWidth, 0));
}
}
@Interfaces([android.text.method.TransformationMethod])
class TextTransformation extends android.text.method.ReplacementTransformationMethod {
constructor(public textBase: TextBase) {
super();
return global.__native(this);
}
protected getOriginal(): native.Array<string> {
return convertStringToNativeCharArray(this.textBase.formattedText ? this.textBase.formattedText.toString() : this.textBase.text);
}
protected getReplacement(): native.Array<string> {
let replacementString: string = "";
const formattedText = this.textBase.formattedText;
const textTransform = this.textBase.textTransform;
if (formattedText) {
for (let i = 0, length = formattedText.spans.length; i < length; i++) {
let span = formattedText.spans.getItem(i);
replacementString += getTransformedText(span.text, textTransform);
}
}
else {
replacementString = getTransformedText(this.textBase.text, textTransform);
}
return convertStringToNativeCharArray(replacementString);
}
public getTransformation(charSeq: any, view: android.view.View): any {
const formattedText = this.textBase.formattedText;
if (formattedText) {
return createSpannableStringBuilder(formattedText);
}
else {
return getTransformedText(this.textBase.text, this.textBase.textTransform);
}
}
}
function getCapitalizedString(str: string): string {
let words = str.split(" ");
let newWords = [];

View File

@ -52,6 +52,7 @@ export class TimePicker extends TimePickerBase {
let validTime = getValidTime(this, this.hour, this.minute);
this._setNativeValueSilently(validTime.hour, validTime.minute);
return this._android;
}
get android(): android.widget.TimePicker {

View File

@ -102,6 +102,7 @@ export class WebView extends WebViewBase {
this._android.getSettings().setJavaScriptEnabled(true);
this._android.getSettings().setBuiltInZoomControls(true);
this._android.setWebViewClient(this._webViewClient);
return this._android;
}
public _resetNativeView() {

View File

@ -454,7 +454,7 @@
public static getVerticalAlignment(view: android.view.View): string;
public static setVerticalAlignment(view: android.view.View, value: string): void;
public static getPadding(view: android.view.View): { left: number, top: number, right: number, bottom: number };
public static getPadding(view: android.view.View): android.graphics.Rect;
public static setPadding(view: android.view.View, left: number, top: number, right: number, bottom: number): void;
public static getPaddingLeft(view: android.view.View): number;