Skip to content

Commit 48ddf54

Browse files
authored
Implements #27 (#53)
1 parent f56260e commit 48ddf54

File tree

4 files changed

+157
-52
lines changed

4 files changed

+157
-52
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,3 +54,4 @@ node_modules
5454
*.tmp.*
5555
platforms
5656
sample/lib
57+
*.log

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ Represents the observable property backing the selectedIndex property of each Dr
4545
Represents the observable property backing the hint property of each DropDown instance.
4646

4747
### Instance Properties
48-
* **ios** - *[UITextField](https://developer.apple.com/library/prerelease/ios/documentation/UIKit/Reference/UITextField_Class/index.html)*
48+
* **ios** - *[UILabel](https://developer.apple.com/reference/uikit/uilabel)*
4949
Gets the native iOS view that represents the user interface for this component. Valid only when running on iOS.
5050

5151
* **android** - *[android.widget.Spinner](http://developer.android.com/reference/android/widget/Spinner.html)*

drop-down.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ declare module "nativescript-drop-down" {
3737
hint: string;
3838
accessoryViewVisible: boolean; /* iOS ONLY! */
3939

40-
ios: UITextField;
40+
ios: UILabel;
4141
android: android.widget.Spinner;
4242

4343
public on(eventNames: string, callback: (data: EventData) => void, thisArg?: any);

drop-down.ios.ts

Lines changed: 154 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
1414
limitations under the License.
1515
***************************************************************************** */
1616

17-
import { TextField } from "ui/text-field";
17+
import { Label } from "ui/label";
1818
import { ListPicker } from "ui/list-picker";
1919
import * as dependencyObservable from "ui/core/dependency-observable";
2020
import { Observable, PropertyChangeData } from "data/observable";
@@ -24,12 +24,15 @@ import * as utils from "utils/utils";
2424
import { Font } from "ui/styling/font";
2525
import { Span } from "text/span";
2626
import { FormattedString } from "text/formatted-string";
27+
import { Color } from "color";
2728
import * as enums from "ui/enums";
29+
import * as types from "utils/types";
2830
import { SelectedIndexChangedEventData } from "nativescript-drop-down";
2931

3032
global.moduleMerge(common, exports);
3133

3234
const TOOLBAR_HEIGHT = 44;
35+
const HINT_COLOR = new Color("#3904041E");
3336

3437
export class DropDown extends common.DropDown {
3538
private _toolbar: UIToolbar;
@@ -38,19 +41,18 @@ export class DropDown extends common.DropDown {
3841
private _doneTapDelegate: TapHandler;
3942
private _accessoryViewVisible: boolean;
4043

41-
public _textField: TextField;
44+
public _label: DropDownLabelWrapper;
4245
public _listPicker: ListPicker;
4346

4447
constructor() {
4548
super();
4649

4750
let applicationFrame = utils.ios.getter(UIScreen, UIScreen.mainScreen).applicationFrame;
4851

49-
this._textField = new TextField();
52+
this._label = new DropDownLabelWrapper(this);
5053
this._listPicker = new ListPicker();
5154

52-
(this._listPicker as any)._delegate = DropDownListPickerDelegateImpl.initWithOwner(this);
53-
(this._textField as any)._delegate = DropDownTextFieldDelegateImpl.initWithOwner(this);
55+
(this._listPicker as any)._delegate = DropDownListPickerDelegateImpl.initWithOwner(this);
5456
this._flexToolbarSpace = UIBarButtonItem.alloc().initWithBarButtonSystemItemTargetAction(UIBarButtonSystemItem.FlexibleSpace, null, null);
5557
this._doneTapDelegate = TapHandler.initWithOwner(new WeakRef(this));
5658
this._doneButton = UIBarButtonItem.alloc().initWithBarButtonSystemItemTargetAction(UIBarButtonSystemItem.Done, this._doneTapDelegate, "tap");
@@ -65,8 +67,8 @@ export class DropDown extends common.DropDown {
6567
this._toolbar.setItemsAnimated(nsArray, false);
6668
}
6769

68-
get ios(): UITextField {
69-
return this._textField.ios;
70+
get ios(): UILabel {
71+
return this._label.ios;
7072
}
7173

7274
get accessoryViewVisible(): boolean {
@@ -84,7 +86,7 @@ export class DropDown extends common.DropDown {
8486
public onLoaded() {
8587
super.onLoaded();
8688

87-
this._textField.onLoaded();
89+
this._label.onLoaded();
8890
this._listPicker.onLoaded();
8991
this._listPicker.on(Observable.propertyChangeEvent,
9092
(data: PropertyChangeData) => {
@@ -103,28 +105,28 @@ export class DropDown extends common.DropDown {
103105

104106
this._listPicker.off(Observable.propertyChangeEvent);
105107

106-
this._textField.onUnloaded();
108+
this._label.onUnloaded();
107109
this._listPicker.onUnloaded();
108110

109111
super.onUnloaded();
110112
}
111113

112114
public open() {
113-
this._textField.focus();
115+
this._label.ios.becomeFirstResponder();
114116
}
115117

116118
public _onItemsPropertyChanged(data: dependencyObservable.PropertyChangeData) {
117119
this._listPicker.items = data.newValue;
118120
}
119121

120122
public _onHintPropertyChanged(data: dependencyObservable.PropertyChangeData) {
121-
this._textField.hint = data.newValue;
123+
this._label.hint = data.newValue;
122124
}
123125

124126
public _onSelectedIndexPropertyChanged(data: dependencyObservable.PropertyChangeData) {
125127
super._onSelectedIndexPropertyChanged(data);
126128
this._listPicker.selectedIndex = data.newValue;
127-
this._textField.text = (this.items && this.items.getItem ? this.items.getItem(data.newValue) : this.items[data.newValue]);
129+
this._label.text = (this.items && this.items.getItem ? this.items.getItem(data.newValue) : this.items[data.newValue]);
128130
}
129131
}
130132

@@ -147,27 +149,6 @@ class TapHandler extends NSObject {
147149
}
148150
}
149151

150-
class DropDownTextFieldDelegateImpl extends NSObject implements UITextFieldDelegate {
151-
public static ObjCProtocols = [UITextFieldDelegate];
152-
153-
private _owner: WeakRef<DropDown>;
154-
155-
public static initWithOwner(owner: DropDown): DropDownTextFieldDelegateImpl {
156-
let delegate = <DropDownTextFieldDelegateImpl>DropDownTextFieldDelegateImpl.new();
157-
delegate._owner = new WeakRef(owner);
158-
return delegate;
159-
}
160-
161-
public textFieldDidBeginEditing(textField: UITextField) {
162-
let owner = this._owner.get();
163-
164-
owner.notify({
165-
eventName: common.DropDown.openedEvent,
166-
object: owner
167-
});
168-
}
169-
}
170-
171152
class DropDownListPickerDelegateImpl extends NSObject implements UIPickerViewDelegate {
172153
public static ObjCProtocols = [UIPickerViewDelegate];
173154

@@ -221,6 +202,129 @@ class DropDownListPickerDelegateImpl extends NSObject implements UIPickerViewDel
221202
}
222203
}
223204

205+
class DropDownLabelWrapper extends Label {
206+
private _ios: UILabel;
207+
private _hint: string = "";
208+
private _hasText: boolean = true;
209+
private _internalColor: Color;
210+
211+
constructor(dropDown: DropDown) {
212+
super();
213+
214+
this._ios = DropDownLabel.initWithOwner(dropDown);
215+
this._ios.userInteractionEnabled = true;
216+
}
217+
218+
public onLoaded() {
219+
super.onLoaded();
220+
this.internalColor = this.color;
221+
}
222+
223+
get text(): string {
224+
return this._ios.text;
225+
}
226+
set text(value: string) {
227+
let actualText = value || this._hint || "";
228+
229+
this._hasText = !types.isNullOrUndefined(value);
230+
this._ios.text = (actualText === "" ? " " : actualText); // HACK: If empty use <space> so the label does not collapse
231+
232+
this._refreshColor();
233+
}
234+
235+
get hint(): string {
236+
return this._hint;
237+
}
238+
set hint(value: string) {
239+
this._hint = value;
240+
241+
if (!this._hasText) {
242+
this._ios.text = value;
243+
}
244+
}
245+
246+
get internalColor(): Color {
247+
return this._internalColor;
248+
}
249+
set internalColor(value: Color) {
250+
this._internalColor = value;
251+
this._refreshColor();
252+
}
253+
254+
private _refreshColor() {
255+
this.color = (this._hasText ? this._internalColor : HINT_COLOR);
256+
}
257+
}
258+
259+
class DropDownLabel extends TNSLabel {
260+
private _inputView: UIView;
261+
private _inputAccessoryView: UIView;
262+
private _isInputViewOpened: boolean;
263+
private _owner: WeakRef<DropDown>;
264+
265+
public static initWithOwner(owner: DropDown): DropDownLabel {
266+
let label = <DropDownLabel>DropDownLabel.new();
267+
label._owner = new WeakRef(owner);
268+
label._isInputViewOpened = false;
269+
return label;
270+
}
271+
272+
get inputView(): UIView {
273+
return this._inputView;
274+
}
275+
set inputView(value: UIView) {
276+
this._inputView = value;
277+
}
278+
279+
get inputAccessoryView(): UIView {
280+
return this._inputAccessoryView;
281+
}
282+
set inputAccessoryView(value: UIView) {
283+
this._inputAccessoryView = value;
284+
}
285+
286+
get canBecomeFirstResponder(): boolean {
287+
return true;
288+
}
289+
290+
get canResignFirstResponder(): boolean {
291+
return true;
292+
}
293+
294+
public becomeFirstResponder(): boolean {
295+
let result = super.becomeFirstResponder();
296+
297+
if (result) {
298+
if (!this._isInputViewOpened) {
299+
let owner = this._owner.get();
300+
301+
owner.notify({
302+
eventName: common.DropDown.openedEvent,
303+
object: owner
304+
});
305+
}
306+
307+
this._isInputViewOpened = true;
308+
}
309+
310+
return result;
311+
}
312+
313+
public resignFirstResponder(): boolean {
314+
let result = super.resignFirstResponder();
315+
316+
if (result) {
317+
this._isInputViewOpened = false;
318+
}
319+
320+
return result;
321+
}
322+
323+
public touchesEndedWithEvent(touches: NSSet<UITouch>, event: UIEvent) {
324+
this.becomeFirstResponder();
325+
}
326+
}
327+
224328
//#region Styling
225329
export class DropDownStyler implements style.Styler {
226330
//#region Font
@@ -258,36 +362,36 @@ export class DropDownStyler implements style.Styler {
258362

259363
//#region Text Decoration
260364
private static setTextDecorationProperty(dropDown: DropDown, newValue: any) {
261-
dropDown._textField.style.textDecoration = newValue;
262-
(<any>dropDown._textField.style)._updateTextDecoration();
365+
dropDown._label.style.textDecoration = newValue;
366+
(<any>dropDown._label.style)._updateTextDecoration();
263367
}
264368

265369
private static resetTextDecorationProperty(dropDown: DropDown, nativeValue: any) {
266-
dropDown._textField.style.textDecoration = enums.TextDecoration.none;
267-
dropDown._textField.style._updateTextDecoration();
370+
dropDown._label.style.textDecoration = enums.TextDecoration.none;
371+
dropDown._label.style._updateTextDecoration();
268372
}
269373
//#endregion
270374

271375
//#region Color
272376
private static setColorProperty(dropDown: DropDown, newValue: any) {
273-
let ios = dropDown.ios;
274-
let pickerView = <UIPickerView>dropDown._listPicker.ios;
377+
let dropDownLabel = dropDown._label,
378+
pickerView = <UIPickerView>dropDown._listPicker.ios;
275379

276-
ios.textColor = newValue;
380+
dropDownLabel.internalColor = utils.ios.getColor(newValue);
277381
pickerView.reloadAllComponents();
278382
}
279383

280384
private static resetColorProperty(dropDown: DropDown, nativeValue: any) {
281-
let ios = dropDown.ios;
282-
let pickerView = <UIPickerView>dropDown._listPicker.ios;
385+
let dropDownLabel = dropDown._label,
386+
pickerView = <UIPickerView>dropDown._listPicker.ios;
283387

284-
ios.textColor = nativeValue;
388+
dropDownLabel.internalColor = utils.ios.getColor(nativeValue);
285389
pickerView.reloadAllComponents();
286390
}
287391

288392
private static getNativeColorValue(dropDown: DropDown): any {
289-
let ios = dropDown.ios;
290-
return ios.textColor;
393+
let dropDownLabel = dropDown._label;
394+
return dropDownLabel.internalColor ? dropDownLabel.internalColor.ios : dropDownLabel.ios.textColor;
291395
}
292396
//#endregion
293397

@@ -332,13 +436,13 @@ export class DropDownStyler implements style.Styler {
332436
}
333437

334438
private static setPadding(dropDown: DropDown, newValue: UIEdgeInsets) {
335-
dropDown._textField.style.paddingTop = newValue.top;
336-
dropDown._textField.style.paddingRight = newValue.right;
337-
dropDown._textField.style.paddingBottom = newValue.bottom;
338-
dropDown._textField.style.paddingLeft = newValue.left;
439+
dropDown._label.style.paddingTop = newValue.top;
440+
dropDown._label.style.paddingRight = newValue.right;
441+
dropDown._label.style.paddingBottom = newValue.bottom;
442+
dropDown._label.style.paddingLeft = newValue.left;
339443
}
340444
//#endregion
341-
445+
342446
public static registerHandlers() {
343447
style.registerHandler(style.fontInternalProperty,
344448
new style.StylePropertyChangedHandler(

0 commit comments

Comments
 (0)