diff --git a/tns-core-modules/ui/core/properties.ts b/tns-core-modules/ui/core/properties.ts index 96ca18fb8..a1a2c8c93 100644 --- a/tns-core-modules/ui/core/properties.ts +++ b/tns-core-modules/ui/core/properties.ts @@ -108,8 +108,7 @@ export class Property implements PropertyDescriptor { }); } - let nativeObject = this.nativeView; - if (nativeObject) { + if (this.nativeView) { this[native] = unboxedValue; } @@ -215,8 +214,7 @@ export class CoercibleProperty implements PropertyDescrip }); } - let nativeObject = this.nativeView; - if (nativeObject) { + if (this.nativeView) { this[native] = unboxedValue; } diff --git a/tns-core-modules/ui/list-picker/list-picker-common.ts b/tns-core-modules/ui/list-picker/list-picker-common.ts index 177cd8547..7fff16b94 100644 --- a/tns-core-modules/ui/list-picker/list-picker-common.ts +++ b/tns-core-modules/ui/list-picker/list-picker-common.ts @@ -1,5 +1,5 @@ import { ListPicker as ListPickerDefinition, ItemsSource } from "ui/list-picker"; -import { View, Property } from "ui/core/view"; +import { View, Property, CoercibleProperty } from "ui/core/view"; export * from "ui/core/view"; @@ -7,30 +7,43 @@ export class ListPickerBase extends View implements ListPickerDefinition { public selectedIndex: number; public items: any[] | ItemsSource; + public isItemsSource: boolean; public _getItemAsString(index: number): any { - if (!this.items) { + let items = this.items; + if (!items) { return " "; } - let getItem = (this.items).getItem; - let item = typeof getItem === "function" ? getItem(index) : this.items[index]; - return item === undefined || item === null ? index + "" : item + ""; - } - - protected getSelectedIndex(items: any[] | ItemsSource): number { - let maxValue = items && items.length > 0 ? items.length - 1 : 0; - let selectedIndex = this.selectedIndex; - if (selectedIndex < 0 || selectedIndex > maxValue) { - selectedIndex = 0; - } - - return selectedIndex; + let item = this.isItemsSource ? (this.items).getItem(index) : this.items[index]; + return (item === undefined || item === null) ? index + "" : item + ""; } } -export const selectedIndexProperty = new Property({ name: "selectedIndex", defaultValue: -1, valueConverter: (v) => parseInt(v) }); +export const selectedIndexProperty = new CoercibleProperty({ + name: "selectedIndex", defaultValue: -1, + valueConverter: (v) => parseInt(v), + coerceValue: (target, value) => { + let items = target.items; + if (items) { + let max = items.length - 1; + if (value > max) { + value = max; + } + } else { + value = -1; + } + + return value; + } +}); selectedIndexProperty.register(ListPickerBase); -export const itemsProperty = new Property({ name: "items" }); +export const itemsProperty = new Property({ + name: "items", valueChanged: (target, oldValue, newValue) => { + let getItem = newValue && (newValue).getItem; + target.isItemsSource = typeof getItem === "function"; + selectedIndexProperty.coerce(target); + } +}); itemsProperty.register(ListPickerBase); \ No newline at end of file diff --git a/tns-core-modules/ui/list-picker/list-picker.android.ts b/tns-core-modules/ui/list-picker/list-picker.android.ts index 2ed5ac32d..db2c4ca35 100644 --- a/tns-core-modules/ui/list-picker/list-picker.android.ts +++ b/tns-core-modules/ui/list-picker/list-picker.android.ts @@ -1,4 +1,4 @@ -import { ListPickerBase, selectedIndexProperty, itemsProperty, colorProperty } from "./list-picker-common"; +import { ListPickerBase, selectedIndexProperty, itemsProperty, colorProperty, Color } from "./list-picker-common"; import { ItemsSource } from "ui/list-picker"; export * from "./list-picker-common"; @@ -33,19 +33,44 @@ class ValueChangeListener implements android.widget.NumberPicker.OnValueChangeLi } } +function getEditText(picker: android.widget.NumberPicker): android.widget.EditText { + for (let i = 0, count = picker.getChildCount(); i < count; i++) { + let child = picker.getChildAt(i); + if (child instanceof android.widget.EditText) { + return child; + } + } + + return null; +} + +let selectorWheelPaintField: java.lang.reflect.Field; +function getSelectorWheelPaint(picker: android.widget.NumberPicker): android.graphics.Paint { + if (!selectorWheelPaintField) { + selectorWheelPaintField = picker.getClass().getDeclaredField("mSelectorWheelPaint"); + selectorWheelPaintField.setAccessible(true); + } + + return selectorWheelPaintField.get(picker); +} + export class ListPicker extends ListPickerBase { private _android: android.widget.NumberPicker; private _valueChangedListener: android.widget.NumberPicker.OnValueChangeListener; private _formatter: android.widget.NumberPicker.Formatter; private _editText: android.widget.EditText; - private itemsSet: boolean; + private _selectorWheelPaint: android.graphics.Paint; get android(): android.widget.NumberPicker { return this._android; } + public _createUI() { this._android = new android.widget.NumberPicker(this._context); + this._editText = getEditText(this._android); + this._selectorWheelPaint = getSelectorWheelPaint(this._android); + this._android.setDescendantFocusability(android.widget.NumberPicker.FOCUS_BLOCK_DESCENDANTS); this._android.setMinValue(0); @@ -55,24 +80,21 @@ export class ListPicker extends ListPickerBase { let formatter = this._formatter || new Formatter(new WeakRef(this)); this._android.setFormatter(this._formatter); - let valueChangedListener = this._valueChangedListener || new ValueChangeListener(new WeakRef(this)); + this._valueChangedListener = this._valueChangedListener || new ValueChangeListener(new WeakRef(this)); this._android.setOnValueChangedListener(this._valueChangedListener); //Fix the disappearing selected item. //HACK: http://stackoverflow.com/questions/17708325/android-numberpicker-with-formatter-does-not-format-on-first-rendering/26797732 - var mInputTextField = java.lang.Class.forName("android.widget.NumberPicker").getDeclaredField("mInputText"); - mInputTextField.setAccessible(true); - this._editText = mInputTextField.get(this._android); this._editText.setFilters([]); //Since the Android NumberPicker has to always have at least one item, i.e. minValue=maxValue=value=0, we don't want this zero showing up when this.items is empty. this._editText.setText(" ", android.widget.TextView.BufferType.NORMAL); - this.android.setWrapSelectorWheel(false); + this._android.setWrapSelectorWheel(false); } private updateSelectedValue(): void { - let selectedIndex = this.getSelectedIndex(this.items); + let selectedIndex = this.selectedIndex; this.android.setValue(selectedIndex); } @@ -87,12 +109,12 @@ export class ListPicker extends ListPickerBase { private _fixNumberPickerRendering() { //HACK: Force the stubborn NumberPicker to render correctly when we have 0 or 1 items. - this.android.setFormatter(null); - this.android.setFormatter(this._formatter); //Force the NumberPicker to call our Formatter + this._android.setFormatter(null); + this._android.setFormatter(this._formatter); //Force the NumberPicker to call our Formatter if (this._editText) { this._editText.setFilters([]); + this._editText.invalidate(); //Force the EditText to redraw } - this._editText.invalidate(); //Force the EditText to redraw this.android.invalidate(); } @@ -122,7 +144,24 @@ export class ListPicker extends ListPickerBase { } } - get [colorProperty.native](): number { - return + get [colorProperty.native](): { wheelColor: number, textColor: number } { + return { + wheelColor: this._selectorWheelPaint.getColor(), + textColor: this._editText.getTextColors().getDefaultColor() + } + } + + set [colorProperty.native](value: { wheelColor: number, textColor: number } | Color) { + let color: number; + let wheelColor: number; + if (value instanceof Color) { + color = wheelColor = value.android; + } else { + color = value.textColor; + wheelColor = value.wheelColor; + } + + this._selectorWheelPaint.setColor(wheelColor); + this._editText.setTextColor(color); } } \ No newline at end of file diff --git a/tns-core-modules/ui/list-picker/list-picker.ios.ts b/tns-core-modules/ui/list-picker/list-picker.ios.ts index db8751f14..461fcc69c 100644 --- a/tns-core-modules/ui/list-picker/list-picker.ios.ts +++ b/tns-core-modules/ui/list-picker/list-picker.ios.ts @@ -7,7 +7,6 @@ export class ListPicker extends ListPickerBase { private _ios: UIPickerView; private _dataSource: ListPickerDataSource; private _delegate: ListPickerDelegateImpl; - private itemsSet: boolean; constructor() { super(); @@ -32,7 +31,7 @@ export class ListPicker extends ListPickerBase { } private updateSelectedValue(): void { - let selectedIndex = this.getSelectedIndex(this.items); + let selectedIndex = this.selectedIndex; if (selectedIndex >= 0) { this.ios.selectRowInComponentAnimated(selectedIndex, 0, false); } diff --git a/tns-core-modules/ui/tab-view/tab-view-common.ts b/tns-core-modules/ui/tab-view/tab-view-common.ts index 1106d7438..caf6c78ca 100644 --- a/tns-core-modules/ui/tab-view/tab-view-common.ts +++ b/tns-core-modules/ui/tab-view/tab-view-common.ts @@ -154,10 +154,12 @@ export const itemsProperty = new Property({ itemsProperty.register(TabViewBase); export const selectedIndexProperty = new CoercibleProperty({ - name: "selectedIndex", defaultValue: -1, affectsLayout: isIOS, valueChanged: (target, oldValue, newValue) => { + name: "selectedIndex", defaultValue: -1, affectsLayout: isIOS, + valueChanged: (target, oldValue, newValue) => { let args = { eventName: TabViewBase.selectedIndexChangedEvent, object: this, oldIndex: oldValue, newIndex: newValue }; target.notify(args); - }, coerceValue: (target, value) => { + }, + coerceValue: (target, value) => { let items = target.items; if (items) { let max = items.length - 1; @@ -169,7 +171,8 @@ export const selectedIndexProperty = new CoercibleProperty( } return value; - } + }, + valueConverter: (v) => parseInt(v) }); selectedIndexProperty.register(TabViewBase);