diff --git a/tns-core-modules/ui/editable-text-base/editable-text-base-common.ts b/tns-core-modules/ui/editable-text-base/editable-text-base-common.ts index 0911ea533..c3e88975d 100644 --- a/tns-core-modules/ui/editable-text-base/editable-text-base-common.ts +++ b/tns-core-modules/ui/editable-text-base/editable-text-base-common.ts @@ -13,6 +13,7 @@ export abstract class EditableTextBase extends TextBase implements EditableTextB public editable: boolean; public autocorrect: boolean; public hint: string; + public maxLength: number; public abstract dismissSoftInput(); public abstract _setInputType(inputType: number): void; @@ -49,4 +50,7 @@ export const autocorrectProperty = new Property({ nam autocorrectProperty.register(EditableTextBase); export const hintProperty = new Property({ name: "hint", defaultValue: "" }); -hintProperty.register(EditableTextBase); \ No newline at end of file +hintProperty.register(EditableTextBase); + +export const maxLengthProperty = new Property({ name: "maxLength", defaultValue: Number.POSITIVE_INFINITY }); +maxLengthProperty.register(EditableTextBase); diff --git a/tns-core-modules/ui/editable-text-base/editable-text-base.android.ts b/tns-core-modules/ui/editable-text-base/editable-text-base.android.ts index d1f946d89..2be2ce13f 100644 --- a/tns-core-modules/ui/editable-text-base/editable-text-base.android.ts +++ b/tns-core-modules/ui/editable-text-base/editable-text-base.android.ts @@ -2,7 +2,7 @@ EditableTextBase as EditableTextBaseCommon, keyboardTypeProperty, returnKeyTypeProperty, editableProperty, autocapitalizationTypeProperty, autocorrectProperty, hintProperty, - textProperty, placeholderColorProperty, Color, textTransformProperty + textProperty, placeholderColorProperty, Color, textTransformProperty, maxLengthProperty } from "./editable-text-base-common"; import { ad } from "../../utils/utils"; @@ -429,4 +429,23 @@ export abstract class EditableTextBase extends EditableTextBaseCommon { [textTransformProperty.setNative](value: "default") { // } -} \ No newline at end of file + + [maxLengthProperty.setNative](value: number) { + let lengthFilter = new android.text.InputFilter.LengthFilter(+value); + let filters = this.nativeView.getFilters(); + let newFilters = []; + + // retain existing filters + for (let i = 0; i < filters.length; i++) { + newFilters.push(filters[i]); + // update an existing length filter + if (filters[i] instanceof android.text.InputFilter.LengthFilter) { + filters[i] = lengthFilter; + return; + } + } + // no current length filter found, so add it + newFilters.push(lengthFilter); + this.nativeView.setFilters(newFilters); + } +} diff --git a/tns-core-modules/ui/editable-text-base/editable-text-base.d.ts b/tns-core-modules/ui/editable-text-base/editable-text-base.d.ts index eaf6ad152..d4da01d11 100644 --- a/tns-core-modules/ui/editable-text-base/editable-text-base.d.ts +++ b/tns-core-modules/ui/editable-text-base/editable-text-base.d.ts @@ -45,6 +45,11 @@ export class EditableTextBase extends TextBase { */ hint: string; + /** + * Limits input to a certain number of characters. + */ + maxLength: number; + /** * Hides the soft input method, ususally a soft keyboard. */ @@ -71,6 +76,7 @@ export const autocapitalizationTypeProperty: Property; export const hintProperty: Property; export const placeholderColorProperty: CssProperty; +export const maxLengthProperty: Property; //@private /** diff --git a/tns-core-modules/ui/text-field/text-field.ios.ts b/tns-core-modules/ui/text-field/text-field.ios.ts index 76e24ac83..af274ecc2 100644 --- a/tns-core-modules/ui/text-field/text-field.ios.ts +++ b/tns-core-modules/ui/text-field/text-field.ios.ts @@ -1,5 +1,5 @@ import { - TextFieldBase, secureProperty, textProperty, hintProperty, colorProperty, placeholderColorProperty, + TextFieldBase, secureProperty, textProperty, hintProperty, colorProperty, placeholderColorProperty, Length, paddingTopProperty, paddingRightProperty, paddingBottomProperty, paddingLeftProperty, _updateCharactersInRangeReplacementString, Color, layout } from "./text-field-common"; @@ -67,6 +67,13 @@ class UITextFieldDelegateImpl extends NSObject implements UITextFieldDelegate { public textFieldShouldChangeCharactersInRangeReplacementString(textField: UITextField, range: NSRange, replacementString: string): boolean { const owner = this._owner.get(); if (owner) { + const delta = replacementString.length - range.length; + if (delta > 0) { + if (textField.text.length + delta > owner.maxLength) { + return false; + } + } + if (owner.updateTextTrigger === "textChanged") { if (textField.secureTextEntry && this.firstEdit) { textProperty.nativeValueChange(owner, replacementString); diff --git a/tns-core-modules/ui/text-view/text-view.ios.ts b/tns-core-modules/ui/text-view/text-view.ios.ts index 08a7c254f..6adf10f6f 100644 --- a/tns-core-modules/ui/text-view/text-view.ios.ts +++ b/tns-core-modules/ui/text-view/text-view.ios.ts @@ -59,8 +59,17 @@ class UITextViewDelegateImpl extends NSObject implements UITextViewDelegate { public textViewShouldChangeTextInRangeReplacementText(textView: UITextView, range: NSRange, replacementString: string): boolean { const owner = this._owner.get(); - if (owner && owner.formattedText) { - _updateCharactersInRangeReplacementString(owner.formattedText, range.location, range.length, replacementString); + if (owner) { + const delta = replacementString.length - range.length; + if (delta > 0) { + if (textView.text.length + delta > owner.maxLength) { + return false; + } + } + + if (owner.formattedText) { + _updateCharactersInRangeReplacementString(owner.formattedText, range.location, range.length, replacementString); + } } return true;