mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-08-14 18:12:09 +08:00
feat(css): support for text-overflow (#10369)
This commit is contained in:
@ -14,6 +14,17 @@
|
|||||||
<GridLayout marginTop="10" borderWidth="1" borderColor="#efefef" height="60" paddingLeft="5">
|
<GridLayout marginTop="10" borderWidth="1" borderColor="#efefef" height="60" paddingLeft="5">
|
||||||
<Label text="Test Label 3: should be aligned top" verticalAlignment="top" />
|
<Label text="Test Label 3: should be aligned top" verticalAlignment="top" />
|
||||||
</GridLayout>
|
</GridLayout>
|
||||||
|
<GridLayout marginTop="10" borderWidth="1" borderColor="#efefef" height="60" paddingLeft="5">
|
||||||
|
<Label text="Test Label text-overflow: ellipsis, this should be long sentence and clipped at very end." textOverflow="ellipsis" whiteSpace="nowrap" />
|
||||||
|
</GridLayout>
|
||||||
|
|
||||||
|
<GridLayout marginTop="10" borderWidth="1" borderColor="#efefef" height="60" paddingLeft="5">
|
||||||
|
<Button text="Test Button text-overflow: ellipsis, this should be long sentence and clipped at very end." textOverflow="ellipsis" whiteSpace="nowrap" />
|
||||||
|
</GridLayout>
|
||||||
|
|
||||||
|
<GridLayout marginTop="10" borderWidth="1" borderColor="#efefef" height="60" paddingLeft="5">
|
||||||
|
<Button text="Test Button text-overflow: initial, this should be long sentence and truncated in the middle with ellipsis." textOverflow="initial" whiteSpace="nowrap" />
|
||||||
|
</GridLayout>
|
||||||
<Label text="maxLines 2" fontWeight="bold" marginTop="10" />
|
<Label text="maxLines 2" fontWeight="bold" marginTop="10" />
|
||||||
<Label
|
<Label
|
||||||
text="Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum."
|
text="Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum."
|
||||||
|
@ -94,6 +94,14 @@ export namespace CoreTypes {
|
|||||||
export const nowrap = 'nowrap';
|
export const nowrap = 'nowrap';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type TextOverflowType = 'clip' | 'ellipsis' | 'initial' | 'unset';
|
||||||
|
export namespace TextOverflow {
|
||||||
|
export const clip = 'clip';
|
||||||
|
export const ellipsis = 'ellipsis';
|
||||||
|
export const initial = 'initial';
|
||||||
|
export const unset = 'unset';
|
||||||
|
}
|
||||||
|
|
||||||
export type MaxLinesType = number;
|
export type MaxLinesType = number;
|
||||||
|
|
||||||
export type OrientationType = 'horizontal' | 'vertical';
|
export type OrientationType = 'horizontal' | 'vertical';
|
||||||
|
@ -2,7 +2,7 @@ import { ControlStateChangeListener } from '../core/control-state-change';
|
|||||||
import { ButtonBase } from './button-common';
|
import { ButtonBase } from './button-common';
|
||||||
import { View, PseudoClassHandler } from '../core/view';
|
import { View, PseudoClassHandler } from '../core/view';
|
||||||
import { backgroundColorProperty, borderTopWidthProperty, borderRightWidthProperty, borderBottomWidthProperty, borderLeftWidthProperty, paddingLeftProperty, paddingTopProperty, paddingRightProperty, paddingBottomProperty } from '../styling/style-properties';
|
import { backgroundColorProperty, borderTopWidthProperty, borderRightWidthProperty, borderBottomWidthProperty, borderLeftWidthProperty, paddingLeftProperty, paddingTopProperty, paddingRightProperty, paddingBottomProperty } from '../styling/style-properties';
|
||||||
import { textAlignmentProperty, whiteSpaceProperty } from '../text-base';
|
import { textAlignmentProperty, whiteSpaceProperty, textOverflowProperty } from '../text-base';
|
||||||
import { layout } from '../../utils';
|
import { layout } from '../../utils';
|
||||||
import { CoreTypes } from '../../core-types';
|
import { CoreTypes } from '../../core-types';
|
||||||
import { Color } from '../../color';
|
import { Color } from '../../color';
|
||||||
@ -219,17 +219,42 @@ export class Button extends ButtonBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
[whiteSpaceProperty.setNative](value: CoreTypes.WhiteSpaceType) {
|
[whiteSpaceProperty.setNative](value: CoreTypes.WhiteSpaceType) {
|
||||||
|
this.adjustLineBreak();
|
||||||
|
}
|
||||||
|
|
||||||
|
[textOverflowProperty.setNative](value: CoreTypes.TextOverflowType) {
|
||||||
|
this.adjustLineBreak();
|
||||||
|
}
|
||||||
|
|
||||||
|
private adjustLineBreak() {
|
||||||
|
const whiteSpace = this.whiteSpace;
|
||||||
|
const textOverflow = this.textOverflow;
|
||||||
const nativeView = this.nativeViewProtected.titleLabel;
|
const nativeView = this.nativeViewProtected.titleLabel;
|
||||||
switch (value) {
|
switch (whiteSpace) {
|
||||||
case 'normal':
|
case 'normal':
|
||||||
nativeView.lineBreakMode = NSLineBreakMode.ByWordWrapping;
|
nativeView.lineBreakMode = NSLineBreakMode.ByWordWrapping;
|
||||||
nativeView.numberOfLines = this.maxLines;
|
nativeView.numberOfLines = this.maxLines;
|
||||||
break;
|
break;
|
||||||
case 'nowrap':
|
|
||||||
case 'initial':
|
case 'initial':
|
||||||
nativeView.lineBreakMode = NSLineBreakMode.ByTruncatingMiddle;
|
nativeView.lineBreakMode = NSLineBreakMode.ByTruncatingMiddle;
|
||||||
nativeView.numberOfLines = 1;
|
nativeView.numberOfLines = 1;
|
||||||
break;
|
break;
|
||||||
|
case 'nowrap':
|
||||||
|
switch (textOverflow) {
|
||||||
|
case 'clip':
|
||||||
|
nativeView.lineBreakMode = NSLineBreakMode.ByClipping;
|
||||||
|
nativeView.numberOfLines = this.maxLines;
|
||||||
|
break;
|
||||||
|
case 'ellipsis':
|
||||||
|
nativeView.lineBreakMode = NSLineBreakMode.ByTruncatingTail;
|
||||||
|
nativeView.numberOfLines = 1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
nativeView.lineBreakMode = NSLineBreakMode.ByTruncatingMiddle;
|
||||||
|
nativeView.numberOfLines = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,7 +68,7 @@ export { CSSHelper } from './styling/css-selector';
|
|||||||
|
|
||||||
export { Switch } from './switch';
|
export { Switch } from './switch';
|
||||||
export { TabView, TabViewItem } from './tab-view';
|
export { TabView, TabViewItem } from './tab-view';
|
||||||
export { TextBase, getTransformedText, letterSpacingProperty, textAlignmentProperty, textDecorationProperty, textTransformProperty, textShadowProperty, whiteSpaceProperty, lineHeightProperty } from './text-base';
|
export { TextBase, getTransformedText, letterSpacingProperty, textAlignmentProperty, textDecorationProperty, textTransformProperty, textShadowProperty, whiteSpaceProperty, textOverflowProperty, lineHeightProperty } from './text-base';
|
||||||
export { FormattedString } from './text-base/formatted-string';
|
export { FormattedString } from './text-base/formatted-string';
|
||||||
export { Span } from './text-base/span';
|
export { Span } from './text-base/span';
|
||||||
export { TextField } from './text-field';
|
export { TextField } from './text-field';
|
||||||
|
@ -4,7 +4,7 @@ import { Length, borderTopWidthProperty, borderRightWidthProperty, borderBottomW
|
|||||||
import { booleanConverter } from '../core/view-base';
|
import { booleanConverter } from '../core/view-base';
|
||||||
import { View, CSSType } from '../core/view';
|
import { View, CSSType } from '../core/view';
|
||||||
import { CoreTypes } from '../../core-types';
|
import { CoreTypes } from '../../core-types';
|
||||||
import { TextBase, whiteSpaceProperty } from '../text-base';
|
import { TextBase, whiteSpaceProperty, textOverflowProperty } from '../text-base';
|
||||||
import { layout } from '../../utils';
|
import { layout } from '../../utils';
|
||||||
|
|
||||||
import { ios } from '../styling/background';
|
import { ios } from '../styling/background';
|
||||||
@ -113,17 +113,38 @@ export class Label extends TextBase implements LabelDefinition {
|
|||||||
}
|
}
|
||||||
|
|
||||||
[whiteSpaceProperty.setNative](value: CoreTypes.WhiteSpaceType) {
|
[whiteSpaceProperty.setNative](value: CoreTypes.WhiteSpaceType) {
|
||||||
const nativeView = this.nativeTextViewProtected;
|
this.adjustLineBreak();
|
||||||
switch (value) {
|
}
|
||||||
|
|
||||||
|
[textOverflowProperty.setNative](value: CoreTypes.TextOverflowType) {
|
||||||
|
this.adjustLineBreak();
|
||||||
|
}
|
||||||
|
|
||||||
|
private adjustLineBreak() {
|
||||||
|
const whiteSpace = this.whiteSpace;
|
||||||
|
const textOverflow = this.textOverflow;
|
||||||
|
const nativeView = this.nativeViewProtected;
|
||||||
|
switch (whiteSpace) {
|
||||||
case 'normal':
|
case 'normal':
|
||||||
nativeView.lineBreakMode = NSLineBreakMode.ByWordWrapping;
|
nativeView.lineBreakMode = NSLineBreakMode.ByWordWrapping;
|
||||||
nativeView.numberOfLines = this.maxLines;
|
nativeView.numberOfLines = this.maxLines;
|
||||||
break;
|
break;
|
||||||
case 'nowrap':
|
|
||||||
case 'initial':
|
case 'initial':
|
||||||
nativeView.lineBreakMode = NSLineBreakMode.ByTruncatingTail;
|
nativeView.lineBreakMode = NSLineBreakMode.ByTruncatingTail;
|
||||||
nativeView.numberOfLines = 1;
|
nativeView.numberOfLines = 1;
|
||||||
break;
|
break;
|
||||||
|
case 'nowrap':
|
||||||
|
switch (textOverflow) {
|
||||||
|
case 'clip':
|
||||||
|
nativeView.lineBreakMode = NSLineBreakMode.ByClipping;
|
||||||
|
nativeView.numberOfLines = this.maxLines;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
nativeView.lineBreakMode = NSLineBreakMode.ByTruncatingTail;
|
||||||
|
nativeView.numberOfLines = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -172,6 +172,7 @@ export class Style extends Observable implements StyleDefinition {
|
|||||||
public textTransform: CoreTypes.TextTransformType;
|
public textTransform: CoreTypes.TextTransformType;
|
||||||
public textShadow: CSSShadow;
|
public textShadow: CSSShadow;
|
||||||
public whiteSpace: CoreTypes.WhiteSpaceType;
|
public whiteSpace: CoreTypes.WhiteSpaceType;
|
||||||
|
public textOverflow: CoreTypes.TextOverflowType;
|
||||||
|
|
||||||
public minWidth: CoreTypes.LengthType;
|
public minWidth: CoreTypes.LengthType;
|
||||||
public minHeight: CoreTypes.LengthType;
|
public minHeight: CoreTypes.LengthType;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// Types
|
// Types
|
||||||
import { getClosestPropertyValue, maxLinesProperty } from './text-base-common';
|
import { getClosestPropertyValue, maxLinesProperty, textOverflowProperty } from './text-base-common';
|
||||||
import { CSSShadow } from '../styling/css-shadow';
|
import { CSSShadow } from '../styling/css-shadow';
|
||||||
|
|
||||||
// Requires
|
// Requires
|
||||||
@ -311,17 +311,36 @@ export class TextBase extends TextBaseCommon {
|
|||||||
// Overridden in TextField because setSingleLine(false) will remove methodTransformation.
|
// Overridden in TextField because setSingleLine(false) will remove methodTransformation.
|
||||||
// and we don't want to allow TextField to be multiline
|
// and we don't want to allow TextField to be multiline
|
||||||
[whiteSpaceProperty.setNative](value: CoreTypes.WhiteSpaceType) {
|
[whiteSpaceProperty.setNative](value: CoreTypes.WhiteSpaceType) {
|
||||||
|
this.adjustLineBreak();
|
||||||
|
}
|
||||||
|
|
||||||
|
[textOverflowProperty.setNative](value: CoreTypes.TextOverflowType) {
|
||||||
|
this.adjustLineBreak();
|
||||||
|
}
|
||||||
|
|
||||||
|
private adjustLineBreak() {
|
||||||
|
const whiteSpace = this.whiteSpace;
|
||||||
|
const textOverflow = this.textOverflow;
|
||||||
const nativeView = this.nativeTextViewProtected;
|
const nativeView = this.nativeTextViewProtected;
|
||||||
switch (value) {
|
switch (whiteSpace) {
|
||||||
case 'initial':
|
case 'initial':
|
||||||
case 'normal':
|
case 'normal':
|
||||||
nativeView.setSingleLine(false);
|
nativeView.setSingleLine(false);
|
||||||
nativeView.setEllipsize(null);
|
nativeView.setEllipsize(null);
|
||||||
break;
|
break;
|
||||||
case 'nowrap':
|
case 'nowrap':
|
||||||
|
switch (textOverflow) {
|
||||||
|
case 'initial':
|
||||||
|
case 'ellipsis':
|
||||||
nativeView.setSingleLine(true);
|
nativeView.setSingleLine(true);
|
||||||
nativeView.setEllipsize(android.text.TextUtils.TruncateAt.END);
|
nativeView.setEllipsize(android.text.TextUtils.TruncateAt.END);
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
nativeView.setSingleLine(false);
|
||||||
|
nativeView.setEllipsize(android.text.TextUtils.TruncateAt.END);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
6
packages/core/ui/text-base/index.d.ts
vendored
6
packages/core/ui/text-base/index.d.ts
vendored
@ -63,6 +63,11 @@ export class TextBase extends View implements AddChildFromBuilder {
|
|||||||
*/
|
*/
|
||||||
whiteSpace: CoreTypes.WhiteSpaceType;
|
whiteSpace: CoreTypes.WhiteSpaceType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets or sets text-overflow style property.
|
||||||
|
*/
|
||||||
|
textOverflow: CoreTypes.TextOverflowType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets or sets white space style property.
|
* Gets or sets white space style property.
|
||||||
*/
|
*/
|
||||||
@ -134,6 +139,7 @@ export const textDecorationProperty: CssProperty<Style, CoreTypes.TextDecoration
|
|||||||
export const textTransformProperty: CssProperty<Style, CoreTypes.TextTransformType>;
|
export const textTransformProperty: CssProperty<Style, CoreTypes.TextTransformType>;
|
||||||
export const textShadowProperty: CssProperty<Style, CSSShadow>;
|
export const textShadowProperty: CssProperty<Style, CSSShadow>;
|
||||||
export const whiteSpaceProperty: CssProperty<Style, CoreTypes.WhiteSpaceType>;
|
export const whiteSpaceProperty: CssProperty<Style, CoreTypes.WhiteSpaceType>;
|
||||||
|
export const textOverflowProperty: CssProperty<Style, CoreTypes.TextOverflowType>;
|
||||||
export const letterSpacingProperty: CssProperty<Style, number>;
|
export const letterSpacingProperty: CssProperty<Style, number>;
|
||||||
export const lineHeightProperty: CssProperty<Style, number>;
|
export const lineHeightProperty: CssProperty<Style, number>;
|
||||||
|
|
||||||
|
@ -132,6 +132,13 @@ export abstract class TextBaseCommon extends View implements TextBaseDefinition
|
|||||||
this.style.whiteSpace = value;
|
this.style.whiteSpace = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get textOverflow(): CoreTypes.TextOverflowType {
|
||||||
|
return this.style.textOverflow;
|
||||||
|
}
|
||||||
|
set textOverflow(value: CoreTypes.TextOverflowType) {
|
||||||
|
this.style.textOverflow = value;
|
||||||
|
}
|
||||||
|
|
||||||
get padding(): string | CoreTypes.LengthType {
|
get padding(): string | CoreTypes.LengthType {
|
||||||
return this.style.padding;
|
return this.style.padding;
|
||||||
}
|
}
|
||||||
@ -291,6 +298,16 @@ export const whiteSpaceProperty = new CssProperty<Style, CoreTypes.WhiteSpaceTyp
|
|||||||
});
|
});
|
||||||
whiteSpaceProperty.register(Style);
|
whiteSpaceProperty.register(Style);
|
||||||
|
|
||||||
|
const textOverflowConverter = makeParser<CoreTypes.TextOverflowType>(makeValidator<CoreTypes.TextOverflowType>('clip', 'ellipsis', 'initial', 'unset'));
|
||||||
|
export const textOverflowProperty = new CssProperty<Style, CoreTypes.TextOverflowType>({
|
||||||
|
name: 'textOverflow',
|
||||||
|
cssName: 'text-overflow',
|
||||||
|
defaultValue: 'initial',
|
||||||
|
affectsLayout: global.isIOS,
|
||||||
|
valueConverter: textOverflowConverter,
|
||||||
|
});
|
||||||
|
textOverflowProperty.register(Style);
|
||||||
|
|
||||||
const textDecorationConverter = makeParser<CoreTypes.TextDecorationType>(makeValidator<CoreTypes.TextDecorationType>('none', 'underline', 'line-through', 'underline line-through'));
|
const textDecorationConverter = makeParser<CoreTypes.TextDecorationType>(makeValidator<CoreTypes.TextDecorationType>('none', 'underline', 'line-through', 'underline line-through'));
|
||||||
export const textDecorationProperty = new CssProperty<Style, CoreTypes.TextDecorationType>({
|
export const textDecorationProperty = new CssProperty<Style, CoreTypes.TextDecorationType>({
|
||||||
name: 'textDecoration',
|
name: 'textDecoration',
|
||||||
|
Reference in New Issue
Block a user