Added Padding+Border support for Label, Button, TextField and TextView for both platforms. Only iOS TextView does not support them.

This commit is contained in:
Rossen Hristov
2015-08-04 10:34:47 +03:00
parent a286027a4f
commit abc9faccfa
15 changed files with 251 additions and 55 deletions

View File

@ -107,6 +107,9 @@
<Content Include="apps\action-bar-demo\pages\center-view-segmented.xml" />
<Content Include="apps\action-bar-demo\pages\center-view.xml" />
<Content Include="apps\action-bar-demo\pages\data-binding.xml" />
<Content Include="apps\editable-text-demo\main-page.css">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="apps\gallery-app\content\html-view.xml" />
<Content Include="apps\orientation-demo\main-page.port.xml">
<SubType>Designer</SubType>
@ -1921,7 +1924,7 @@
<SaveServerSettingsInUserFile>False</SaveServerSettingsInUserFile>
</WebProjectProperties>
</FlavorProperties>
<UserProperties ui_2layouts_2wrap-layout_2package_1json__JSONSchema="http://json.schemastore.org/package" ui_2layouts_2grid-layout_2package_1json__JSONSchema="" ui_2layouts_2dock-layout_2package_1json__JSONSchema="" ui_2layouts_2absolute-layout_2package_1json__JSONSchema="http://json.schemastore.org/package" ui_2layouts_2linear-layout_2package_1json__JSONSchema="http://json.schemastore.org/package" ui_2web-view_2package_1json__JSONSchema="http://json.schemastore.org/package" ui_2content-view_2package_1json__JSONSchema="http://json.schemastore.org/package" apps_2gallery-app_2package_1json__JSONSchema="http://json.schemastore.org/package" apps_2absolute-layout-demo_2package_1json__JSONSchema="http://json.schemastore.org/package" apps_2editable-text-demo_2package_1json__JSONSchema="http://json.schemastore.org/package" ui_2scroll-view_2package_1json__JSONSchema="http://json.schemastore.org/package" />
<UserProperties ui_2scroll-view_2package_1json__JSONSchema="http://json.schemastore.org/package" apps_2editable-text-demo_2package_1json__JSONSchema="http://json.schemastore.org/package" apps_2absolute-layout-demo_2package_1json__JSONSchema="http://json.schemastore.org/package" apps_2gallery-app_2package_1json__JSONSchema="http://json.schemastore.org/package" ui_2content-view_2package_1json__JSONSchema="http://json.schemastore.org/package" ui_2web-view_2package_1json__JSONSchema="http://json.schemastore.org/package" ui_2layouts_2linear-layout_2package_1json__JSONSchema="http://json.schemastore.org/package" ui_2layouts_2absolute-layout_2package_1json__JSONSchema="http://json.schemastore.org/package" ui_2layouts_2dock-layout_2package_1json__JSONSchema="" ui_2layouts_2grid-layout_2package_1json__JSONSchema="" ui_2layouts_2wrap-layout_2package_1json__JSONSchema="http://json.schemastore.org/package" />
</VisualStudio>
</ProjectExtensions>
</Project>

View File

@ -0,0 +1,12 @@
Button, Label, TextView, TextField {
border-color: black;
border-width: 50;
border-radius: 3;
padding-left: 50;
padding-top: 50;
padding-right: 50;
padding-bottom: 50;
margin: 10;
font-size: 24;
text-align: right;
}

View File

