Add support for snapshot

Fix Layout class getMeasuredWidth & getMeasuredHeight
Move some classes to widgets
Fix API17 tests
This commit is contained in:
Hristo Hristov
2017-02-27 14:59:11 +02:00
parent 1eefb1af74
commit 33aa48bdfd
28 changed files with 950 additions and 872 deletions

View File

@@ -15,6 +15,33 @@ function generateItemId(): number {
return actionItemIdGenerator;
}
interface MenuItemClickListener {
new (owner: ActionBar): android.support.v7.widget.Toolbar.OnMenuItemClickListener;
}
let MenuItemClickListener: MenuItemClickListener;
function initializeMenuItemClickListener(): void {
if (MenuItemClickListener) {
return;
}
@Interfaces([android.support.v7.widget.Toolbar.OnMenuItemClickListener])
class MenuItemClickListenerImpl extends java.lang.Object implements android.support.v7.widget.Toolbar.OnMenuItemClickListener {
constructor(public owner: ActionBar) {
super();
return global.__native(this);
}
onMenuItemClick(item: android.view.IMenuItem): boolean {
let itemId = item.getItemId();
return this.owner._onAndroidItemSelected(itemId);
}
}
MenuItemClickListener = MenuItemClickListenerImpl;
}
export class ActionItem extends ActionItemBase {
private _androidPosition: AndroidActionItemSettings = {
position: "actionBar",
@@ -73,24 +100,6 @@ export class NavigationButton extends ActionItem {
}
@Interfaces([android.support.v7.widget.Toolbar.OnMenuItemClickListener])
class MenuItemClickListener extends java.lang.Object implements android.support.v7.widget.Toolbar.OnMenuItemClickListener {
constructor(public owner: WeakRef<ActionBar>) {
super();
return global.__native(this);
}
onMenuItemClick(item: android.view.IMenuItem): boolean {
let owner = this.owner.get();
if (!owner) {
return false;
}
let itemId = item.getItemId();
return owner._onAndroidItemSelected(itemId);
}
}
export class ActionBar extends ActionBarBase {
private _appResources: android.content.res.Resources;
private _android: AndroidActionBarSettings;
@@ -116,8 +125,9 @@ export class ActionBar extends ActionBarBase {
}
public _createNativeView() {
initializeMenuItemClickListener();
this._toolbar = new android.support.v7.widget.Toolbar(this._context);
this._menuItemClickListener = this._menuItemClickListener || new MenuItemClickListener(new WeakRef(this));
this._menuItemClickListener = this._menuItemClickListener || new MenuItemClickListener(this);
this._toolbar.setOnMenuItemClickListener(this._menuItemClickListener);
}
@@ -342,7 +352,7 @@ export class ActionBar extends ActionBarBase {
return defaultTitleTextColor;
}
set [colorProperty.native](value: number | Color) {
let color = value instanceof Color ? value.android : value;
let color = value instanceof Color ? value.android : value;
this.nativeView.setTitleTextColor(color);
}
}

View File

@@ -40,7 +40,7 @@ declare module "ui/action-bar" {
update();
//@private
_isEmpty(): boolean
_isEmpty(): boolean;
//@endprivate
_addArrayFromBuilder(name: string, value: Array<any>): void;

View File

@@ -6,34 +6,45 @@
export * from "./button-common";
@Interfaces([android.view.View.OnClickListener])
class ClickListener extends java.lang.Object implements android.view.View.OnClickListener {
constructor(public owner: WeakRef<Button>) {
super();
return global.__native(this);
interface ClickListener {
new (owner: Button): android.view.View.OnClickListener;
}
let ClickListener: ClickListener;
function initializeClickListener(): void {
if (ClickListener) {
return;
}
public onClick(v: android.view.View): void {
let btn = this.owner.get();
if (btn) {
btn._emit(ButtonBase.tapEvent);
@Interfaces([android.view.View.OnClickListener])
class ClickListenerImpl extends java.lang.Object implements android.view.View.OnClickListener {
constructor(public owner: Button) {
super();
return global.__native(this);
}
public onClick(v: android.view.View): void {
this.owner._emit(ButtonBase.tapEvent);
}
}
ClickListener = ClickListenerImpl;
}
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;
}
public _createNativeView() {
let weakRef = new WeakRef(this);
initializeClickListener();
this._button = new android.widget.Button(this._context);
this._button.setOnClickListener(new ClickListener(weakRef));
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();
@@ -67,7 +78,7 @@ export class Button extends ButtonBase {
//PaddingTop
get [paddingTopProperty.native](): Length {
return { value: this._defaultNativePadding.top, unit: "px" }
return { value: this._defaultNativePadding.top, unit: "px" }
}
set [paddingTopProperty.native](value: Length) {
org.nativescript.widgets.ViewHelper.setPaddingTop(this.nativeView, Length.toDevicePixels(value, 0) + Length.toDevicePixels(this.style.borderTopWidth, 0));
@@ -75,7 +86,7 @@ export class Button extends ButtonBase {
//PaddingRight
get [paddingRightProperty.native](): Length {
return { value: this._defaultNativePadding.right, unit: "px" }
return { value: this._defaultNativePadding.right, unit: "px" }
}
set [paddingRightProperty.native](value: Length) {
org.nativescript.widgets.ViewHelper.setPaddingRight(this.nativeView, Length.toDevicePixels(value, 0) + Length.toDevicePixels(this.style.borderRightWidth, 0));
@@ -83,7 +94,7 @@ export class Button extends ButtonBase {
//PaddingBottom
get [paddingBottomProperty.native](): Length {
return { value: this._defaultNativePadding.bottom, unit: "px" }
return { value: this._defaultNativePadding.bottom, unit: "px" }
}
set [paddingBottomProperty.native](value: Length) {
org.nativescript.widgets.ViewHelper.setPaddingBottom(this.nativeView, Length.toDevicePixels(value, 0) + Length.toDevicePixels(this.style.borderBottomWidth, 0));
@@ -91,7 +102,7 @@ export class Button extends ButtonBase {
//PaddingLeft
get [paddingLeftProperty.native](): Length {
return { value: this._defaultNativePadding.left, unit: "px" }
return { value: this._defaultNativePadding.left, unit: "px" }
}
set [paddingLeftProperty.native](value: Length) {
org.nativescript.widgets.ViewHelper.setPaddingLeft(this.nativeView, Length.toDevicePixels(value, 0) + Length.toDevicePixels(this.style.borderLeftWidth, 0));
@@ -103,8 +114,8 @@ export class Button extends ButtonBase {
set [zIndexProperty.native](value: number) {
org.nativescript.widgets.ViewHelper.setZIndex(this.nativeView, value);
// API >= 21
if (this.nativeView.setStateListAnimator){
if (this.nativeView.setStateListAnimator) {
this.nativeView.setStateListAnimator(null);
}
}
}
}

View File

@@ -108,8 +108,6 @@ export abstract class ViewCommon extends ViewBase implements ViewDefinition {
public _gestureObservers = {};
// public parent: ViewCommon;
public effectiveMinWidth: number;
public effectiveMinHeight: number;
public effectiveWidth: number;
@@ -127,11 +125,6 @@ export abstract class ViewCommon extends ViewBase implements ViewDefinition {
public effectiveBorderBottomWidth: number;
public effectiveBorderLeftWidth: number;
constructor() {
super();
this._goToVisualState("normal");
}
observe(type: GestureTypes, callback: (args: GestureEventData) => void, thisArg?: any): void {
if (!this._gestureObservers[type]) {
this._gestureObservers[type] = [];

View File

@@ -17,49 +17,53 @@ const ANDROID = "_android";
const NATIVE_VIEW = "_nativeView";
const VIEW_GROUP = "_viewGroup";
// TODO: Move this class into widgets.
@Interfaces([android.view.View.OnTouchListener])
class DisableUserInteractionListener extends java.lang.Object implements android.view.View.OnTouchListener {
constructor() {
super();
return global.__native(this);
}
onTouch(view: android.view.View, event: android.view.MotionEvent): boolean {
return true;
}
interface TouchListener {
new (owner: View): android.view.View.OnTouchListener;
}
@Interfaces([android.view.View.OnTouchListener])
class TouchListener extends java.lang.Object implements android.view.View.OnTouchListener {
constructor(private owner: WeakRef<View>) {
super();
return global.__native(this);
let TouchListener: TouchListener;
let disableUserInteractionListener: org.nativescript.widgets.DisableUserInteractionListener;
function initializeDisabledListener(): void {
if (disableUserInteractionListener) {
return;
}
onTouch(view: android.view.View, event: android.view.MotionEvent): boolean {
let owner = this.owner.get();
if (!owner) {
return false;
disableUserInteractionListener = new org.nativescript.widgets.DisableUserInteractionListener();
}
function initializeTouchListener(): void {
if (TouchListener) {
return;
}
@Interfaces([android.view.View.OnTouchListener])
class TouchListenerImpl extends java.lang.Object implements android.view.View.OnTouchListener {
constructor(private owner: View) {
super();
return global.__native(this);
}
for (let type in owner._gestureObservers) {
let list = owner._gestureObservers[type];
for (let i = 0; i < list.length; i++) {
list[i].androidOnTouchEvent(event);
onTouch(view: android.view.View, event: android.view.MotionEvent): boolean {
const owner = this.owner;
for (let type in owner._gestureObservers) {
let list = owner._gestureObservers[type];
list.forEach(element => {
element.androidOnTouchEvent(event);
});
}
}
let nativeView = owner._nativeView;
if (!nativeView || !nativeView.onTouchEvent) {
return false;
}
let nativeView = owner._nativeView;
if (!nativeView || !nativeView.onTouchEvent) {
return false;
}
return nativeView.onTouchEvent(event);
return nativeView.onTouchEvent(event);
}
}
}
const disableUserInteractionListener = new DisableUserInteractionListener();
TouchListener = TouchListenerImpl;
}
export class View extends ViewCommon {
private touchListenerIsSet: boolean;
@@ -101,7 +105,8 @@ export class View extends ViewCommon {
this._nativeView.setClickable(true);
}
this.touchListener = this.touchListener || new TouchListener(new WeakRef(this));
initializeTouchListener();
this.touchListener = this.touchListener || new TouchListener(this);
this._nativeView.setOnTouchListener(this.touchListener);
}
}
@@ -311,6 +316,7 @@ export class View extends ViewCommon {
}
set [isUserInteractionEnabledProperty.native](value: boolean) {
if (!value) {
initializeDisabledListener();
// User interaction is disabled -- we stop it and we do not care whether someone wants to listen for gestures.
this._nativeView.setOnTouchListener(disableUserInteractionListener);
} else {
@@ -480,62 +486,60 @@ function createNativePercentLengthProperty({key, auto = 0, getPixels, setPixels,
});
}
const ViewHelper = org.nativescript.widgets.ViewHelper;
createNativePercentLengthProperty({
key: marginTopProperty.native,
getPixels: ViewHelper.getMarginTop,
setPixels: ViewHelper.setMarginTop,
setPercent: ViewHelper.setMarginTopPercent
getPixels: org.nativescript.widgets.ViewHelper.getMarginTop,
setPixels: org.nativescript.widgets.ViewHelper.setMarginTop,
setPercent: org.nativescript.widgets.ViewHelper.setMarginTopPercent
});
createNativePercentLengthProperty({
key: marginRightProperty.native,
getPixels: ViewHelper.getMarginRight,
setPixels: ViewHelper.setMarginRight,
setPercent: ViewHelper.setMarginRightPercent
getPixels: org.nativescript.widgets.ViewHelper.getMarginRight,
setPixels: org.nativescript.widgets.ViewHelper.setMarginRight,
setPercent: org.nativescript.widgets.ViewHelper.setMarginRightPercent
});
createNativePercentLengthProperty({
key: marginBottomProperty.native,
getPixels: ViewHelper.getMarginBottom,
setPixels: ViewHelper.setMarginBottom,
setPercent: ViewHelper.setMarginBottomPercent
getPixels: org.nativescript.widgets.ViewHelper.getMarginBottom,
setPixels: org.nativescript.widgets.ViewHelper.setMarginBottom,
setPercent: org.nativescript.widgets.ViewHelper.setMarginBottomPercent
});
createNativePercentLengthProperty({
key: marginLeftProperty.native,
getPixels: ViewHelper.getMarginLeft,
setPixels: ViewHelper.setMarginLeft,
setPercent: ViewHelper.setMarginLeftPercent
getPixels: org.nativescript.widgets.ViewHelper.getMarginLeft,
setPixels: org.nativescript.widgets.ViewHelper.setMarginLeft,
setPercent: org.nativescript.widgets.ViewHelper.setMarginLeftPercent
});
createNativePercentLengthProperty({
key: widthProperty.native,
auto: android.view.ViewGroup.LayoutParams.MATCH_PARENT,
getPixels: ViewHelper.getWidth,
setPixels: ViewHelper.setWidth,
setPercent: ViewHelper.setWidthPercent
getPixels: org.nativescript.widgets.ViewHelper.getWidth,
setPixels: org.nativescript.widgets.ViewHelper.setWidth,
setPercent: org.nativescript.widgets.ViewHelper.setWidthPercent
});
createNativePercentLengthProperty({
key: heightProperty.native,
auto: android.view.ViewGroup.LayoutParams.MATCH_PARENT,
getPixels: ViewHelper.getHeight,
setPixels: ViewHelper.setHeight,
setPercent: ViewHelper.setHeightPercent
getPixels: org.nativescript.widgets.ViewHelper.getHeight,
setPixels: org.nativescript.widgets.ViewHelper.setHeight,
setPercent: org.nativescript.widgets.ViewHelper.setHeightPercent
});
createNativePercentLengthProperty({
key: "_minWidthNative",
getPixels: ViewHelper.getMinWidth,
setPixels: ViewHelper.setMinWidth
getPixels: org.nativescript.widgets.ViewHelper.getMinWidth,
setPixels: org.nativescript.widgets.ViewHelper.setMinWidth
});
createNativePercentLengthProperty({
key: "_minHeightNative",
getPixels: ViewHelper.getMinHeight,
setPixels: ViewHelper.setMinHeight
getPixels: org.nativescript.widgets.ViewHelper.getMinHeight,
setPixels: org.nativescript.widgets.ViewHelper.setMinHeight
});
export class CustomLayoutView extends View implements CustomLayoutViewDefinition {

View File

@@ -5,39 +5,49 @@
export * from "./date-picker-common";
@Interfaces([android.widget.DatePicker.OnDateChangedListener])
class DateChangedListener extends java.lang.Object implements android.widget.DatePicker.OnDateChangedListener {
constructor(public owner: WeakRef<DatePicker>) {
super()
return global.__native(this);
interface DateChangedListener {
new (owner: DatePicker): android.widget.DatePicker.OnDateChangedListener;
}
let DateChangedListener: DateChangedListener;
function initializeDateChangedListener(): void {
if (DateChangedListener) {
return;
}
onDateChanged(picker: android.widget.DatePicker, year: number, month: number, day: number) {
let owner = this.owner.get();
if (!owner) {
return;
@Interfaces([android.widget.DatePicker.OnDateChangedListener])
class DateChangedListenerImpl extends java.lang.Object implements android.widget.DatePicker.OnDateChangedListener {
constructor(public owner: DatePicker) {
super()
return global.__native(this);
}
let dateIsChanged = false;
if (year !== owner.year) {
yearProperty.nativeValueChange(owner, year);
dateIsChanged = true;
}
onDateChanged(picker: android.widget.DatePicker, year: number, month: number, day: number) {
const owner = this.owner;
let dateIsChanged = false;
if (year !== owner.year) {
yearProperty.nativeValueChange(owner, year);
dateIsChanged = true;
}
if ((month + 1) !== owner.month) {
monthProperty.nativeValueChange(owner, month + 1);
dateIsChanged = true;
}
if ((month + 1) !== owner.month) {
monthProperty.nativeValueChange(owner, month + 1);
dateIsChanged = true;
}
if (day !== owner.day) {
dayProperty.nativeValueChange(owner, day);
dateIsChanged = true;
}
if (day !== owner.day) {
dayProperty.nativeValueChange(owner, day);
dateIsChanged = true;
}
if (dateIsChanged) {
dateProperty.nativeValueChange(owner, new Date(year, month, day));
if (dateIsChanged) {
dateProperty.nativeValueChange(owner, new Date(year, month, day));
}
}
}
DateChangedListener = DateChangedListenerImpl;
}
export class DatePicker extends DatePickerBase {
@@ -49,9 +59,10 @@ export class DatePicker extends DatePickerBase {
}
public _createNativeView() {
initializeDateChangedListener();
this._android = new android.widget.DatePicker(this._context);
this._android.setCalendarViewShown(false);
this._listener = this._listener = new DateChangedListener(new WeakRef(this));
this._listener = this._listener = new DateChangedListener(this);
this._android.init(0, 0, 0, this._listener);
}
@@ -120,4 +131,4 @@ export class DatePicker extends DatePickerBase {
picker.setMinDate(newValue);
}
}
}
}

View File

@@ -9,102 +9,86 @@ import { ad } from "utils/utils";
export * from "./editable-text-base-common";
@Interfaces([android.text.TextWatcher])
class TextWatcher extends java.lang.Object implements android.text.TextWatcher {
constructor(private owner: WeakRef<EditableTextBase>) {
super();
return global.__native(this);
}
public beforeTextChanged(text: string, start: number, count: number, after: number) {
//
}
public onTextChanged(text: string, start: number, before: number, count: number) {
let owner = this.owner.get();
if (!owner) {
return;
}
let selectionStart = owner.android.getSelectionStart();
owner.android.removeTextChangedListener(owner._textWatcher);
// //RemoveThisDoubleCall
// owner.style._updateTextDecoration();
// owner.style._updateTextTransform();
owner.android.addTextChangedListener(owner._textWatcher);
owner.android.setSelection(selectionStart);
}
public afterTextChanged(editable: android.text.IEditable) {
let owner = this.owner.get();
if (!owner) {
return;
}
switch (owner.updateTextTrigger) {
case "focusLost":
owner._dirtyTextAccumulator = editable.toString();
break;
case "textChanged":
textProperty.nativeValueChange(owner, editable.toString());
break;
default:
throw new Error("Invalid updateTextTrigger: " + owner.updateTextTrigger);
}
}
}
//https://github.com/NativeScript/NativeScript/issues/2942
let dismissKeyboardTimeoutId: any;
@Interfaces([android.view.View.OnFocusChangeListener])
class FocusChangeListener extends java.lang.Object implements android.view.View.OnFocusChangeListener {
constructor(private owner: WeakRef<EditableTextBase>) {
super();
return global.__native(this);
}
public onFocusChange(view: android.view.View, hasFocus: boolean) {
let owner = this.owner.get();
if (!owner) {
return;
}
if (hasFocus) {
if (dismissKeyboardTimeoutId) {
// https://github.com/NativeScript/NativeScript/issues/2942
// Don't hide the keyboard since another (or the same) EditText has gained focus.
clearTimeout(dismissKeyboardTimeoutId);
dismissKeyboardTimeoutId = undefined;
}
}
else {
if (owner._dirtyTextAccumulator) {
textProperty.nativeValueChange(owner, owner._dirtyTextAccumulator);
owner._dirtyTextAccumulator = undefined;
}
dismissKeyboardTimeoutId = setTimeout(() => {
// https://github.com/NativeScript/NativeScript/issues/2942
// Dismiss the keyboard if focus goes to something different from EditText.
owner.dismissSoftInput();
dismissKeyboardTimeoutId = null;
}, 1);
}
}
interface EditTextListeners extends android.text.TextWatcher, android.view.View.OnFocusChangeListener, android.widget.TextView.OnEditorActionListener {
}
@Interfaces([android.widget.TextView.OnEditorActionListener])
class EditorActionListener extends java.lang.Object implements android.widget.TextView.OnEditorActionListener {
constructor(private owner: WeakRef<EditableTextBase>) {
super();
return global.__native(this);
interface EditTextListenersClass {
prototype: EditTextListeners;
new (owner: EditableTextBase): EditTextListeners;
}
let EditTextListeners: EditTextListenersClass;
function initializeEditTextListeners(): void {
if (EditTextListeners) {
return;
}
public onEditorAction(textView: android.widget.TextView, actionId: number, event: android.view.KeyEvent): boolean {
let owner = this.owner.get();
if (owner) {
@Interfaces([android.text.TextWatcher, android.view.View.OnFocusChangeListener, android.widget.TextView.OnEditorActionListener])
class EditTextListenersImpl extends java.lang.Object implements android.text.TextWatcher, android.view.View.OnFocusChangeListener, android.widget.TextView.OnEditorActionListener {
constructor(private owner: EditableTextBase) {
super();
return global.__native(this);
}
public beforeTextChanged(text: string, start: number, count: number, after: number) {
//
}
public onTextChanged(text: string, start: number, before: number, count: number) {
const owner = this.owner;
let selectionStart = owner.android.getSelectionStart();
owner.android.removeTextChangedListener(owner._editTextListeners);
owner.android.addTextChangedListener(owner._editTextListeners);
owner.android.setSelection(selectionStart);
}
public afterTextChanged(editable: android.text.IEditable) {
const owner = this.owner;
switch (owner.updateTextTrigger) {
case "focusLost":
owner._dirtyTextAccumulator = editable.toString();
break;
case "textChanged":
textProperty.nativeValueChange(owner, editable.toString());
break;
default:
throw new Error("Invalid updateTextTrigger: " + owner.updateTextTrigger);
}
}
public onFocusChange(view: android.view.View, hasFocus: boolean) {
const owner = this.owner;
if (hasFocus) {
if (dismissKeyboardTimeoutId) {
// https://github.com/NativeScript/NativeScript/issues/2942
// Don't hide the keyboard since another (or the same) EditText has gained focus.
clearTimeout(dismissKeyboardTimeoutId);
dismissKeyboardTimeoutId = undefined;
}
}
else {
if (owner._dirtyTextAccumulator) {
textProperty.nativeValueChange(owner, owner._dirtyTextAccumulator);
owner._dirtyTextAccumulator = undefined;
}
dismissKeyboardTimeoutId = setTimeout(() => {
// https://github.com/NativeScript/NativeScript/issues/2942
// Dismiss the keyboard if focus goes to something different from EditText.
owner.dismissSoftInput();
dismissKeyboardTimeoutId = null;
}, 1);
}
}
public onEditorAction(textView: android.widget.TextView, actionId: number, event: android.view.KeyEvent): boolean {
const owner = this.owner;
if (actionId === android.view.inputmethod.EditorInfo.IME_ACTION_DONE ||
actionId === android.view.inputmethod.EditorInfo.IME_ACTION_GO ||
actionId === android.view.inputmethod.EditorInfo.IME_ACTION_SEARCH ||
@@ -126,18 +110,19 @@ class EditorActionListener extends java.lang.Object implements android.widget.Te
return false;
}
}
EditTextListeners = EditTextListenersImpl;
}
export abstract class EditableTextBase extends EditableTextBaseCommon {
_textWatcher: android.text.TextWatcher;
/* tslint:disable */
_dirtyTextAccumulator: string;
/* tslint:enable */
_editTextListeners: EditTextListeners;
private _android: android.widget.EditText;
private _keyListenerCache: android.text.method.KeyListener;
private _focusChangeListener: android.view.View.OnFocusChangeListener;
private _editorActionListener: android.widget.TextView.OnEditorActionListener;
get android(): android.widget.EditText {
return this._android;
@@ -148,34 +133,24 @@ export abstract class EditableTextBase extends EditableTextBaseCommon {
public abstract _onReturnPress(): void;
public _createNativeView() {
initializeEditTextListeners();
this._android = new android.widget.EditText(this._context);
this._configureEditText();
this._keyListenerCache = this.android.getKeyListener();
let weakRef = new WeakRef(this);
this._textWatcher = this._textWatcher || new TextWatcher(weakRef);
this._android.addTextChangedListener(this._textWatcher);
this._focusChangeListener = this._focusChangeListener || new FocusChangeListener(weakRef);
this._android.setOnFocusChangeListener(this._focusChangeListener);
this._editorActionListener = this._editorActionListener || new EditorActionListener(weakRef);
this._android.setOnEditorActionListener(this._editorActionListener);
this._editTextListeners = this._editTextListeners || new EditTextListeners(this);
this._android.addTextChangedListener(this._editTextListeners);
this._android.setOnFocusChangeListener(this._editTextListeners);
this._android.setOnEditorActionListener(this._editTextListeners);
}
public _resetNativeView(force?: boolean) {
if (this._android) {
if (this._textWatcher) {
this._android.removeTextChangedListener(this._textWatcher);
}
this._android.setOnFocusChangeListener(null);
this._android.setOnEditorActionListener(null);
if (this._focusChangeListener) {
this._android.setOnFocusChangeListener(null);
}
if (this._editorActionListener) {
this._android.setOnEditorActionListener(null);
if (this._editTextListeners) {
this._android.removeTextChangedListener(this._editTextListeners);
}
}
super._resetNativeView();
@@ -436,4 +411,4 @@ export abstract class EditableTextBase extends EditableTextBaseCommon {
this._android.setHintTextColor(value);
}
}
}
}

View File

@@ -1,12 +1,226 @@
import { GestureEventData, SwipeGestureEventData, PanGestureEventData, RotationGestureEventData } from "ui/gestures";
import { GesturesObserverBase, toString, TouchAction, GestureStateTypes, GestureTypes, SwipeDirection,
View, EventData } from "./gestures-common";
import {
GesturesObserverBase, toString, TouchAction, GestureStateTypes, GestureTypes, SwipeDirection,
View, EventData
} from "./gestures-common";
// Import layout from utils directly to avoid circular references
import { layout } from "utils/utils";
export * from "./gestures-common";
interface TapAndDoubleTapGestureListener {
new (observer: GesturesObserver, target: View, type: number): android.view.GestureDetector.SimpleOnGestureListener;
}
let TapAndDoubleTapGestureListener: TapAndDoubleTapGestureListener;
function initializeTapAndDoubleTapGestureListener() {
if (TapAndDoubleTapGestureListener) {
return;
}
class TapAndDoubleTapGestureListenerImpl extends android.view.GestureDetector.SimpleOnGestureListener {
private _observer: GesturesObserver;
private _target: View;
private _type: number;
constructor(observer: GesturesObserver, target: View, type: number) {
super();
this._observer = observer;
this._target = target;
this._type = type;
return global.__native(this);
}
public onSingleTapUp(motionEvent: android.view.MotionEvent): boolean {
if (this._type & GestureTypes.tap) {
let args = _getArgs(GestureTypes.tap, this._target, motionEvent);
_executeCallback(this._observer, args);
}
return true;
}
public onDoubleTap(motionEvent: android.view.MotionEvent): boolean {
if (this._type & GestureTypes.doubleTap) {
let args = _getArgs(GestureTypes.doubleTap, this._target, motionEvent);
_executeCallback(this._observer, args);
}
return true;
}
public onDown(motionEvent: android.view.MotionEvent): boolean {
return true;
}
public onLongPress(motionEvent: android.view.MotionEvent): void {
if (this._type & GestureTypes.longPress) {
let args = _getArgs(GestureTypes.longPress, this._target, motionEvent);
_executeCallback(this._observer, args);
}
}
}
TapAndDoubleTapGestureListener = TapAndDoubleTapGestureListenerImpl;
}
interface PinchGestureListener {
new (observer: GesturesObserver, target: View): android.view.ScaleGestureDetector.SimpleOnScaleGestureListener;
}
let PinchGestureListener: PinchGestureListener;
function initializePinchGestureListener() {
if (PinchGestureListener) {
return;
}
class PinchGestureListenerImpl extends android.view.ScaleGestureDetector.SimpleOnScaleGestureListener {
private _observer: GesturesObserver;
private _target: View;
private _scale: number;
private _density: number;
constructor(observer: GesturesObserver, target: View) {
super();
this._observer = observer;
this._target = target;
this._density = layout.getDisplayDensity();
return global.__native(this);
}
public onScaleBegin(detector: android.view.ScaleGestureDetector): boolean {
this._scale = detector.getScaleFactor();
let args = new PinchGestureEventData(
this._target,
detector,
this._scale,
this._target,
GestureStateTypes.began);
_executeCallback(this._observer, args);
return true;
}
public onScale(detector: android.view.ScaleGestureDetector): boolean {
this._scale *= detector.getScaleFactor();
let args = new PinchGestureEventData(
this._target,
detector,
this._scale,
this._target,
GestureStateTypes.changed);
_executeCallback(this._observer, args);
return true;
}
public onScaleEnd(detector: android.view.ScaleGestureDetector): void {
this._scale *= detector.getScaleFactor();
let args = new PinchGestureEventData(
this._target,
detector,
this._scale,
this._target,
GestureStateTypes.ended);
_executeCallback(this._observer, args);
}
}
PinchGestureListener = PinchGestureListenerImpl;
}
interface SwipeGestureListener {
new (observer: GesturesObserver, target: View): android.view.GestureDetector.SimpleOnGestureListener;
}
let SwipeGestureListener: SwipeGestureListener;
function initializeSwipeGestureListener() {
if (SwipeGestureListener) {
return;
}
class SwipeGestureListenerImpl extends android.view.GestureDetector.SimpleOnGestureListener {
private _observer: GesturesObserver;
private _target: View;
constructor(observer: GesturesObserver, target: View) {
super();
this._observer = observer;
this._target = target;
return global.__native(this);
}
public onDown(motionEvent: android.view.MotionEvent): boolean {
return true;
}
public onFling(initialEvent: android.view.MotionEvent, currentEvent: android.view.MotionEvent, velocityX: number, velocityY: number): boolean {
let result = false;
let args: SwipeGestureEventData;
try {
let deltaY = currentEvent.getY() - initialEvent.getY();
let deltaX = currentEvent.getX() - initialEvent.getX();
if (Math.abs(deltaX) > Math.abs(deltaY)) {
if (Math.abs(deltaX) > SWIPE_THRESHOLD
&& Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
if (deltaX > 0) {
args = _getSwipeArgs(SwipeDirection.right, this._target, initialEvent, currentEvent);
_executeCallback(this._observer, args);
result = true;
} else {
args = _getSwipeArgs(SwipeDirection.left, this._target, initialEvent, currentEvent);
_executeCallback(this._observer, args);
result = true;
}
}
} else {
if (Math.abs(deltaY) > SWIPE_THRESHOLD
&& Math.abs(velocityY) > SWIPE_VELOCITY_THRESHOLD) {
if (deltaY > 0) {
args = _getSwipeArgs(SwipeDirection.down, this._target, initialEvent, currentEvent);
_executeCallback(this._observer, args);
result = true;
} else {
args = _getSwipeArgs(SwipeDirection.up, this._target, initialEvent, currentEvent);
_executeCallback(this._observer, args);
result = true;
}
}
}
} catch (ex) {
//
}
return result;
}
}
SwipeGestureListener = SwipeGestureListenerImpl;
}
const SWIPE_THRESHOLD = 100;
const SWIPE_VELOCITY_THRESHOLD = 100;
const INVALID_POINTER_ID = -1;
@@ -78,18 +292,18 @@ export class GesturesObserver extends GesturesObserverBase {
this._detach();
if (type & GestureTypes.tap || type & GestureTypes.doubleTap || type & GestureTypes.longPress) {
ensureTapAndDoubleTapGestureListenerClass();
this._simpleGestureDetector = new android.support.v4.view.GestureDetectorCompat(target._context, new TapAndDoubleTapGestureListenerClass(this, this.target, type));
initializeTapAndDoubleTapGestureListener();
this._simpleGestureDetector = new android.support.v4.view.GestureDetectorCompat(target._context, new TapAndDoubleTapGestureListener(this, this.target, type));
}
if (type & GestureTypes.pinch) {
ensurePinchGestureListenerClass();
this._scaleGestureDetector = new android.view.ScaleGestureDetector(target._context, new PinchGestureListenerClass(this, this.target));
initializePinchGestureListener();
this._scaleGestureDetector = new android.view.ScaleGestureDetector(target._context, new PinchGestureListener(this, this.target));
}
if (type & GestureTypes.swipe) {
ensureSwipeGestureListenerClass();
this._swipeGestureDetector = new android.support.v4.view.GestureDetectorCompat(target._context, new SwipeGestureListenerClass(this, this.target));
initializeSwipeGestureListener();
this._swipeGestureDetector = new android.support.v4.view.GestureDetectorCompat(target._context, new SwipeGestureListener(this, this.target));
}
if (type & GestureTypes.pan) {
@@ -182,57 +396,6 @@ function _executeCallback(observer: GesturesObserver, args: GestureEventData) {
}
}
let TapAndDoubleTapGestureListenerClass;
function ensureTapAndDoubleTapGestureListenerClass() {
if (TapAndDoubleTapGestureListenerClass) {
return;
}
class TapAndDoubleTapGestureListener extends android.view.GestureDetector.SimpleOnGestureListener {
private _observer: GesturesObserver;
private _target: View;
private _type: number;
constructor(observer: GesturesObserver, target: View, type: number) {
super();
this._observer = observer;
this._target = target;
this._type = type;
return global.__native(this);
}
public onSingleTapUp(motionEvent: android.view.MotionEvent): boolean {
if (this._type & GestureTypes.tap) {
let args = _getArgs(GestureTypes.tap, this._target, motionEvent);
_executeCallback(this._observer, args);
}
return true;
}
public onDoubleTap(motionEvent: android.view.MotionEvent): boolean {
if (this._type & GestureTypes.doubleTap) {
let args = _getArgs(GestureTypes.doubleTap, this._target, motionEvent);
_executeCallback(this._observer, args);
}
return true;
}
public onDown(motionEvent: android.view.MotionEvent): boolean {
return true;
}
public onLongPress(motionEvent: android.view.MotionEvent): void {
if (this._type & GestureTypes.longPress) {
let args = _getArgs(GestureTypes.longPress, this._target, motionEvent);
_executeCallback(this._observer, args);
}
}
}
TapAndDoubleTapGestureListenerClass = TapAndDoubleTapGestureListener;
}
class PinchGestureEventData implements PinchGestureEventData {
public type = GestureTypes.pinch;
public eventName = toString(GestureTypes.pinch);
@@ -255,155 +418,6 @@ class PinchGestureEventData implements PinchGestureEventData {
}
}
let PinchGestureListenerClass;
function ensurePinchGestureListenerClass() {
if (PinchGestureListenerClass) {
return;
}
class PinchGestureListener extends android.view.ScaleGestureDetector.SimpleOnScaleGestureListener {
private _observer: GesturesObserver;
private _target: View;
private _scale: number;
private _density: number;
constructor(observer: GesturesObserver, target: View) {
super();
this._observer = observer;
this._target = target;
this._density = layout.getDisplayDensity();
return global.__native(this);
}
public onScaleBegin(detector: android.view.ScaleGestureDetector): boolean {
this._scale = detector.getScaleFactor();
let args = new PinchGestureEventData(
this._target,
detector,
this._scale,
this._target,
GestureStateTypes.began);
_executeCallback(this._observer, args);
return true;
}
public onScale(detector: android.view.ScaleGestureDetector): boolean {
this._scale *= detector.getScaleFactor();
let args = new PinchGestureEventData(
this._target,
detector,
this._scale,
this._target,
GestureStateTypes.changed);
_executeCallback(this._observer, args);
return true;
}
public onScaleEnd(detector: android.view.ScaleGestureDetector): void {
this._scale *= detector.getScaleFactor();
let args = new PinchGestureEventData(
this._target,
detector,
this._scale,
this._target,
GestureStateTypes.ended);
_executeCallback(this._observer, args);
}
}
PinchGestureListenerClass = PinchGestureListener;
}
let SwipeGestureListenerClass;
function ensureSwipeGestureListenerClass() {
if (SwipeGestureListenerClass) {
return;
}
class SwipeGestureListener extends android.view.GestureDetector.SimpleOnGestureListener {
private _observer: GesturesObserver;
private _target: View;
constructor(observer: GesturesObserver, target: View) {
super();
this._observer = observer;
this._target = target;
return global.__native(this);
}
public onDown(motionEvent: android.view.MotionEvent): boolean {
return true;
}
public onFling(initialEvent: android.view.MotionEvent, currentEvent: android.view.MotionEvent, velocityX: number, velocityY: number): boolean {
let result = false;
let args: SwipeGestureEventData;
try {
let deltaY = currentEvent.getY() - initialEvent.getY();
let deltaX = currentEvent.getX() - initialEvent.getX();
if (Math.abs(deltaX) > Math.abs(deltaY)) {
if (Math.abs(deltaX) > SWIPE_THRESHOLD
&& Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
if (deltaX > 0) {
args = _getSwipeArgs(SwipeDirection.right, this._target, initialEvent, currentEvent);
_executeCallback(this._observer, args);
result = true;
} else {
args = _getSwipeArgs(SwipeDirection.left, this._target, initialEvent, currentEvent);
_executeCallback(this._observer, args);
result = true;
}
}
} else {
if (Math.abs(deltaY) > SWIPE_THRESHOLD
&& Math.abs(velocityY) > SWIPE_VELOCITY_THRESHOLD) {
if (deltaY > 0) {
args = _getSwipeArgs(SwipeDirection.down, this._target, initialEvent, currentEvent);
_executeCallback(this._observer, args);
result = true;
} else {
args = _getSwipeArgs(SwipeDirection.up, this._target, initialEvent, currentEvent);
_executeCallback(this._observer, args);
result = true;
}
}
}
} catch (ex) {
//
}
return result;
}
}
SwipeGestureListenerClass = SwipeGestureListener;
}
class CustomPanGestureDetector {
private observer: GesturesObserver;
private target: View;

View File

@@ -60,6 +60,7 @@ export class Image extends ImageBase {
}
public _createNativeView() {
initializeImageLoadedListener();
if (!imageFetcher) {
initImageCache(this._context);
}
@@ -77,7 +78,7 @@ export class Image extends ImageBase {
let value = this.src;
let async = this.loadMode === ASYNC;
this._imageLoadedListener = this._imageLoadedListener || new ImageLoadedListener(new WeakRef(this));
this._imageLoadedListener = this._imageLoadedListener || new ImageLoadedListener(this);
if (typeof value === "string") {
value = value.trim();
@@ -163,17 +164,27 @@ export class Image extends ImageBase {
}
}
@Interfaces([org.nativescript.widgets.image.Worker.OnImageLoadedListener])
class ImageLoadedListener extends java.lang.Object implements org.nativescript.widgets.image.Worker.OnImageLoadedListener {
constructor(private owner: WeakRef<Image>) {
super();
return global.__native(this);
interface ImageLoadedListener {
new (owner: Image): org.nativescript.widgets.image.Worker.OnImageLoadedListener;
}
let ImageLoadedListener: ImageLoadedListener;
function initializeImageLoadedListener() {
if (ImageLoadedListener) {
return;
}
onImageLoaded(success: boolean): void {
let owner = this.owner.get();
if (owner) {
owner.isLoading = false;
@Interfaces([org.nativescript.widgets.image.Worker.OnImageLoadedListener])
class ImageLoadedListenerImpl extends java.lang.Object implements org.nativescript.widgets.image.Worker.OnImageLoadedListener {
constructor(private owner: Image) {
super();
return global.__native(this);
}
onImageLoaded(success: boolean): void {
this.owner.isLoading = false;
}
}
ImageLoadedListener = ImageLoadedListenerImpl;
}

View File

@@ -77,64 +77,62 @@ function setLayoutParamsProperty(view: View, setter: (lp: org.nativescript.widge
}
}
import FlexboxLayoutWidget = org.nativescript.widgets.FlexboxLayout;
const flexDirectionMap = {
[FlexDirection.ROW]: FlexboxLayoutWidget.FLEX_DIRECTION_ROW,
[FlexDirection.ROW_REVERSE]: FlexboxLayoutWidget.FLEX_DIRECTION_ROW_REVERSE,
[FlexDirection.COLUMN]: FlexboxLayoutWidget.FLEX_DIRECTION_COLUMN,
[FlexDirection.COLUMN_REVERSE]: FlexboxLayoutWidget.FLEX_DIRECTION_COLUMN_REVERSE
}
[FlexDirection.ROW]: 0, //FlexboxLayoutWidget.FLEX_DIRECTION_ROW,
[FlexDirection.ROW_REVERSE]: 1, //FlexboxLayoutWidget.FLEX_DIRECTION_ROW_REVERSE,
[FlexDirection.COLUMN]: 2, //FlexboxLayoutWidget.FLEX_DIRECTION_COLUMN,
[FlexDirection.COLUMN_REVERSE]: 3 //FlexboxLayoutWidget.FLEX_DIRECTION_COLUMN_REVERSE
};
const flexWrapMap = {
[FlexWrap.NOWRAP]: FlexboxLayoutWidget.FLEX_WRAP_NOWRAP,
[FlexWrap.WRAP]: FlexboxLayoutWidget.FLEX_WRAP_WRAP,
[FlexWrap.WRAP_REVERSE]: FlexboxLayoutWidget.FLEX_WRAP_WRAP_REVERSE
[FlexWrap.NOWRAP]: 0, //FlexboxLayoutWidget.FLEX_WRAP_NOWRAP,
[FlexWrap.WRAP]: 1, //FlexboxLayoutWidget.FLEX_WRAP_WRAP,
[FlexWrap.WRAP_REVERSE]: 2 //FlexboxLayoutWidget.FLEX_WRAP_WRAP_REVERSE
}
const justifyContentMap = {
[JustifyContent.CENTER]: FlexboxLayoutWidget.JUSTIFY_CONTENT_CENTER,
[JustifyContent.FLEX_END]: FlexboxLayoutWidget.JUSTIFY_CONTENT_FLEX_END,
[JustifyContent.FLEX_START]: FlexboxLayoutWidget.JUSTIFY_CONTENT_FLEX_START,
[JustifyContent.SPACE_AROUND]: FlexboxLayoutWidget.JUSTIFY_CONTENT_SPACE_AROUND,
[JustifyContent.SPACE_BETWEEN]: FlexboxLayoutWidget.JUSTIFY_CONTENT_SPACE_BETWEEN
[JustifyContent.FLEX_START]: 0, //FlexboxLayoutWidget.JUSTIFY_CONTENT_FLEX_START,
[JustifyContent.FLEX_END]: 1, //FlexboxLayoutWidget.JUSTIFY_CONTENT_FLEX_END,
[JustifyContent.CENTER]: 2, //FlexboxLayoutWidget.JUSTIFY_CONTENT_CENTER,
[JustifyContent.SPACE_BETWEEN]: 3, //FlexboxLayoutWidget.JUSTIFY_CONTENT_SPACE_BETWEEN
[JustifyContent.SPACE_AROUND]: 4 //FlexboxLayoutWidget.JUSTIFY_CONTENT_SPACE_AROUND,
}
const alignItemsMap = {
[AlignItems.BASELINE]: FlexboxLayoutWidget.ALIGN_ITEMS_BASELINE,
[AlignItems.CENTER]: FlexboxLayoutWidget.ALIGN_ITEMS_CENTER,
[AlignItems.FLEX_END]: FlexboxLayoutWidget.ALIGN_ITEMS_FLEX_END,
[AlignItems.FLEX_START]: FlexboxLayoutWidget.ALIGN_ITEMS_FLEX_START,
[AlignItems.STRETCH]: FlexboxLayoutWidget.ALIGN_ITEMS_STRETCH
[AlignItems.FLEX_START]: 0, //FlexboxLayoutWidget.ALIGN_ITEMS_FLEX_START,
[AlignItems.FLEX_END]: 1, //FlexboxLayoutWidget.ALIGN_ITEMS_FLEX_END,
[AlignItems.CENTER]: 2, //FlexboxLayoutWidget.ALIGN_ITEMS_CENTER,
[AlignItems.BASELINE]: 3, //FlexboxLayoutWidget.ALIGN_ITEMS_BASELINE,
[AlignItems.STRETCH]: 4 //FlexboxLayoutWidget.ALIGN_ITEMS_STRETCH
}
const alignContentMap = {
[AlignContent.CENTER]: FlexboxLayoutWidget.ALIGN_CONTENT_CENTER,
[AlignContent.FLEX_END]: FlexboxLayoutWidget.ALIGN_CONTENT_FLEX_END,
[AlignContent.FLEX_START]: FlexboxLayoutWidget.ALIGN_CONTENT_FLEX_START,
[AlignContent.SPACE_AROUND]: FlexboxLayoutWidget.ALIGN_CONTENT_SPACE_AROUND,
[AlignContent.SPACE_BETWEEN]: FlexboxLayoutWidget.ALIGN_CONTENT_SPACE_BETWEEN,
[AlignContent.STRETCH]: FlexboxLayoutWidget.ALIGN_CONTENT_STRETCH
[AlignContent.FLEX_START]: 0, //FlexboxLayoutWidget.ALIGN_CONTENT_FLEX_START,
[AlignContent.FLEX_END]: 1, //FlexboxLayoutWidget.ALIGN_CONTENT_FLEX_END,
[AlignContent.CENTER]: 2, //FlexboxLayoutWidget.ALIGN_CONTENT_CENTER,
[AlignContent.SPACE_BETWEEN]: 3, //FlexboxLayoutWidget.ALIGN_CONTENT_SPACE_BETWEEN,
[AlignContent.SPACE_AROUND]: 4, //FlexboxLayoutWidget.ALIGN_CONTENT_SPACE_AROUND,
[AlignContent.STRETCH]: 5 //FlexboxLayoutWidget.ALIGN_CONTENT_STRETCH
}
const alignSelfMap = {
[AlignSelf.AUTO]: FlexboxLayoutWidget.LayoutParams.ALIGN_SELF_AUTO,
[AlignSelf.FLEX_START]: FlexboxLayoutWidget.LayoutParams.ALIGN_SELF_FLEX_START,
[AlignSelf.FLEX_END]: FlexboxLayoutWidget.LayoutParams.ALIGN_SELF_FLEX_END,
[AlignSelf.CENTER]: FlexboxLayoutWidget.LayoutParams.ALIGN_SELF_CENTER,
[AlignSelf.BASELINE]: FlexboxLayoutWidget.LayoutParams.ALIGN_SELF_BASELINE,
[AlignSelf.STRETCH]: FlexboxLayoutWidget.LayoutParams.ALIGN_SELF_STRETCH
[AlignSelf.AUTO]: -1, //FlexboxLayoutWidget.LayoutParams.ALIGN_SELF_AUTO,
[AlignSelf.FLEX_START]: 0, //FlexboxLayoutWidget.LayoutParams.ALIGN_SELF_FLEX_START,
[AlignSelf.FLEX_END]: 1, //FlexboxLayoutWidget.LayoutParams.ALIGN_SELF_FLEX_END,
[AlignSelf.CENTER]: 2, //FlexboxLayoutWidget.LayoutParams.ALIGN_SELF_CENTER,
[AlignSelf.BASELINE]: 3, //FlexboxLayoutWidget.LayoutParams.ALIGN_SELF_BASELINE,
[AlignSelf.STRETCH]: 4 //FlexboxLayoutWidget.LayoutParams.ALIGN_SELF_STRETCH
}
export class FlexboxLayout extends FlexboxLayoutBase {
private _layout: FlexboxLayoutWidget;
private _layout: org.nativescript.widgets.FlexboxLayout;
constructor() {
super();
}
get android(): FlexboxLayoutWidget { return this._layout; }
get _nativeView(): FlexboxLayoutWidget { return this._layout; }
get android(): org.nativescript.widgets.FlexboxLayout { return this._layout; }
get _nativeView(): org.nativescript.widgets.FlexboxLayout { return this._layout; }
public _createNativeView() {
this._layout = new org.nativescript.widgets.FlexboxLayout(this._context);
@@ -161,7 +159,7 @@ export class FlexboxLayout extends FlexboxLayoutBase {
this.android.setJustifyContent(justifyContentMap[justifyContent]);
}
get [alignItemsProperty.native](): AlignItems{
get [alignItemsProperty.native](): AlignItems {
return alignItemsProperty.defaultValue;
}
set [alignItemsProperty.native](alignItems: AlignItems) {

View File

@@ -5,27 +5,41 @@ export * from "ui/layouts/layout-base";
const OWNER = Symbol("_owner");
var NativeViewGroupClass;
function ensureNativeViewGroupClass() {
if (NativeViewGroupClass) {
interface NativeViewGroup {
new (context: android.content.Context): android.view.ViewGroup;
}
let NativeViewGroup: NativeViewGroup;
function initializeNativeViewGroup() {
if (NativeViewGroup) {
return;
}
NativeViewGroupClass = (<any>android.view.ViewGroup).extend({
onMeasure: function (widthMeasureSpec, heightMeasureSpec) {
class NativeViewGroupImpl extends android.view.ViewGroup {
constructor(context: android.content.Context) {
super(context);
return global.__native(this);
}
onMeasure(widthMeasureSpec: number, heightMeasureSpec: number): void {
const owner: View = this[OWNER];
owner.onMeasure(widthMeasureSpec, heightMeasureSpec);
this.setMeasuredDimension(owner.getMeasuredWidth(), owner.getMeasuredHeight());
},
onLayout: function (changed: boolean, left: number, top: number, right: number, bottom: number): void {
}
onLayout(changed: boolean, left: number, top: number, right: number, bottom: number): void {
const owner: View = this[OWNER];
owner.onLayout(left, top, right, bottom);
}
});
}
NativeViewGroup = NativeViewGroupImpl;
}
export class Layout extends LayoutBase implements LayoutDefinition {
private _viewGroup: android.view.ViewGroup;
_measuredWidth: number;
_measuredHeight: number;
get android(): android.view.ViewGroup {
return this._viewGroup;
@@ -36,8 +50,8 @@ export class Layout extends LayoutBase implements LayoutDefinition {
}
public _createNativeView() {
ensureNativeViewGroupClass();
this._viewGroup = new NativeViewGroupClass(this._context);
initializeNativeViewGroup();
this._viewGroup = new NativeViewGroup(this._context);
this._viewGroup[OWNER] = this;
}
@@ -77,4 +91,23 @@ export class Layout extends LayoutBase implements LayoutDefinition {
public onLayout(left: number, top: number, right: number, bottom: number): void {
// Don't call super because it will trigger layout again.
}
// NOTE: overriden so we cache measuredWidth & measuredHeight.
public setMeasuredDimension(measuredWidth: number, measuredHeight: number): void {
super.setMeasuredDimension(measuredWidth, measuredHeight);
this._measuredWidth = measuredWidth;
this._measuredHeight = measuredHeight;
}
// NOTE: base implementation use the nativeView.getMeasuredWidth which should
// not be called while we are in onMeasure.
public getMeasuredWidth(): number {
return this._measuredWidth;
}
// NOTE: base implementation use the nativeView.getMeasuredWidth which should
// not be called while we are in onMeasure.
public getMeasuredHeight(): number {
return this._measuredHeight;
}
}

View File

@@ -3,36 +3,48 @@ import { ItemsSource } from "ui/list-picker";
export * from "./list-picker-common";
@Interfaces([android.widget.NumberPicker.Formatter])
class Formatter extends java.lang.Object implements android.widget.NumberPicker.Formatter {
constructor(private owner: WeakRef<ListPicker>) {
super();
return global.__native(this);
}
format(index: number): string {
let owner = this.owner.get();
if (owner) {
return owner._getItemAsString(index);
}
return " ";
}
interface Formatter {
new (owner: ListPicker): android.widget.NumberPicker.Formatter;
}
@Interfaces([android.widget.NumberPicker.OnValueChangeListener])
class ValueChangeListener extends java.lang.Object implements android.widget.NumberPicker.OnValueChangeListener {
constructor(private owner: WeakRef<ListPicker>) {
super();
return global.__native(this);
interface ValueChangeListener {
new (owner: ListPicker): android.widget.NumberPicker.OnValueChangeListener;
}
let Formatter: Formatter;
let ValueChangeListener: ValueChangeListener;
function initializeNativeClasses(): void {
if (Formatter) {
return;
}
onValueChange(picker: android.widget.NumberPicker, oldValue: number, newValue: number): void {
let owner = this.owner.get();
if (owner) {
selectedIndexProperty.nativeValueChange(owner, newValue);
@Interfaces([android.widget.NumberPicker.Formatter])
class FormatterImpl extends java.lang.Object implements android.widget.NumberPicker.Formatter {
constructor(private owner: ListPicker) {
super();
return global.__native(this);
}
format(index: number): string {
return this.owner._getItemAsString(index);
}
}
@Interfaces([android.widget.NumberPicker.OnValueChangeListener])
class ValueChangeListenerImpl extends java.lang.Object implements android.widget.NumberPicker.OnValueChangeListener {
constructor(private owner: ListPicker) {
super();
return global.__native(this);
}
onValueChange(picker: android.widget.NumberPicker, oldValue: number, newValue: number): void {
selectedIndexProperty.nativeValueChange(this.owner, newValue);
}
}
Formatter = FormatterImpl;
ValueChangeListener = ValueChangeListenerImpl;
}
function getEditText(picker: android.widget.NumberPicker): android.widget.EditText {
@@ -68,6 +80,7 @@ export class ListPicker extends ListPickerBase {
}
public _createNativeView() {
initializeNativeClasses();
this._android = new android.widget.NumberPicker(this._context);
let editText = getEditText(this._android);
this._editText = editText;
@@ -79,10 +92,10 @@ export class ListPicker extends ListPickerBase {
this._android.setMaxValue(0);
this._android.setValue(0);
this._formatter = this._formatter || new Formatter(new WeakRef(this));
this._formatter = this._formatter || new Formatter(this);
this._android.setFormatter(this._formatter);
this._valueChangedListener = this._valueChangedListener || new ValueChangeListener(new WeakRef(this));
this._valueChangedListener = this._valueChangedListener || new ValueChangeListener(this);
this._android.setOnValueChangedListener(this._valueChangedListener);
if (editText) {

View File

@@ -13,20 +13,32 @@ const ITEMLOADING = ListViewBase.itemLoadingEvent;
const LOADMOREITEMS = ListViewBase.loadMoreItemsEvent;
const ITEMTAP = ListViewBase.itemTapEvent;
@Interfaces([android.widget.AdapterView.OnItemClickListener])
class ItemClickListener extends java.lang.Object implements android.widget.AdapterView.OnItemClickListener {
constructor(private owner: WeakRef<ListView>) {
super();
return global.__native(this);
interface ItemClickListener {
new (owner: ListView): android.widget.AdapterView.OnItemClickListener;
}
let ItemClickListener: ItemClickListener;
function initializeItemClickListener(): void {
if (ItemClickListener) {
return;
}
onItemClick<T extends android.widget.Adapter>(parent: android.widget.AdapterView<T>, convertView: android.view.View, index: number, id: number) {
let owner = this.owner.get();
if (owner) {
let view = owner._realizedTemplates.get(owner._getItemTemplate(index).key).get(convertView);
@Interfaces([android.widget.AdapterView.OnItemClickListener])
class ItemClickListenerImpl extends java.lang.Object implements android.widget.AdapterView.OnItemClickListener {
constructor(private owner: ListView) {
super();
return global.__native(this);
}
onItemClick<T extends android.widget.Adapter>(parent: android.widget.AdapterView<T>, convertView: android.view.View, index: number, id: number) {
const owner = this.owner;
const view = owner._realizedTemplates.get(owner._getItemTemplate(index).key).get(convertView);
owner.notify({ eventName: ITEMTAP, object: owner, index: index, view: view });
}
}
ItemClickListener = ItemClickListenerImpl;
}
export class ListView extends ListViewBase {
@@ -37,6 +49,7 @@ export class ListView extends ListViewBase {
public _realizedTemplates = new Map<string, Map<android.view.View, View>>();
public _createNativeView() {
initializeItemClickListener();
this._android = new android.widget.ListView(this._context);
this._android.setDescendantFocusability(android.view.ViewGroup.FOCUS_AFTER_DESCENDANTS);
this.updateEffectiveRowHeight();
@@ -51,7 +64,7 @@ export class ListView extends ListViewBase {
ensureListViewAdapterClass();
this._android.setAdapter(new ListViewAdapterClass(this));
this._itemClickListener = this._itemClickListener || new ItemClickListener(new WeakRef(this));
this._itemClickListener = this._itemClickListener || new ItemClickListener(this);
this.android.setOnItemClickListener(this._itemClickListener);
}

View File

@@ -10,17 +10,17 @@ const SYSTEM_UI_FLAG_LIGHT_STATUS_BAR = 0x00002000;
const STATUS_BAR_LIGHT_BCKG = -657931;
const STATUS_BAR_DARK_BCKG = 1711276032;
interface DialogFragmentClass {
interface DialogFragment {
new (owner: Page, fullscreen: boolean, shownCallback: () => void, dismissCallback: () => void): android.app.DialogFragment;
}
let DialogFragmentClass: DialogFragmentClass;
let DialogFragment: DialogFragment;
function ensureDialogFragmentClass() {
if (DialogFragmentClass) {
function initializeDialogFragment() {
if (DialogFragment) {
return;
}
class DialogFragmentClassInner extends android.app.DialogFragment {
class DialogFragmentImpl extends android.app.DialogFragment {
constructor(
private _owner: Page,
private _fullscreen: boolean,
@@ -83,7 +83,7 @@ function ensureDialogFragmentClass() {
};
DialogFragmentClass = DialogFragmentClassInner;
DialogFragment = DialogFragmentImpl;
}
export class Page extends PageBase {
@@ -158,9 +158,9 @@ export class Page extends PageBase {
this._setupUI(parent._context);
this._isAddedToNativeVisualTree = true;
ensureDialogFragmentClass();
initializeDialogFragment();
this._dialogFragment = new DialogFragmentClass(this, !!fullscreen, () => this._raiseShownModallyEvent(), () => this.closeModal());
this._dialogFragment = new DialogFragment(this, !!fullscreen, () => this._raiseShownModallyEvent(), () => this.closeModal());
super._raiseShowingModallyEvent();

View File

@@ -9,16 +9,31 @@ export * from "./search-bar-common";
const SEARCHTEXT = Symbol("searchText");
const QUERY = Symbol("query");
@Interfaces([android.widget.SearchView.OnQueryTextListener])
class QueryTextListener extends java.lang.Object implements android.widget.SearchView.OnQueryTextListener {
constructor(private owner: WeakRef<SearchBar>) {
super();
return global.__native(this);
interface QueryTextListener {
new (owner: SearchBar): android.widget.SearchView.OnQueryTextListener;
}
interface CloseListener {
new (owner: SearchBar): android.widget.SearchView.OnCloseListener;
}
let QueryTextListener: QueryTextListener;
let CloseListener: CloseListener;
function initializeNativeClasses(): void {
if (QueryTextListener) {
return;
}
onQueryTextChange(newText: string): boolean {
let owner = this.owner.get();
if (owner) {
@Interfaces([android.widget.SearchView.OnQueryTextListener])
class QueryTextListenerImpl extends java.lang.Object implements android.widget.SearchView.OnQueryTextListener {
constructor(private owner: SearchBar) {
super();
return global.__native(this);
}
onQueryTextChange(newText: string): boolean {
const owner = this.owner;
textProperty.nativeValueChange(owner, newText);
// This code is needed since sometimes OnCloseListener is not called!
@@ -27,37 +42,36 @@ class QueryTextListener extends java.lang.Object implements android.widget.Searc
}
this[SEARCHTEXT] = newText;
return true;
}
return true;
}
onQueryTextSubmit(query: string): boolean {
let owner = this.owner.get();
if (owner) {
onQueryTextSubmit(query: string): boolean {
const owner = this.owner;
// This code is needed since onQueryTextSubmit is called twice with same query!
if (query !== "" && this[QUERY] !== query) {
owner._emit(SearchBarBase.submitEvent);
}
this[QUERY] = query;
return true;
}
return true;
}
}
@Interfaces([android.widget.SearchView.OnCloseListener])
class CloseListener extends java.lang.Object implements android.widget.SearchView.OnCloseListener {
constructor(private owner: WeakRef<SearchBar>) {
super();
return global.__native(this);
}
onClose(): boolean {
let owner = this.owner.get();
if (owner) {
owner._emit(SearchBarBase.clearEvent);
@Interfaces([android.widget.SearchView.OnCloseListener])
class CloseListenerImpl extends java.lang.Object implements android.widget.SearchView.OnCloseListener {
constructor(private owner: SearchBar) {
super();
return global.__native(this);
}
onClose(): boolean {
this.owner._emit(SearchBarBase.clearEvent);
return true;
}
return true;
}
QueryTextListener = QueryTextListenerImpl;
CloseListener = CloseListenerImpl;
}
export class SearchBar extends SearchBarBase {
@@ -79,14 +93,15 @@ export class SearchBar extends SearchBarBase {
}
public _createNativeView() {
initializeNativeClasses();
this._android = new android.widget.SearchView(this._context);
this._android.setIconified(false);
this._queryTextListener = this._queryTextListener || new QueryTextListener(new WeakRef(this));
this._queryTextListener = this._queryTextListener || new QueryTextListener(this);
this._android.setOnQueryTextListener(this._queryTextListener);
this._closeListener = this._closeListener || new CloseListener(new WeakRef(this));
this._closeListener = this._closeListener || new CloseListener(this);
this._android.setOnCloseListener(this._closeListener);
}

View File

@@ -10,40 +10,77 @@ const R_ID_TABCONTENT = 0x01020011;
const R_ATTR_STATE_SELECTED = 0x010100a1;
const TITLE_TEXT_VIEW_ID = 16908310; // http://developer.android.com/reference/android/R.id.html#title
interface TabChangeListener {
new (owner: SegmentedBar): android.widget.TabHost.OnTabChangeListener;
}
interface TabContentFactory {
new (owner: SegmentedBar): android.widget.TabHost.TabContentFactory;
}
interface TabHost {
new (context: android.content.Context, attrs: android.util.AttributeSet): android.widget.TabHost;
}
let apiLevel: number;
// TODO: Move this into widgets.
let SegmentedBarColorDrawableClass;
function ensureSegmentedBarColorDrawableClass() {
if (SegmentedBarColorDrawableClass) {
let TabHost: TabHost;
let TabChangeListener: TabChangeListener;
let TabContentFactory: TabContentFactory;
function initializeNativeClasses(): void {
if (TabChangeListener) {
return;
}
apiLevel = android.os.Build.VERSION.SDK_INT;
class SegmentedBarColorDrawable extends android.graphics.drawable.ColorDrawable {
constructor(arg: any) {
super(arg);
@Interfaces([android.widget.TabHost.OnTabChangeListener])
class TabChangeListenerImpl extends java.lang.Object implements android.widget.TabHost.OnTabChangeListener {
constructor(private owner: SegmentedBar) {
super();
return global.__native(this);
}
public draw(canvas: android.graphics.Canvas): void {
let p = new android.graphics.Paint();
p.setColor(this.getColor());
p.setStyle(android.graphics.Paint.Style.FILL);
canvas.drawRect(0, this.getBounds().height() - 15, this.getBounds().width(), this.getBounds().height(), p);
onTabChanged(id: string): void {
const owner = this.owner;
if (owner.shouldChangeSelectedIndex()) {
owner.selectedIndex = parseInt(id);
}
}
}
SegmentedBarColorDrawableClass = SegmentedBarColorDrawable;
}
@Interfaces([android.widget.TabHost.TabContentFactory])
class TabContentFactoryImpl extends java.lang.Object implements android.widget.TabHost.TabContentFactory {
constructor(private owner: SegmentedBar) {
super();
return global.__native(this);
}
function setBackground(view: android.view.View, background: android.graphics.drawable.Drawable): void {
if (apiLevel >= 16) {
view.setBackground(background);
} else {
view.setBackgroundDrawable(background);
createTabContent(tag: string): android.view.View {
const tv = new android.widget.TextView(this.owner._context);
// This is collapsed by default and made visible
// by android when TabItem becomes visible/selected.
// TODO: Try commenting visibility change.
tv.setVisibility(android.view.View.GONE);
tv.setMaxLines(1);
tv.setEllipsize(android.text.TextUtils.TruncateAt.END);
return tv;
}
}
class TabHostImpl extends android.widget.TabHost {
constructor(context: android.content.Context, attrs: android.util.AttributeSet) {
super(context, attrs);
return global.__native(this);
}
protected onAttachedToWindow(): void {
// overriden to remove the code that will steal the focus from edit fields.
}
}
TabHost = TabHostImpl;
TabChangeListener = TabChangeListenerImpl;
TabContentFactory = TabContentFactoryImpl;
}
export class SegmentedBarItem extends SegmentedBarItemBase {
@@ -122,59 +159,20 @@ export class SegmentedBarItem extends SegmentedBarItemBase {
if (apiLevel > 21 && backgroundDrawable && typeof backgroundDrawable.setColorFilter === "function") {
const newDrawable = backgroundDrawable.getConstantState().newDrawable();
newDrawable.setColorFilter(color, android.graphics.PorterDuff.Mode.SRC_IN);
setBackground(viewGroup, newDrawable);
org.nativescript.widgets.ViewHelper.setBackground(viewGroup, newDrawable);
} else {
const stateDrawable = new android.graphics.drawable.StateListDrawable();
let arr = Array.create("int", 1);
arr[0] = R_ATTR_STATE_SELECTED;
let colorDrawable: android.graphics.drawable.ColorDrawable = new SegmentedBarColorDrawableClass(color);
let colorDrawable: android.graphics.drawable.ColorDrawable = new org.nativescript.widgets.SegmentedBarColorDrawable(color);
stateDrawable.addState(arr, colorDrawable);
stateDrawable.setBounds(0, 15, viewGroup.getRight(), viewGroup.getBottom());
setBackground(viewGroup, stateDrawable);
org.nativescript.widgets.ViewHelper.setBackground(viewGroup, stateDrawable);
}
} else {
setBackground(viewGroup, value.newDrawable());
}
}
}
@Interfaces([android.widget.TabHost.OnTabChangeListener])
class TabChangeListener extends java.lang.Object implements android.widget.TabHost.OnTabChangeListener {
constructor(private owner: WeakRef<SegmentedBar>) {
super();
return global.__native(this);
}
onTabChanged(id: string): void {
let owner = this.owner.get();
if (owner && owner.shouldChangeSelectedIndex()) {
owner.selectedIndex = parseInt(id);
}
}
}
@Interfaces([android.widget.TabHost.TabContentFactory])
class TabContentFactory extends java.lang.Object implements android.widget.TabHost.TabContentFactory {
constructor(private owner: WeakRef<SegmentedBar>) {
super();
return global.__native(this);
}
createTabContent(tag: string): android.view.View {
let owner = this.owner.get();
if (owner) {
let tv = new android.widget.TextView(owner._context);
// This is collapsed by default and made visible
// by android when TabItem becomes visible/selected.
// TODO: Try commenting visibility change.
tv.setVisibility(android.view.View.GONE);
tv.setMaxLines(1);
tv.setEllipsize(android.text.TextUtils.TruncateAt.END);
return tv;
} else {
throw new Error(`Invalid owner: ${this.owner}`);
org.nativescript.widgets.ViewHelper.setBackground(viewGroup, value.newDrawable());
}
}
}
@@ -190,14 +188,12 @@ export class SegmentedBar extends SegmentedBarBase {
}
public _createNativeView() {
ensureTabHostClass();
ensureSegmentedBarColorDrawableClass();
initializeNativeClasses();
let weakRef = new WeakRef(this);
this._android = new TabHostClass(this._context, null);
this._android = new TabHost(this._context, null);
this.listener = this.listener || new TabChangeListener(weakRef);
this.tabContentFactory = this.tabContentFactory || new TabContentFactory(weakRef);
this.listener = this.listener || new TabChangeListener(this);
this.tabContentFactory = this.tabContentFactory || new TabContentFactory(this);
const tabHostLayout = new android.widget.LinearLayout(this._context);
tabHostLayout.setOrientation(android.widget.LinearLayout.VERTICAL);
@@ -251,24 +247,3 @@ export class SegmentedBar extends SegmentedBarBase {
}
}
}
let TabHostClass;
function ensureTabHostClass() {
if (TabHostClass) {
return;
}
class OurTabHost extends android.widget.TabHost {
constructor(context: any, attrs: any) {
super(context, attrs);
return global.__native(this);
}
protected onAttachedToWindow(): void {
// overriden to remove the code that will steal the focus from edit fields.
}
}
TabHostClass = OurTabHost;
}

View File

@@ -6,30 +6,42 @@
export * from "./slider-common";
@Interfaces([android.widget.SeekBar.OnSeekBarChangeListener])
class SeekBarChangeListener extends java.lang.Object implements android.widget.SeekBar.OnSeekBarChangeListener {
constructor(private owner: WeakRef<Slider>) {
super();
return global.__native(this);
interface SeekBarChangeListener {
new (owner: Slider): android.widget.SeekBar.OnSeekBarChangeListener;
}
let SeekBarChangeListener: SeekBarChangeListener;
function initializeSeekBarChangeListener(): void {
if (SeekBarChangeListener) {
return;
}
onProgressChanged(seekBar: android.widget.SeekBar, progress: number, fromUser: boolean): void {
let owner = this.owner.get();
if (owner) {
if (!owner._supressNativeValue) {
let newValue: number = seekBar.getProgress() + owner.minValue;
valueProperty.nativeValueChange(owner, newValue);
}
@Interfaces([android.widget.SeekBar.OnSeekBarChangeListener])
class SeekBarChangeListenerImpl extends java.lang.Object implements android.widget.SeekBar.OnSeekBarChangeListener {
constructor(private owner: Slider) {
super();
return global.__native(this);
}
onProgressChanged(seekBar: android.widget.SeekBar, progress: number, fromUser: boolean): void {
const owner = this.owner;
if (!owner._supressNativeValue) {
let newValue: number = seekBar.getProgress() + owner.minValue;
valueProperty.nativeValueChange(owner, newValue);
}
}
onStartTrackingTouch(seekBar: android.widget.SeekBar): void {
//
}
onStopTrackingTouch(seekBar: android.widget.SeekBar): void {
//
}
}
onStartTrackingTouch(seekBar: android.widget.SeekBar): void {
//
}
onStopTrackingTouch(seekBar: android.widget.SeekBar): void {
//
}
SeekBarChangeListener = SeekBarChangeListenerImpl;
}
export class Slider extends SliderBase {
@@ -38,7 +50,8 @@ export class Slider extends SliderBase {
private changeListener: android.widget.SeekBar.OnSeekBarChangeListener;
public _createNativeView() {
this.changeListener = this.changeListener || new SeekBarChangeListener(new WeakRef(this));
initializeSeekBarChangeListener();
this.changeListener = this.changeListener || new SeekBarChangeListener(this);
this._android = new android.widget.SeekBar(this._context);
this._android.setOnSeekBarChangeListener(this.changeListener);
}

View File

@@ -72,32 +72,26 @@ export module ad {
refreshBorderDrawable(view, <org.nativescript.widgets.BorderDrawable>backgroundDrawable);
}
// This should be done only when backgroundImage is set!!!
if ((background.hasBorderWidth() || background.hasBorderRadius() || background.clipPath) && getSDK() < 18) {
// Switch to software because of unsupported canvas methods if hardware acceleration is on:
// http://developer.android.com/guide/topics/graphics/hardware-accel.html
cache.layerType = cache.getLayerType();
cache.setLayerType(android.view.View.LAYER_TYPE_SOFTWARE, null);
if (cache.layerType === undefined) {
cache.layerType = cache.getLayerType();
cache.setLayerType(android.view.View.LAYER_TYPE_SOFTWARE, null);
}
}
}
else {
// reset the value with the default native value
if (nativeView instanceof android.widget.Button) {
let nativeButton = new android.widget.Button(nativeView.getContext());
if (getSDK() >= 16) {
nativeView.setBackground(nativeButton.getBackground());
} else {
nativeView.setBackgroundDrawable(nativeButton.getBackground());
}
org.nativescript.widgets.ViewHelper.setBackground(nativeView, nativeButton.getBackground());
}
else {
let viewClass = getClass(view);
if (_defaultBackgrounds.has(viewClass)) {
if (getSDK() >= 16) {
nativeView.setBackground(_defaultBackgrounds.get(viewClass));
} else {
nativeView.setBackgroundDrawable(_defaultBackgrounds.get(viewClass));
}
org.nativescript.widgets.ViewHelper.setBackground(nativeView, _defaultBackgrounds.get(viewClass));
}
}

View File

@@ -4,19 +4,31 @@
export * from "./switch-common";
@Interfaces([android.widget.CompoundButton.OnCheckedChangeListener])
class CheckedChangeListener extends java.lang.Object implements android.widget.CompoundButton.OnCheckedChangeListener {
constructor(private owner: WeakRef<Switch>) {
super();
return global.__native(this);
interface CheckedChangeListener {
new (owner: Switch): android.widget.CompoundButton.OnCheckedChangeListener;
}
let CheckedChangeListener: CheckedChangeListener;
function initializeCheckedChangeListener(): void {
if (CheckedChangeListener) {
return;
}
onCheckedChanged(buttonView: android.widget.CompoundButton, isChecked: boolean): void {
let owner = this.owner.get();
if (owner) {
@Interfaces([android.widget.CompoundButton.OnCheckedChangeListener])
class CheckedChangeListenerImpl extends java.lang.Object implements android.widget.CompoundButton.OnCheckedChangeListener {
constructor(private owner: Switch) {
super();
return global.__native(this);
}
onCheckedChanged(buttonView: android.widget.CompoundButton, isChecked: boolean): void {
const owner = this.owner;
checkedProperty.nativeValueChange(owner, isChecked);
}
}
CheckedChangeListener = CheckedChangeListenerImpl;
}
export class Switch extends SwitchBase {
@@ -29,8 +41,9 @@ export class Switch extends SwitchBase {
}
public _createNativeView() {
initializeCheckedChangeListener();
this._android = new android.widget.Switch(this._context);
this.listener = this.listener || new CheckedChangeListener(new WeakRef(this));
this.listener = this.listener || new CheckedChangeListener(this);
this._android.setOnCheckedChangeListener(this.listener);
}

View File

@@ -16,70 +16,23 @@ const ACCENT_COLOR = "colorAccent";
const PRIMARY_COLOR = "colorPrimary";
const DEFAULT_ELEVATION = 4;
let defaultAccentColor: number = undefined;
function getDefaultAccentColor(context: android.content.Context): number {
if (defaultAccentColor === undefined) {
//Fallback color: https://developer.android.com/samples/SlidingTabsColors/src/com.example.android.common/view/SlidingTabStrip.html
defaultAccentColor = ad.resources.getPalleteColor(ACCENT_COLOR, context) || 0xFF33B5E5;
}
return defaultAccentColor;
interface PagerAdapter {
new (owner: TabView, items: Array<TabViewItem>): android.support.v4.view.PagerAdapter;
}
export class TabViewItem extends TabViewItemBase {
public nativeView: android.widget.TextView;
public tabItemSpec: org.nativescript.widgets.TabItemSpec;
public index: number;
public setNativeView(textView: android.widget.TextView): void {
this.nativeView = textView;
if (textView) {
initNativeView(this);
}
}
public _update(): void {
const tv = this.nativeView;
if (tv) {
const tabLayout = <org.nativescript.widgets.TabLayout>tv.getParent();
tabLayout.updateItemAt(this.index, this.tabItemSpec);
}
}
get [fontSizeProperty.native](): { nativeSize: number } {
return { nativeSize: this.nativeView.getTextSize() };
}
set [fontSizeProperty.native](value: number | { nativeSize: number }) {
if (typeof value === "number") {
this.nativeView.setTextSize(value);
} else {
this.nativeView.setTextSize(android.util.TypedValue.COMPLEX_UNIT_PX, value.nativeSize);
}
}
get [fontInternalProperty.native](): android.graphics.Typeface {
return this.nativeView.getTypeface();
}
set [fontInternalProperty.native](value: Font | android.graphics.Typeface) {
this.nativeView.setTypeface(value instanceof Font ? value.getAndroidTypeface() : value);
}
get [textTransformProperty.native](): TextTransform {
return "none";
}
set [textTransformProperty.native](value: TextTransform) {
const tv = this.nativeView;
const result = getTransformedText(this.title, value);
tv.setText(result);
}
interface PageChangedListener {
new (owner: TabView): android.support.v4.view.ViewPager.SimpleOnPageChangeListener;
}
let PagerAdapterClass;
function ensurePagerAdapterClass() {
if (PagerAdapterClass) {
let PagerAdapter: PagerAdapter;
let PageChangedListener: PageChangedListener;
function initializeNativeClasses() {
if (PagerAdapter) {
return;
}
class PagerAdapterClassInner extends android.support.v4.view.PagerAdapter {
class PagerAdapterImpl extends android.support.v4.view.PagerAdapter {
private owner: TabView;
private items: Array<TabViewItem>;
@@ -160,8 +113,8 @@ function ensurePagerAdapterClass() {
traceWrite("TabView.PagerAdapter.saveState", traceCategory);
}
let owner: TabView = this.owner;
if (!owner || owner._childrenCount === 0) {
const owner: TabView = this.owner;
if (owner._childrenCount === 0) {
return null;
}
@@ -194,16 +147,7 @@ function ensurePagerAdapterClass() {
}
};
PagerAdapterClass = PagerAdapterClassInner;
}
let PageChangedListenerClass;
function ensurePageChangedListenerClass() {
if (PageChangedListenerClass) {
return;
}
class PageChangedListener extends android.support.v4.view.ViewPager.SimpleOnPageChangeListener {
class PageChangedListenerImpl extends android.support.v4.view.ViewPager.SimpleOnPageChangeListener {
private _owner: TabView;
constructor(owner: TabView) {
super();
@@ -216,7 +160,8 @@ function ensurePageChangedListenerClass() {
}
}
PageChangedListenerClass = PageChangedListener;
PagerAdapter = PagerAdapterImpl;
PageChangedListener = PageChangedListenerImpl;
}
function createTabItemSpec(item: TabViewItem): org.nativescript.widgets.TabItemSpec {
@@ -238,6 +183,63 @@ function createTabItemSpec(item: TabViewItem): org.nativescript.widgets.TabItemS
return result;
}
let defaultAccentColor: number = undefined;
function getDefaultAccentColor(context: android.content.Context): number {
if (defaultAccentColor === undefined) {
//Fallback color: https://developer.android.com/samples/SlidingTabsColors/src/com.example.android.common/view/SlidingTabStrip.html
defaultAccentColor = ad.resources.getPalleteColor(ACCENT_COLOR, context) || 0xFF33B5E5;
}
return defaultAccentColor;
}
export class TabViewItem extends TabViewItemBase {
public nativeView: android.widget.TextView;
public tabItemSpec: org.nativescript.widgets.TabItemSpec;
public index: number;
public setNativeView(textView: android.widget.TextView): void {
this.nativeView = textView;
if (textView) {
initNativeView(this);
}
}
public _update(): void {
const tv = this.nativeView;
if (tv) {
const tabLayout = <org.nativescript.widgets.TabLayout>tv.getParent();
tabLayout.updateItemAt(this.index, this.tabItemSpec);
}
}
get [fontSizeProperty.native](): { nativeSize: number } {
return { nativeSize: this.nativeView.getTextSize() };
}
set [fontSizeProperty.native](value: number | { nativeSize: number }) {
if (typeof value === "number") {
this.nativeView.setTextSize(value);
} else {
this.nativeView.setTextSize(android.util.TypedValue.COMPLEX_UNIT_PX, value.nativeSize);
}
}
get [fontInternalProperty.native](): android.graphics.Typeface {
return this.nativeView.getTypeface();
}
set [fontInternalProperty.native](value: Font | android.graphics.Typeface) {
this.nativeView.setTypeface(value instanceof Font ? value.getAndroidTypeface() : value);
}
get [textTransformProperty.native](): TextTransform {
return "none";
}
set [textTransformProperty.native](value: TextTransform) {
const tv = this.nativeView;
const result = getTransformedText(this.title, value);
tv.setText(result);
}
}
export class TabView extends TabViewBase {
private _grid: org.nativescript.widgets.GridLayout;
private _tabLayout: org.nativescript.widgets.TabLayout;
@@ -264,6 +266,7 @@ export class TabView extends TabViewBase {
}
public _createNativeView() {
initializeNativeClasses();
if (traceEnabled()) {
traceWrite("TabView._createUI(" + this + ");", traceCategory);
}
@@ -298,8 +301,7 @@ export class TabView extends TabViewBase {
this._viewPager.setLayoutParams(lp);
this._grid.addView(this._viewPager);
ensurePageChangedListenerClass();
this._pageChagedListener = new PageChangedListenerClass(this);
this._pageChagedListener = new PageChangedListener(this);
(<any>this._viewPager).addOnPageChangeListener(this._pageChagedListener);
this.nativeView = this._viewPager;
this._nativeView = this._viewPager;
@@ -331,9 +333,8 @@ export class TabView extends TabViewBase {
tabItems.push(tabItemSpec);
});
ensurePagerAdapterClass();
// TODO: optimize by reusing the adapter and calling setAdapter(null) then the same adapter.
this._pagerAdapter = new PagerAdapterClass(this, items);
this._pagerAdapter = new PagerAdapter(this, items);
this._viewPager.setAdapter(this._pagerAdapter);
const tabLayout = this._tabLayout;

View File

@@ -331,8 +331,7 @@ function setSpanModifiers(ssb: android.text.SpannableStringBuilder, span: Span,
const fontFamily = span.fontFamily;
if (fontFamily) {
const font = new Font(fontFamily, 0, (italic) ? "italic" : "normal", (bold) ? "bold" : "normal");
ensureCustomTypefaceSpanClass();
const typefaceSpan: android.text.style.TypefaceSpan = new CustomTypefaceSpanClass(fontFamily, font.getAndroidTypeface());
const typefaceSpan: android.text.style.TypefaceSpan = new org.nativescript.widgets.CustomTypefaceSpan(fontFamily, font.getAndroidTypeface());
ssb.setSpan(typefaceSpan, start, end, android.text.Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
@@ -375,49 +374,4 @@ function setSpanModifiers(ssb: android.text.SpannableStringBuilder, span: Span,
ssb.setSpan(new android.text.style.StrikethroughSpan(), start, end, android.text.Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
}
}
var CustomTypefaceSpanClass;
function ensureCustomTypefaceSpanClass() {
if (CustomTypefaceSpanClass) {
return;
}
// TODO: Move this class in widgets.
class CustomTypefaceSpan extends android.text.style.TypefaceSpan {
private typeface: android.graphics.Typeface;
constructor(family: string, typeface: android.graphics.Typeface) {
super(family);
this.typeface = typeface;
return global.__native(this);
}
public updateDrawState(ds: android.text.TextPaint): void {
this.applyCustomTypeFace(ds);
}
public updateMeasureState(paint: android.text.TextPaint): void {
this.applyCustomTypeFace(paint);
}
private applyCustomTypeFace(paint: android.text.TextPaint) {
const old = paint.getTypeface();
const oldStyle = old === null ? 0 : old.getStyle();
const typeface = this.typeface;
let fake = oldStyle & ~typeface.getStyle();
if ((fake & android.graphics.Typeface.BOLD) !== 0) {
paint.setFakeBoldText(true);
}
if ((fake & android.graphics.Typeface.ITALIC) !== 0) {
paint.setTextSkewX(-0.25);
}
paint.setTypeface(typeface);
}
}
CustomTypefaceSpanClass = CustomTypefaceSpan;
}

View File

@@ -2,21 +2,33 @@
export * from "./time-picker-common";
@Interfaces([android.widget.TimePicker.OnTimeChangedListener])
class TimeChangedListener extends java.lang.Object implements android.widget.TimePicker.OnTimeChangedListener {
constructor(public owner: WeakRef<TimePicker>) {
super();
return global.__native(this);
interface TimeChangedListener {
new (owner: TimePicker): android.widget.TimePicker.OnTimeChangedListener;
}
let TimeChangedListener: TimeChangedListener;
function initializeTimeChangedListener(): void {
if (TimeChangedListener) {
return;
}
onTimeChanged(picker: android.widget.TimePicker, hour: number, minute: number): void {
let timePicker = this.owner.get();
if (timePicker) {
@Interfaces([android.widget.TimePicker.OnTimeChangedListener])
class TimeChangedListenerImpl extends java.lang.Object implements android.widget.TimePicker.OnTimeChangedListener {
constructor(public owner: TimePicker) {
super();
return global.__native(this);
}
onTimeChanged(picker: android.widget.TimePicker, hour: number, minute: number): void {
const timePicker = this.owner;
let validTime = getValidTime(timePicker, hour, minute);
timePicker._setNativeValueSilently(validTime.hour, validTime.minute);
timeProperty.nativeValueChange(timePicker, new Date(0, 0, 0, validTime.hour, validTime.minute));
}
}
TimeChangedListener = TimeChangedListenerImpl;
}
export class TimePicker extends TimePickerBase {
@@ -24,8 +36,9 @@ export class TimePicker extends TimePickerBase {
private _listener: android.widget.TimePicker.OnTimeChangedListener;
public _createNativeView() {
initializeTimeChangedListener();
this._android = new android.widget.TimePicker(this._context);
this._listener = this._listener || new TimeChangedListener(new WeakRef(this));
this._listener = this._listener || new TimeChangedListener(this);
this._android.setOnTimeChangedListener(this._listener);
let c = java.util.Calendar.getInstance();

View File

@@ -2,7 +2,7 @@
export class FadeTransition extends Transition {
public createAndroidAnimator(transitionType: string): android.animation.Animator {
let alphaValues = Array.create("float", 2);
const alphaValues = Array.create("float", 2);
switch (transitionType) {
case AndroidTransitionType.enter:
case AndroidTransitionType.popEnter:
@@ -15,11 +15,13 @@ export class FadeTransition extends Transition {
alphaValues[1] = 0;
break;
}
let animator = android.animation.ObjectAnimator.ofFloat(null, "alpha", alphaValues);
let duration = this.getDuration();
const animator = android.animation.ObjectAnimator.ofFloat(null, "alpha", alphaValues);
const duration = this.getDuration();
if (duration !== undefined) {
animator.setDuration(duration);
}
animator.setInterpolator(this.getCurve());
return animator;
}

View File

@@ -13,10 +13,10 @@ export class FlipTransition extends Transition {
let objectAnimators;
let values;
let animator: android.animation.ObjectAnimator;
let animatorSet = new android.animation.AnimatorSet();
let fullDuration = this.getDuration() || 300;
let interpolator = this.getCurve();
let rotationY = this._direction === "right" ? 180 : -180;
const animatorSet = new android.animation.AnimatorSet();
const fullDuration = this.getDuration() || 300;
const interpolator = this.getCurve();
const rotationY = this._direction === "right" ? 180 : -180;
switch (transitionType) {
case AndroidTransitionType.enter: // card_flip_right_in

View File

@@ -2,8 +2,8 @@
import * as platform from "platform";
import lazy from "utils/lazy";
let screenWidth = lazy(() => platform.screen.mainScreen.widthPixels);
let screenHeight = lazy(() => platform.screen.mainScreen.heightPixels);
const screenWidth = lazy(() => platform.screen.mainScreen.widthPixels);
const screenHeight = lazy(() => platform.screen.mainScreen.heightPixels);
export class SlideTransition extends transition.Transition {
private _direction: string;
@@ -14,7 +14,7 @@ export class SlideTransition extends transition.Transition {
}
public createAndroidAnimator(transitionType: string): android.animation.Animator {
let translationValues = Array.create("float", 2);
const translationValues = Array.create("float", 2);
switch (this._direction) {
case "left":
switch (transitionType) {
@@ -105,8 +105,8 @@ export class SlideTransition extends transition.Transition {
prop = "translationY";
}
let animator = android.animation.ObjectAnimator.ofFloat(null, prop, translationValues);
let duration = this.getDuration();
const animator = android.animation.ObjectAnimator.ofFloat(null, prop, translationValues);
const duration = this.getDuration();
if (duration !== undefined) {
animator.setDuration(duration);
}

View File

@@ -45,10 +45,10 @@ interface ExpandedFragment {
isDestroyed: boolean;
}
let enterFakeResourceId = -10;
let exitFakeResourceId = -20;
let popEnterFakeResourceId = -30;
let popExitFakeResourceId = -40;
const enterFakeResourceId = -10;
const exitFakeResourceId = -20;
const popEnterFakeResourceId = -30;
const popExitFakeResourceId = -40;
export module AndroidTransitionType {
export const enter: string = "enter";

View File

@@ -2,13 +2,18 @@ import { WebViewBase, knownFolders, traceEnabled, traceWrite, traceCategories }
export * from "./web-view-common";
let WebViewClientClass;
function ensureWebViewClientClass() {
if (WebViewClientClass) {
interface WebViewClient {
new (owner: WebView): android.webkit.WebViewClient;
}
let WebViewClient: WebViewClient;
function initializeWebViewClient(): void {
if (WebViewClient) {
return;
}
class WebViewClientClassInner extends android.webkit.WebViewClient {
class WebViewClientImpl extends android.webkit.WebViewClient {
private _view: WebViewBase;
constructor(view: WebViewBase) {
@@ -79,25 +84,20 @@ function ensureWebViewClientClass() {
}
};
WebViewClientClass = WebViewClientClassInner;
WebViewClient = WebViewClientImpl;
}
export class WebView extends WebViewBase {
private _android: android.webkit.WebView;
private _webViewClient: android.webkit.WebViewClient;
constructor() {
super();
ensureWebViewClientClass();
this._webViewClient = new WebViewClientClass(this);
}
get android(): android.webkit.WebView {
return this._android;
}
public _createNativeView() {
initializeWebViewClient();
this._webViewClient = new WebViewClient(this);
this._android = new android.webkit.WebView(this._context);
this._android.getSettings().setJavaScriptEnabled(true);
this._android.getSettings().setBuiltInZoomControls(true);

View File

@@ -490,7 +490,19 @@
public static getLetterspacing(view: android.view.View): number;
public static setLetterspacing(view: android.view.View, value: number): void;
public static setBackground(view: android.view.View, background: android.graphics.drawable.Drawable): void;
}
export class DisableUserInteractionListener extends java.lang.Object implements android.view.View.OnTouchListener {
public onTouch(view: android.view.View, motionEvent: android.view.MotionEvent): boolean;
}
export class SegmentedBarColorDrawable extends android.graphics.drawable.ColorDrawable {
}
export class CustomTypefaceSpan extends android.text.style.TypefaceSpan {
constructor(family: string, typeface: android.graphics.Typeface);
}
}
}
}
}