Files
NativeScript/nativescript-core/ui/list-picker/list-picker.android.ts
Alexander Vakrilov cc97a16800 feat: Scoped Packages (#7911)
* chore: move tns-core-modules to nativescript-core

* chore: preparing compat generate script

* chore: add missing definitions

* chore: no need for http-request to be private

* chore: packages chore

* test: generate tests for tns-core-modules

* chore: add anroid module for consistency

* chore: add .npmignore

* chore: added privateModulesWhitelist

* chore(webpack): added bundle-entry-points

* chore: scripts

* chore: tests changed to use @ns/core

* test: add scoped-packages test project

* test: fix types

* test: update test project

* chore: build scripts

* chore: update build script

* chore: npm scripts cleanup

* chore: make the compat pgk work with old wp config

* test: generate diff friendly tests

* chore: create barrel exports

* chore: move files after rebase

* chore: typedoc config

* chore: compat mode

* chore: review of barrels

* chore: remove tns-core-modules import after rebase

* chore: dev workflow setup

* chore: update developer-workflow

* docs: experiment with API extractor

* chore: api-extractor and barrel exports

* chore: api-extractor configs

* chore: generate d.ts rollup with api-extractor

* refactor: move methods inside Frame

* chore: fic tests to use Frame static methods

* refactor: create Builder class

* refactor: use Builder class in tests

* refactor: include Style in ui barrel

* chore: separate compat build script

* chore: fix tslint errors

* chore: update NATIVESCRIPT_CORE_ARGS

* chore: fix compat pack

* chore: fix ui-test-app build with linked modules

* chore: Application, ApplicationSettings, Connectivity and Http

* chore: export Trace, Profiling and Utils

* refactor: Static create methods for ImageSource

* chore: fix deprecated usages of ImageSource

* chore: move Span and FormattedString to ui

* chore: add events-args and ImageSource to index files

* chore: check for CLI >= 6.2 when building for IOS

* chore: update travis build

* chore: copy Pod file to compat package

* chore: update error msg ui-tests-app

* refactor: Apply suggestions from code review

Co-Authored-By: Martin Yankov <m.i.yankov@gmail.com>

* chore: typings and refs

* chore: add missing d.ts files for public API

* chore: adress code review FB

* chore: update api-report

* chore: dev-workflow for other apps

* chore: api update

* chore: update api-report
2019-10-17 00:45:33 +03:00

197 lines
7.1 KiB
TypeScript

import { ListPickerBase, selectedIndexProperty, itemsProperty, colorProperty, Color } from "./list-picker-common";
import { ItemsSource } from ".";
import { device } from "../../platform";
import lazy from "../../utils/lazy";
export * from "./list-picker-common";
const sdkVersion = lazy(() => parseInt(device.sdkVersion));
interface Formatter {
new(owner: ListPicker): android.widget.NumberPicker.Formatter;
}
interface ValueChangeListener {
new(owner: ListPicker): android.widget.NumberPicker.OnValueChangeListener;
}
let Formatter: Formatter;
let ValueChangeListener: ValueChangeListener;
function initializeNativeClasses(): void {
if (Formatter) {
return;
}
@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);
this.owner.updateSelectedValue(newValue);
}
}
Formatter = FormatterImpl;
ValueChangeListener = ValueChangeListenerImpl;
}
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 {
nativeViewProtected: android.widget.NumberPicker;
private _selectorWheelPaint: android.graphics.Paint;
public createNativeView() {
const picker = new android.widget.NumberPicker(this._context);
picker.setDescendantFocusability(android.widget.NumberPicker.FOCUS_BLOCK_DESCENDANTS);
picker.setMinValue(0);
picker.setMaxValue(0);
picker.setValue(0);
picker.setWrapSelectorWheel(false);
return picker;
}
public initNativeView(): void {
super.initNativeView();
initializeNativeClasses();
const nativeView = this.nativeViewProtected;
// api28 and lower uses reflection to retrieve and manipulate
// android.graphics.Paint object; this is no longer allowed on newer api levels but
// equivalent public methods are exposed on api29+ directly on the native widget
if (sdkVersion() < 29) {
this._selectorWheelPaint = getSelectorWheelPaint(nativeView);
}
const formatter = new Formatter(this);
nativeView.setFormatter(formatter);
(<any>nativeView).formatter = formatter;
const valueChangedListener = new ValueChangeListener(this);
nativeView.setOnValueChangedListener(valueChangedListener);
(<any>nativeView).valueChangedListener = valueChangedListener;
const editText = getEditText(nativeView);
if (editText) {
(<any>nativeView).editText = editText;
//Fix the disappearing selected item.
//HACK: http://stackoverflow.com/questions/17708325/android-numberpicker-with-formatter-does-not-format-on-first-rendering/26797732
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.
editText.setText(" ", android.widget.TextView.BufferType.NORMAL);
}
}
public disposeNativeView() {
const nativeView = this.nativeViewProtected;
(<any>nativeView).formatter.owner = null;
(<any>nativeView).valueChangedListener.owner = null;
super.disposeNativeView();
}
private _fixNumberPickerRendering() {
const nativeView = this.nativeViewProtected;
//HACK: Force the stubborn NumberPicker to render correctly when we have 0 or 1 items.
nativeView.setFormatter(null);
nativeView.setFormatter((<any>nativeView).formatter); //Force the NumberPicker to call our Formatter
const editText = (<any>nativeView).editText;
if (editText) {
editText.setFilters([]);
editText.invalidate(); //Force the EditText to redraw
}
nativeView.invalidate();
}
[selectedIndexProperty.getDefault](): number {
return -1;
}
[selectedIndexProperty.setNative](value: number) {
if (value >= 0) {
this.nativeViewProtected.setValue(value);
}
}
[itemsProperty.getDefault](): any[] {
return null;
}
[itemsProperty.setNative](value: any[] | ItemsSource) {
let maxValue = value && value.length > 0 ? value.length - 1 : 0;
this.nativeViewProtected.setMaxValue(maxValue);
this._fixNumberPickerRendering();
// Coerce selected index after we have set items to native view.
selectedIndexProperty.coerce(this);
}
[colorProperty.getDefault](): number {
// api28 and lower uses reflection to retrieve and manipulate
// android.graphics.Paint object; this is no longer allowed on newer api levels but
// equivalent public methods are exposed on api29+ directly on the native widget
if (this._selectorWheelPaint) {
return this._selectorWheelPaint.getColor();
}
return this.nativeView.getTextColor();
}
[colorProperty.setNative](value: number | Color) {
const color = value instanceof Color ? value.android : value;
// api28 and lower uses reflection to retrieve and manipulate
// android.graphics.Paint object; this is no longer allowed on newer api levels but
// equivalent public methods are exposed on api29+ directly on the native widget
if (this._selectorWheelPaint) {
this._selectorWheelPaint.setColor(color);
const editText = (<any>this.nativeViewProtected).editText;
if (editText) {
editText.setTextColor(color);
}
} else {
// api29 and higher native implementation sets
// both wheel color and input text color with single call
this.nativeView.setTextColor(color);
}
}
}