@ -18,34 +18,34 @@ var label: labelModule.Label;
export function onPageLoaded(args: observableModule.EventData) {
var page = <pagesModule.Page>args.object;
stackLayout = page.getViewById<stackLayoutModule.StackLayout>("stack");
button = page.getViewById<buttonModule.Button>("button");
label = page.getViewById<labelModule.Label>("label");
//stackLayout = page.getViewById<stackLayoutModule.StackLayout>("stack");
//button = page.getViewById<buttonModule.Button>("button");
//label = page.getViewById<labelModule.Label>("label");
if (stackLayout.android) {
stackLayout.android.setClickable(true);
stackLayout.android.setFocusableInTouchMode(true);
}
//if (stackLayout.android) {
// stackLayout.android.setClickable(true);
// stackLayout.android.setFocusableInTouchMode(true);
//}
textField = page.getViewById<textFieldModule.TextField>("textField");
textField.style.backgroundColor = new colorModule.Color("LightGray");
//textField = page.getViewById<textFieldModule.TextField>("textField");
//textField.style.backgroundColor = new colorModule.Color("LightGray");
textView = page.getViewById<textViewModule.TextView>("textView");
textView.style.backgroundColor = new colorModule.Color("BlanchedAlmond");
//textView = page.getViewById<textViewModule.TextView>("textView");
//textView.style.backgroundColor = new colorModule.Color("BlanchedAlmond");
var viewModel = new model.WebViewModel();
page.bindingContext = viewModel;
//var viewModel = new model.WebViewModel();
//page.bindingContext = viewModel;
}
export function onTap(args: observableModule.EventData) {
if (textField.updateTextTrigger === enums.UpdateTextTrigger.focusLost) {
textField.updateTextTrigger = enums.UpdateTextTrigger.textChanged;
textView.updateTextTrigger = enums.UpdateTextTrigger.textChanged;
button.text = "textChanged";
}
else {
textField.updateTextTrigger = enums.UpdateTextTrigger.focusLost;
textView.updateTextTrigger = enums.UpdateTextTrigger.focusLost;
button.text = "focusLost";
}
//if (textField.updateTextTrigger === enums.UpdateTextTrigger.focusLost) {
// textField.updateTextTrigger = enums.UpdateTextTrigger.textChanged;
// textView.updateTextTrigger = enums.UpdateTextTrigger.textChanged;
// button.text = "textChanged";
//}
//else {
// textField.updateTextTrigger = enums.UpdateTextTrigger.focusLost;
// textView.updateTextTrigger = enums.UpdateTextTrigger.focusLost;
// button.text = "focusLost";
//}
}

View File

@ -1,8 +1,8 @@
<Page loaded="onPageLoaded">
<StackLayout id="stack">
<Button id="button" text="textChanged" height="100" margin="20" tap="onTap" backgroundColor="Red"/>
<Label id="label" text="{{ text }}" height="100" margin="20"/>
<TextField id="textField" text="{{ text }}" margin="20" autocapitalizationType="none" autocorrect="false"/>
<TextView id="textView" text="{{ text }}" height="100" margin="20" autocapitalizationType="none" autocorrect="false"/>
<Button id="button" text="button" tap="onTap" backgroundColor="Green" />
<Label id="label" text="label" backgroundColor="Yellow"/>
<TextField id="textField" text="text-field" hint="hint" backgroundColor="Red"/>
<TextView id="textView" text="text-view" backgroundColor="Blue"/>
</StackLayout>
</Page>

View File

