mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-08-16 20:11:24 +08:00
Merge pull request #1345 from NativeScript/text-transform-fix
text-transform and text-decoration with formattedText fixed
This commit is contained in:
@ -591,7 +591,7 @@ export var test_setting_button_textTransform_sets_native = function () {
|
||||
testView.text = initial;
|
||||
testView.style.textTransform = enums.TextTransform.capitalize;
|
||||
|
||||
executeTransformTest(testView, androidText, function (v) { return (<UIButton>v.ios).attributedTitleForState(UIControlState.UIControlStateNormal).string; });
|
||||
executeTransformTest(testView, androidText, function (v) { return (<UIButton>v.ios).titleForState(UIControlState.UIControlStateNormal); });
|
||||
}
|
||||
|
||||
export var test_setting_label_textTransform_and_textDecoration_sets_native = function () {
|
||||
|
27
apps/ui-tests-app/css/decoration-transform-formattedtext.xml
Normal file
27
apps/ui-tests-app/css/decoration-transform-formattedtext.xml
Normal file
@ -0,0 +1,27 @@
|
||||
<Page>
|
||||
<StackLayout>
|
||||
<Label text="textText" style="text-transform: uppercase; text-decoration: underline line-through;" />
|
||||
<Label style="text-transform: uppercase; text-decoration: underline line-through;">
|
||||
<Label.formattedText>
|
||||
<FormattedString>
|
||||
<FormattedString.spans>
|
||||
<Span text="text" fontAttributes="Bold" foregroundColor="#ff0000" />
|
||||
<Span text="Text" fontAttributes="Italic" foregroundColor="#00ff00" />
|
||||
</FormattedString.spans>
|
||||
</FormattedString>
|
||||
</Label.formattedText>
|
||||
</Label>
|
||||
|
||||
<Button text="textText" style="text-transform: uppercase; text-decoration: underline line-through;" />
|
||||
<Button style="text-transform: uppercase; text-decoration: underline line-through;">
|
||||
<Button.formattedText>
|
||||
<FormattedString>
|
||||
<FormattedString.spans>
|
||||
<Span text="text" fontAttributes="Bold" foregroundColor="#ff0000" />
|
||||
<Span text="Text" fontAttributes="Italic" foregroundColor="#00ff00" />
|
||||
</FormattedString.spans>
|
||||
</FormattedString>
|
||||
</Button.formattedText>
|
||||
</Button>
|
||||
</StackLayout>
|
||||
</Page>
|
@ -27,6 +27,28 @@
|
||||
<Button text="button Button" style="text-transform:lowercase" />
|
||||
<Button text="button Button" style="text-transform:uppercase; text-decoration:underline;" />
|
||||
|
||||
<Label style="text-transform: uppercase; text-decoration: underline line-through;">
|
||||
<Label.formattedText>
|
||||
<FormattedString>
|
||||
<FormattedString.spans>
|
||||
<Span text="text" fontAttributes="Bold" foregroundColor="#ff0000" />
|
||||
<Span text="Text" fontAttributes="Italic" foregroundColor="#00ff00" />
|
||||
</FormattedString.spans>
|
||||
</FormattedString>
|
||||
</Label.formattedText>
|
||||
</Label>
|
||||
|
||||
<Button style="text-transform: uppercase; text-decoration: underline line-through;">
|
||||
<Button.formattedText>
|
||||
<FormattedString>
|
||||
<FormattedString.spans>
|
||||
<Span text="text" fontAttributes="Bold" foregroundColor="#ff0000" />
|
||||
<Span text="Text" fontAttributes="Italic" foregroundColor="#00ff00" />
|
||||
</FormattedString.spans>
|
||||
</FormattedString>
|
||||
</Button.formattedText>
|
||||
</Button>
|
||||
|
||||
</StackLayout>
|
||||
</ScrollView>
|
||||
</Page>
|
@ -111,6 +111,7 @@ export class Button extends view.View implements definition.Button {
|
||||
// then the property defaults to a system value. Therefore, at a minimum, you should
|
||||
// set the value for the normal state.
|
||||
this.ios.setAttributedTitleForState(value._formattedText, UIControlState.UIControlStateNormal);
|
||||
this.style._updateTextDecoration();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -135,20 +135,20 @@ export class ButtonStyler implements style.Styler {
|
||||
|
||||
// text-decoration
|
||||
private static setTextDecorationProperty(view: view.View, newValue: any) {
|
||||
utils.ios.setTextDecoration((<UIButton>view.ios).titleLabel, newValue);
|
||||
utils.ios.setTextDecorationAndTransform(view, newValue, view.style.textTransform);
|
||||
}
|
||||
|
||||
private static resetTextDecorationProperty(view: view.View, nativeValue: any) {
|
||||
utils.ios.setTextDecoration((<UIButton>view.ios).titleLabel, enums.TextDecoration.none);
|
||||
utils.ios.setTextDecorationAndTransform(view, enums.TextDecoration.none, view.style.textTransform);
|
||||
}
|
||||
|
||||
// text-transform
|
||||
private static setTextTransformProperty(view: view.View, newValue: any) {
|
||||
utils.ios.setTextTransform(view.ios, newValue);
|
||||
utils.ios.setTextDecorationAndTransform(view, view.style.textDecoration, newValue);
|
||||
}
|
||||
|
||||
private static resetTextTransformProperty(view: view.View, nativeValue: any) {
|
||||
utils.ios.setTextTransform(view.ios, enums.TextTransform.none);
|
||||
utils.ios.setTextDecorationAndTransform(view, view.style.textDecoration, enums.TextTransform.none);
|
||||
}
|
||||
|
||||
// white-space
|
||||
|
@ -94,11 +94,11 @@ export class TextBaseStyler implements style.Styler {
|
||||
|
||||
// text-transform
|
||||
private static setTextTransformProperty(view: view.View, newValue: any) {
|
||||
utils.ad.setTextTransform(view._nativeView, newValue);
|
||||
utils.ad.setTextTransform(view, newValue);
|
||||
}
|
||||
|
||||
private static resetTextTransformProperty(view: view.View, nativeValue: any) {
|
||||
utils.ad.setTextTransform(view._nativeView, enums.TextTransform.none);
|
||||
utils.ad.setTextTransform(view, enums.TextTransform.none);
|
||||
}
|
||||
|
||||
// white-space
|
||||
|
@ -40,20 +40,20 @@ export class TextBaseStyler implements style.Styler {
|
||||
|
||||
// text-decoration
|
||||
private static setTextDecorationProperty(view: view.View, newValue: any) {
|
||||
utils.ios.setTextDecoration(view._nativeView, newValue);
|
||||
utils.ios.setTextDecorationAndTransform(view, newValue, view.style.textTransform);
|
||||
}
|
||||
|
||||
private static resetTextDecorationProperty(view: view.View, nativeValue: any) {
|
||||
utils.ios.setTextDecoration(view._nativeView, enums.TextDecoration.none);
|
||||
utils.ios.setTextDecorationAndTransform(view, enums.TextDecoration.none, view.style.textTransform);
|
||||
}
|
||||
|
||||
// text-transform
|
||||
private static setTextTransformProperty(view: view.View, newValue: any) {
|
||||
utils.ios.setTextTransform(view._nativeView, newValue);
|
||||
utils.ios.setTextDecorationAndTransform(view, view.style.textDecoration, newValue);
|
||||
}
|
||||
|
||||
private static resetTextTransformProperty(view: view.View, nativeValue: any) {
|
||||
utils.ios.setTextTransform(view._nativeView, enums.TextTransform.none);
|
||||
utils.ios.setTextDecorationAndTransform(view, view.style.textDecoration, enums.TextTransform.none);
|
||||
}
|
||||
|
||||
// white-space
|
||||
|
@ -77,38 +77,52 @@ export module ad {
|
||||
}
|
||||
}
|
||||
|
||||
export function setTextTransform(view: android.widget.TextView, value: string) {
|
||||
export function setTextTransform(v, value: string) {
|
||||
let view = v._nativeView;
|
||||
let str = view.getText() + "";
|
||||
let result = getTransformedString(value, view, str);
|
||||
|
||||
if (v.formattedText) {
|
||||
for (var i = 0; i < v.formattedText.spans.length; i++) {
|
||||
var span = v.formattedText.spans.getItem(i);
|
||||
span.text = getTransformedString(value, view, span.text);
|
||||
}
|
||||
} else {
|
||||
view.setText(result);
|
||||
}
|
||||
}
|
||||
|
||||
function getTransformedString(textTransform: string, view, stringToTransform: string): string {
|
||||
let result: string;
|
||||
|
||||
switch (value) {
|
||||
switch (textTransform) {
|
||||
case enums.TextTransform.none:
|
||||
default:
|
||||
result = view["originalString"] || str;
|
||||
result = view["originalString"] || stringToTransform;
|
||||
if (view["transformationMethod"]) {
|
||||
view.setTransformationMethod(view["transformationMethod"]);
|
||||
}
|
||||
break;
|
||||
case enums.TextTransform.uppercase:
|
||||
view.setTransformationMethod(null);
|
||||
result = str.toUpperCase();
|
||||
result = stringToTransform.toUpperCase();
|
||||
break;
|
||||
case enums.TextTransform.lowercase:
|
||||
view.setTransformationMethod(null);
|
||||
result = str.toLowerCase();
|
||||
result = stringToTransform.toLowerCase();
|
||||
break;
|
||||
case enums.TextTransform.capitalize:
|
||||
view.setTransformationMethod(null);
|
||||
result = getCapitalizedString(str);
|
||||
result = getCapitalizedString(stringToTransform);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!view["originalString"]) {
|
||||
view["originalString"] = str;
|
||||
view["originalString"] = stringToTransform;
|
||||
view["transformationMethod"] = view.getTransformationMethod();
|
||||
}
|
||||
|
||||
view.setText(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
function getCapitalizedString(str: string): string {
|
||||
|
4
utils/utils.d.ts
vendored
4
utils/utils.d.ts
vendored
@ -145,10 +145,8 @@
|
||||
* Module with ios specific utilities.
|
||||
*/
|
||||
module ios {
|
||||
|
||||
export function setTextDecorationAndTransform(view: any, decoration: string, transform: string);
|
||||
export function setWhiteSpace(view, value: string, parentView?: any);
|
||||
export function setTextTransform(view, value: string);
|
||||
export function setTextDecoration(view, value: string);
|
||||
export function setTextAlignment(view, value: string);
|
||||
|
||||
export interface TextUIView {
|
||||
|
@ -49,108 +49,102 @@ export module ios {
|
||||
}
|
||||
}
|
||||
|
||||
export function setTextDecoration(view: dts.ios.TextUIView, value: string) {
|
||||
var attributes: NSMutableDictionary = NSMutableDictionary.alloc().init();
|
||||
var values = (value + "").split(" ");
|
||||
export function setTextDecorationAndTransform(v: any, decoration: string, transform: string) {
|
||||
if (v.formattedText) {
|
||||
if (v.style.textDecoration.indexOf(enums.TextDecoration.none) === -1) {
|
||||
|
||||
if (values.indexOf(enums.TextDecoration.underline) !== -1) {
|
||||
attributes.setObjectForKey(NSUnderlineStyle.NSUnderlineStyleSingle, NSUnderlineStyleAttributeName);
|
||||
}
|
||||
if (v.style.textDecoration.indexOf(enums.TextDecoration.underline) !== -1) {
|
||||
(<any>v).formattedText.underline = NSUnderlineStyle.NSUnderlineStyleSingle;
|
||||
}
|
||||
|
||||
if (values.indexOf(enums.TextDecoration.lineThrough) !== -1) {
|
||||
attributes.setObjectForKey(NSUnderlineStyle.NSUnderlineStyleSingle, NSStrikethroughStyleAttributeName);
|
||||
}
|
||||
if (v.style.textDecoration.indexOf(enums.TextDecoration.lineThrough) !== -1) {
|
||||
(<any>v).formattedText.strikethrough = NSUnderlineStyle.NSUnderlineStyleSingle;
|
||||
}
|
||||
|
||||
if (values.indexOf(enums.TextDecoration.none) === -1) {
|
||||
setTextDecorationNative(view, view.text || view.attributedText, attributes);
|
||||
} else {
|
||||
(<any>v).formattedText.underline = NSUnderlineStyle.NSUnderlineStyleNone;
|
||||
}
|
||||
|
||||
for (let i = 0; i < v.formattedText.spans.length; i++) {
|
||||
let span = v.formattedText.spans.getItem(i);
|
||||
span.text = getTransformedText(v, span.text, transform);
|
||||
}
|
||||
} else {
|
||||
setTextDecorationNative(view, view.text || view.attributedText, NSMutableDictionary.alloc().init());
|
||||
let source = v.text;
|
||||
let attributes = new Array();
|
||||
let range = { location: 0, length: source.length };
|
||||
|
||||
var decorationValues = (decoration + "").split(" ");
|
||||
|
||||
if (decorationValues.indexOf(enums.TextDecoration.none) === -1) {
|
||||
let dict = new Map<string, number>();
|
||||
|
||||
if (decorationValues.indexOf(enums.TextDecoration.underline) !== -1) {
|
||||
dict.set(NSUnderlineStyleAttributeName, NSUnderlineStyle.NSUnderlineStyleSingle);
|
||||
}
|
||||
|
||||
if (decorationValues.indexOf(enums.TextDecoration.lineThrough) !== -1) {
|
||||
dict.set(NSStrikethroughStyleAttributeName, NSUnderlineStyle.NSUnderlineStyleSingle);
|
||||
}
|
||||
|
||||
attributes.push({ attrs: dict, range: NSValue.valueWithRange(range) });
|
||||
}
|
||||
|
||||
let view: dts.ios.TextUIView | UIButton = v._nativeView;
|
||||
|
||||
source = getTransformedText(v, source, transform);
|
||||
|
||||
if (attributes.length > 0) {
|
||||
let result = NSMutableAttributedString.alloc().initWithString(<string>source);
|
||||
for (let i = 0; i < attributes.length; i++) {
|
||||
result.setAttributesRange(attributes[i]["attrs"], attributes[i]["range"].rangeValue);
|
||||
}
|
||||
|
||||
if (view instanceof UIButton) {
|
||||
(<UIButton>view).setAttributedTitleForState(result, UIControlState.UIControlStateNormal);
|
||||
}
|
||||
else {
|
||||
(<dts.ios.TextUIView>view).attributedText = result;
|
||||
}
|
||||
} else {
|
||||
if (view instanceof UIButton) {
|
||||
(<UIButton>view).setTitleForState(<string>source, UIControlState.UIControlStateNormal);
|
||||
}
|
||||
else {
|
||||
(<dts.ios.TextUIView>view).text = <string>source;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function setTextTransform(view: dts.ios.TextUIView, value: string) {
|
||||
let str = getNSStringFromView(view);
|
||||
let result: string;
|
||||
function getTransformedText(view, source: string, transform: string): string {
|
||||
let result = source;
|
||||
|
||||
switch (value) {
|
||||
switch (transform) {
|
||||
case enums.TextTransform.none:
|
||||
default:
|
||||
result = view["originalString"] || str;
|
||||
result = view["originalString"] || NSStringFromNSAttributedString(source);
|
||||
break;
|
||||
case enums.TextTransform.uppercase:
|
||||
result = str.uppercaseString;
|
||||
result = NSStringFromNSAttributedString(source).uppercaseString;
|
||||
break;
|
||||
case enums.TextTransform.lowercase:
|
||||
result = str.lowercaseString;
|
||||
result = NSStringFromNSAttributedString(source).lowercaseString;
|
||||
break;
|
||||
case enums.TextTransform.capitalize:
|
||||
result = str.capitalizedString;
|
||||
result = NSStringFromNSAttributedString(source).capitalizedString;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!view["originalString"]) {
|
||||
view["originalString"] = str;
|
||||
}
|
||||
|
||||
let newStr = getAttributedStringFromView(view, result);
|
||||
|
||||
if (newStr) {
|
||||
setAttributedStringToView(view, newStr);
|
||||
} else {
|
||||
setStringToView(view, result);
|
||||
}
|
||||
}
|
||||
|
||||
function getNSStringFromView(view: any): NSString {
|
||||
let result: string;
|
||||
|
||||
if (view instanceof UIButton) {
|
||||
let attrTitle = (<UIButton>view).titleLabel.attributedText;
|
||||
result = attrTitle ? attrTitle.string : (<UIButton>view).titleLabel.text;
|
||||
}
|
||||
else {
|
||||
let attrText = (<UITextView>view).attributedText;
|
||||
result = attrText ? attrText.string : (<UITextView>view).text;
|
||||
}
|
||||
|
||||
return NSString.alloc().initWithString(result || "");
|
||||
}
|
||||
|
||||
function setStringToView(view: any, str: string) {
|
||||
if (view instanceof UIButton) {
|
||||
(<UIButton>view).setTitleForState(str, UIControlState.UIControlStateNormal);
|
||||
}
|
||||
else {
|
||||
(<dts.ios.TextUIView>view).text = str;
|
||||
}
|
||||
}
|
||||
|
||||
function getAttributedStringFromView(view: any, value: string): NSMutableAttributedString {
|
||||
let result: NSMutableAttributedString;
|
||||
|
||||
if (view instanceof UIButton) {
|
||||
let attrTitle = (<UIButton>view).titleLabel.attributedText;
|
||||
if (attrTitle) {
|
||||
result = NSMutableAttributedString.alloc().initWithAttributedString(attrTitle);
|
||||
}
|
||||
} else if (view.attributedText) {
|
||||
result = NSMutableAttributedString.alloc().initWithAttributedString(view.attributedText);
|
||||
}
|
||||
|
||||
if (result) {
|
||||
result.replaceCharactersInRangeWithString({ location: 0, length: result.length }, value);
|
||||
view["originalString"] = NSStringFromNSAttributedString(source);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function setAttributedStringToView(view: any, str: NSMutableAttributedString) {
|
||||
if (view instanceof UIButton) {
|
||||
(<UIButton>view).setAttributedTitleForState(str, UIControlState.UIControlStateNormal);
|
||||
}
|
||||
else {
|
||||
(<dts.ios.TextUIView>view).attributedText = str;
|
||||
}
|
||||
function NSStringFromNSAttributedString(source: NSAttributedString | string): NSString {
|
||||
return NSString.stringWithString(source instanceof NSAttributedString && source.string || <string>source);
|
||||
}
|
||||
|
||||
export function setWhiteSpace(view: dts.ios.TextUIView, value: string, parentView?: UIView) {
|
||||
@ -168,19 +162,6 @@ export module ios {
|
||||
}
|
||||
}
|
||||
|
||||
function setTextDecorationNative(view: dts.ios.TextUIView, value: string | NSAttributedString, attributes: NSMutableDictionary) {
|
||||
var attributedString: NSMutableAttributedString;
|
||||
|
||||
if (value instanceof NSAttributedString) {
|
||||
attributedString = NSMutableAttributedString.alloc().initWithAttributedString(value);
|
||||
attributedString.addAttributesRange(attributes, NSRangeFromString(attributedString.string));
|
||||
} else {
|
||||
var types: typeof typesModule = require("utils/types");
|
||||
|
||||
view.attributedText = NSAttributedString.alloc().initWithStringAttributes(types.isString(value) ? <string>value : "", attributes);
|
||||
}
|
||||
}
|
||||
|
||||
export module collections {
|
||||
export function jsArrayToNSArray(str: string[]): NSArray {
|
||||
return NSArray.arrayWithArray(<any>str);
|
||||
|
Reference in New Issue
Block a user