@ -752,10 +752,6 @@ export class View extends proxy.ProxyObject implements definition.View {
//@endandroid
// TODO: We need to implement some kind of build step that includes these members only when building for iOS
//@ios
public _prepareNativeView(view: UIView) {
//
}
//@endios
get _childrenCount(): number {

2
ui/core/view.d.ts vendored
View File

@ -418,8 +418,6 @@ declare module "ui/core/view" {
_onDetached(force?: boolean): void;
_createUI(): void;
_prepareNativeView(view: UIView);
_checkMetadataOnPropertyChanged(metadata: dependencyObservable.PropertyMetadata);
_updateLayout(): void;

View File

@ -82,11 +82,6 @@ export class View extends viewCommon.View {
return this.ios;
}
public _prepareNativeView(view: UIView) {
// For UILabel and UIImage.
view.userInteractionEnabled = true;
}
get isLayoutRequested(): boolean {
return (this._privateFlags & PFLAG_FORCE_LAYOUT) === PFLAG_FORCE_LAYOUT;
}
@ -257,7 +252,7 @@ export class CustomLayoutView extends View {
if (this._nativeView && child._nativeView) {
if (types.isNullOrUndefined(atIndex) || atIndex >= this._nativeView.subviews.count) {
this._nativeView.addSubview(child._nativeView);
this._nativeView.addSubview(child._nativeView);
}
else {
this._nativeView.insertSubviewAtIndex(child._nativeView, atIndex);

View File

@ -33,7 +33,7 @@ export class HtmlView extends common.HtmlView {
super(options);
this._ios = new UILabel();
super._prepareNativeView(this._ios);
this._ios.userInteractionEnabled = true;
}
get ios(): UILabel {

View File

@ -48,7 +48,7 @@ export class Image extends imageCommon.Image {
this._ios = new UIImageView();
this._ios.contentMode = UIViewContentMode.UIViewContentModeScaleAspectFit;
this._ios.clipsToBounds = true;
super._prepareNativeView(this._ios);
this._ios.userInteractionEnabled = true;
}
get ios(): UIImageView {

View File

@ -24,14 +24,49 @@ function onTextWrapPropertyChanged(data: dependencyObservable.PropertyChangeData
global.moduleMerge(common, exports);
class UILabelImpl extends UILabel {
static new(): UILabelImpl {
return <UILabelImpl>super.new();
}
private _owner: Label;
public initWithOwner(owner: Label): UILabelImpl {
this._owner = owner;
return this;
}
public textRectForBoundsLimitedToNumberOfLines(bounds: CGRect, numberOfLines: number): CGRect {
var rect = super.textRectForBoundsLimitedToNumberOfLines(bounds, numberOfLines);
var textRect = CGRectMake(
- (this._owner.borderWidth + this._owner.paddingLeft),
- (this._owner.borderWidth + this._owner.paddingTop),
rect.size.width + (this._owner.borderWidth + this._owner.paddingLeft + this._owner.paddingRight + this._owner.borderWidth),
rect.size.height + (this._owner.borderWidth + this._owner.paddingTop + this._owner.paddingBottom + this._owner.borderWidth)
);
return textRect;
}
public drawTextInRect(rect: CGRect): void {
var textRect = CGRectMake(
(this._owner.borderWidth + this._owner.paddingLeft),
(this._owner.borderWidth + this._owner.paddingTop),
rect.size.width - (this._owner.borderWidth + this._owner.paddingLeft + this._owner.paddingRight + this._owner.borderWidth),
rect.size.height - (this._owner.borderWidth + this._owner.paddingTop + this._owner.paddingBottom + this._owner.borderWidth)
);
super.drawTextInRect(textRect);
}
}
export class Label extends common.Label {
private _ios: UILabel;
constructor(options?: definition.Options) {
super(options);
this._ios = new UILabel();
super._prepareNativeView(this._ios);
//this._ios = new UILabel();
this._ios = UILabelImpl.new().initWithOwner(this);
this._ios.userInteractionEnabled = true;
}
get ios(): UILabel {

View File

@ -801,7 +801,37 @@ export var minWidthProperty = new styleProperty.Property("minWidth", "min-width"
new observable.PropertyMetadata(0, AffectsLayout, null, isMinWidthHeightValid), converters.numberConverter);
export var minHeightProperty = new styleProperty.Property("minHeight", "min-height",
new observable.PropertyMetadata(0, AffectsLayout, null, isMinWidthHeightValid), converters.numberConverter);
new observable.PropertyMetadata(
0, observable.PropertyMetadataSettings.AffectsLayout, null, isMinWidthHeightValid),
converters.numberConverter);
export function parseThickness(value: any): { top: number; right: number; bottom: number; left: number } {
var result = { top: 0, right: 0, bottom: 0, left: 0 };
if (types.isString(value)) {
var arr = value.split(/[ ,]+/);
var top = parseInt(arr[0]);
top = isNaN(top) ? 0 : top;
var right = parseInt(arr[1]);
right = isNaN(right) ? top : right;
var bottom = parseInt(arr[2]);
bottom = isNaN(bottom) ? top : bottom;
var left = parseInt(arr[3]);
left = isNaN(left) ? right : left;
result.top = top;
result.right = right;
result.bottom = bottom;
result.left = left;
} else if (types.isNumber(value)) {
result.top = result.right = result.bottom = result.left = value;
}
return result;
}
// Helper property holding most layout related properties available in CSS.
// When layout related properties are set in CSS we chache them and send them to the native view in a single call.
@ -850,6 +880,9 @@ export var marginBottomProperty = new styleProperty.Property("marginBottom", "ma
export var paddingProperty = new styleProperty.Property("padding", "padding",
new observable.PropertyMetadata(null, null, onPaddingChanged));
export var paddingProperty = new styleProperty.Property("padding", "padding",
new observable.PropertyMetadata(null, null, onPaddingChanged));
export var paddingLeftProperty = new styleProperty.Property("paddingLeft", "padding-left",
new observable.PropertyMetadata(0, AffectsLayout, onPaddingValueChanged, isPaddingValid), converters.numberConverter);

View File

@ -34,9 +34,11 @@ function onBackgroundOrBorderPropertyChanged(v: view.View) {
nativeView.setBackground(bkg);
}
var padding = v.borderWidth * utils.layout.getDisplayDensity();
nativeView.setPadding(padding, padding, padding, padding);
var density = utils.layout.getDisplayDensity();
nativeView.setPadding((v.borderWidth + v.paddingLeft) * density,
(v.borderWidth + v.paddingTop) * density,
(v.borderWidth + v.paddingRight) * density,
(v.borderWidth + v.paddingBottom) * density);
bkg.borderWidth = v.borderWidth;
bkg.cornerRadius = v.borderRadius;
@ -219,6 +221,22 @@ export class DefaultStyler implements definition.stylers.Styler {
DefaultStyler.setMinHeightProperty,
DefaultStyler.resetMinHeightProperty))
style.registerHandler(style.paddingLeftProperty, new stylersCommon.StylePropertyChangedHandler(
DefaultStyler.setPaddingLeftProperty,
DefaultStyler.resetPaddingLeftProperty))
style.registerHandler(style.paddingTopProperty, new stylersCommon.StylePropertyChangedHandler(
DefaultStyler.setPaddingTopProperty,
DefaultStyler.resetPaddingTopProperty))
style.registerHandler(style.paddingRightProperty, new stylersCommon.StylePropertyChangedHandler(
DefaultStyler.setPaddingRightProperty,
DefaultStyler.resetPaddingRightProperty))
style.registerHandler(style.paddingBottomProperty, new stylersCommon.StylePropertyChangedHandler(
DefaultStyler.setPaddingBottomProperty,
DefaultStyler.resetPaddingBottomProperty))
// Use the same handler for all background/border properties
// Note: There is no default value getter - the default value is handled in onBackgroundOrBorderPropertyChanged
var borderHandler = new stylersCommon.StylePropertyChangedHandler(

View File

@ -227,6 +227,39 @@ export class ButtonStyler implements definition.stylers.Styler {
}
}
// Padding
private static setPaddingLeftProperty(view: view.View, newValue: any) {
(<UIButton>view._nativeView).contentEdgeInsets = UIEdgeInsetsFromString("{" + view.paddingTop + "," + newValue + "," + view.paddingBottom + "," + view.paddingRight + "}");
}
private static resetPaddingLeftProperty(view: view.View, nativeValue: any) {
(<UIButton>view._nativeView).contentEdgeInsets = UIEdgeInsetsFromString("{" + view.paddingTop + "," + 0 + "," + view.paddingBottom + "," + view.paddingRight + "}");
}
private static setPaddingTopProperty(view: view.View, newValue: any) {
(<UIButton>view._nativeView).contentEdgeInsets = UIEdgeInsetsFromString("{" + newValue + "," + view.paddingLeft + "," + view.paddingBottom + "," + view.paddingRight + "}");
}
private static resetPaddingTopProperty(view: view.View, nativeValue: any) {
(<UIButton>view._nativeView).contentEdgeInsets = UIEdgeInsetsFromString("{" + 0 + "," + view.paddingLeft + "," + view.paddingBottom + "," + view.paddingRight + "}");
}
private static setPaddingRightProperty(view: view.View, newValue: any) {
(<UIButton>view._nativeView).contentEdgeInsets = UIEdgeInsetsFromString("{" + view.paddingTop + "," + view.paddingLeft + "," + view.paddingBottom + "," + newValue + "}");
}
private static resetPaddingRightProperty(view: view.View, nativeValue: any) {
(<UIButton>view._nativeView).contentEdgeInsets = UIEdgeInsetsFromString("{" + view.paddingTop + "," + view.paddingLeft + "," + view.paddingBottom + "," + 0 + "}");
}
private static setPaddingBottomProperty(view: view.View, newValue: any) {
(<UIButton>view._nativeView).contentEdgeInsets = UIEdgeInsetsFromString("{" + view.paddingTop + "," + view.paddingLeft + "," + newValue + "," + view.paddingRight + "}");
}
private static resetPaddingBottomProperty(view: view.View, nativeValue: any) {
(<UIButton>view._nativeView).contentEdgeInsets = UIEdgeInsetsFromString("{" + view.paddingTop + "," + view.paddingLeft + "," + 0 + "," + view.paddingRight + "}");
}
public static registerHandlers() {
style.registerHandler(style.colorProperty, new stylersCommon.StylePropertyChangedHandler(
ButtonStyler.setColorProperty,
@ -242,6 +275,22 @@ export class ButtonStyler implements definition.stylers.Styler {
ButtonStyler.setTextAlignmentProperty,
ButtonStyler.resetTextAlignmentProperty,
ButtonStyler.getNativeTextAlignmentValue), "Button");
style.registerHandler(style.paddingLeftProperty, new stylersCommon.StylePropertyChangedHandler(
ButtonStyler.setPaddingLeftProperty,
ButtonStyler.resetPaddingLeftProperty), "Button");
style.registerHandler(style.paddingTopProperty, new stylersCommon.StylePropertyChangedHandler(
ButtonStyler.setPaddingTopProperty,
ButtonStyler.resetPaddingTopProperty), "Button");
style.registerHandler(style.paddingRightProperty, new stylersCommon.StylePropertyChangedHandler(
ButtonStyler.setPaddingRightProperty,
ButtonStyler.resetPaddingRightProperty), "Button");
style.registerHandler(style.paddingBottomProperty, new stylersCommon.StylePropertyChangedHandler(
ButtonStyler.setPaddingBottomProperty,
ButtonStyler.resetPaddingBottomProperty), "Button");
}
}

View File

@ -69,15 +69,48 @@ class UITextFieldDelegateImpl extends NSObject implements UITextFieldDelegate {
}
}
class UITextFieldImpl extends UITextField {
static new(): UITextFieldImpl {
return <UITextFieldImpl>super.new();
}
private _owner: TextField;
public initWithOwner(owner: TextField): UITextFieldImpl {
this._owner = owner;
return this;
}
private _getTextRectForBounds(bounds: CGRect): CGRect {
if (!this._owner) {
return bounds;
}
return CGRectMake(
this._owner.borderWidth + this._owner.paddingLeft,
this._owner.borderWidth + this._owner.paddingTop,
bounds.size.width - (this._owner.borderWidth + this._owner.paddingLeft + this._owner.paddingRight + this._owner.borderWidth),
bounds.size.height - (this._owner.borderWidth + this._owner.paddingTop + this._owner.paddingBottom + this._owner.borderWidth)
);
}
public textRectForBounds(bounds: CGRect): CGRect {
return this._getTextRectForBounds(bounds);
}
public editingRectForBounds(bounds: CGRect): CGRect {
return this._getTextRectForBounds(bounds);
}
}
export class TextField extends common.TextField {
private _ios: UITextField;
private _delegate: any;
private _delegate: UITextFieldDelegateImpl;
constructor() {
super();
this._ios = new UITextField();
this._ios = UITextFieldImpl.new().initWithOwner(this);
this._delegate = UITextFieldDelegateImpl.new().initWithOwner(this);
}

View File

@ -40,19 +40,43 @@ class UITextViewDelegateImpl extends NSObject implements UITextViewDelegate {
}
}
//class UITextViewImpl extends UITextView {
// static new(): UITextViewImpl {
// return <UITextViewImpl>super.new();
// }
// private _owner: TextView;
// public initWithOwner(owner: TextView): UITextViewImpl {
// this._owner = owner;
// return this;
// }
// public textRectForBoundsLimitedToNumberOfLines(bounds: CGRect, numberOfLines: number): CGRect {
// var rect = super.textRectForBoundsLimitedToNumberOfLines(bounds, numberOfLines);
// var textRect = CGRectMake(
// this._owner.borderWidth + this._owner.paddingLeft,
// this._owner.borderWidth + this._owner.paddingTop,
// rect.size.width - (this._owner.borderWidth + this._owner.paddingLeft + this._owner.paddingRight + this._owner.borderWidth),
// rect.size.height - (this._owner.borderWidth + this._owner.paddingTop + this._owner.paddingBottom + this._owner.borderWidth)
// );
// console.log("UITextViewImpl.textRectForBoundsLimitedToNumberOfLines(" + NSStringFromCGRect(bounds) + "): " + NSStringFromCGRect(textRect));
// return textRect;
// }
//}
export class TextView extends common.TextView {
private _ios: UITextView;
private _delegate: any;
private _delegate: UITextViewDelegateImpl;
constructor() {
super();
this._ios = UITextView.new();
this._ios = new UITextView();
//this._ios = UITextViewImpl.new().initWithOwner(this);
if (!this._ios.font) {
// For some reason font is null, not like stated in the docs.
this._ios.font = UIFont.systemFontOfSize(12);
}
this._delegate = UITextViewDelegateImpl.new().initWithOwner(this);
}