Border/background render fixes

This commit is contained in:
vakrilov
2015-07-06 13:19:00 +03:00
parent 2b292eec7c
commit 62553d9d24
8 changed files with 157 additions and 90 deletions

View File

@ -1,5 +1,3 @@
import observable = require("data/observable");
import pages = require("ui/page");
import view = require("ui/core/view");
export function applyTap(args) {
var el = view.getViewById(view.getAncestor(args.object, "Page"), "test-element");

View File

@ -1,28 +1,34 @@
<Page loaded="pageLoaded">
<GridLayout rows="auto,*">
<WrapLayout>
<!-- Background and Border -->
<Button width="50" height="50" text="r" tap="resetTap"/>
<Button width="50" height="50" text="1" tap="applyTap" tag="background-color: green;"/>
<Button width="50" height="50" text="2" tap="applyTap" tag="background-color: green; border-color: red; border-radius: 20; border-width: 4;"/>
<Button width="50" height="50" text="1" tap="applyTap" tag="margin: 20; background-color: lightgreen;"/>
<Button width="50" height="50" text="2.1" tap="applyTap" tag="margin: 20; background-color: lightgreen; border-color: lightpink; border-radius: 20; border-width: 40;"/>
<Button width="50" height="50" text="2.2" tap="applyTap" tag="margin: 20; background-color: lightgreen; border-color: lightpink; border-radius: 40; border-width: 40;"/>
<Button width="50" height="50" text="2.3" tap="applyTap" tag="margin: 20; background-color: lightgreen; border-color: lightpink; border-radius: 40; border-width: 20;"/>
<Button width="50" height="50" text="3" tap="applyTap" tag="background-image: url('~/pages/test2.png');"/>
<Button width="50" height="50" text="4" tap="applyTap" tag="background-image: url('~/pages/test2.png'); background-repeat:repeat-y;"/>
<Button width="50" height="50" text="5" tap="applyTap" tag="background-image: url('~/pages/test2.png'); background-repeat:repeat-x;"/>
<!-- Repeat -->
<Button width="50" height="50" text="3.1" tap="applyTap" tag="margin: 20; background-image: url('~/pages/test2.png');"/>
<Button width="50" height="50" text="3.2" tap="applyTap" tag="margin: 20; background-image: url('~/pages/test2.png'); background-repeat:repeat-y;"/>
<Button width="50" height="50" text="3.3" tap="applyTap" tag="margin: 20; background-image: url('~/pages/test2.png'); background-repeat:repeat-x;"/>
<!-- Position -->
<Button width="50" height="50" text="4.1" tap="applyTap" tag="margin: 20; background-image: url('~/pages/test2.png'); background-repeat:no-repeat;"/>
<Button width="50" height="50" text="4.2" tap="applyTap" tag="margin: 20; background-image: url('~/pages/test2.png'); background-repeat:no-repeat; background-position: left top;"/>
<Button width="50" height="50" text="4.3" tap="applyTap" tag="margin: 20; background-image: url('~/pages/test2.png'); background-repeat:no-repeat; background-position: center center;"/>
<Button width="50" height="50" text="4.4" tap="applyTap" tag="margin: 20; background-image: url('~/pages/test2.png'); background-repeat:no-repeat; background-position: right bottom;"/>
<Button width="50" height="50" text="4.5" tap="applyTap" tag="margin: 20; background-image: url('~/pages/test2.png'); background-repeat:no-repeat; background-position: 20% 80%;"/>
<Button width="50" height="50" text="6" tap="applyTap" tag="background-image: url('~/pages/test2.png'); background-repeat:no-repeat;"/>
<Button width="50" height="50" text="7" tap="applyTap" tag="background-image: url('~/pages/test2.png'); background-repeat:no-repeat; background-position: left top;"/>
<Button width="50" height="50" text="8" tap="applyTap" tag="background-image: url('~/pages/test2.png'); background-repeat:no-repeat; background-position: center center;"/>
<Button width="50" height="50" text="9" tap="applyTap" tag="background-image: url('~/pages/test2.png'); background-repeat:no-repeat; background-position: right bottom;"/>
<Button width="50" height="50" text="10" tap="applyTap" tag="background-image: url('~/pages/test2.png'); background-repeat:no-repeat; background-position: 20% 80%;"/>
<!-- Size -->
<Button width="50" height="50" text="5.1" tap="applyTap" tag="margin: 20; background-color: lightgreen; background-image: url('~/pages/test2.png'); background-repeat:no-repeat; background-position: center center; background-size: 100 100;"/>
<Button width="50" height="50" text="5.2" tap="applyTap" tag="margin: 20; background-color: lightgreen; background-image: url('~/pages/test2.png'); background-repeat:no-repeat; background-position: center center; background-size: 100% 100%;"/>
<Button width="50" height="50" text="5.3" tap="applyTap" tag="margin: 20; background-color: lightgreen; background-image: url('~/pages/test2.png'); background-repeat:no-repeat; background-position: center center; background-size: cover;"/>
<Button width="50" height="50" text="5.4" tap="applyTap" tag="margin: 20; background-color: lightgreen; background-image: url('~/pages/test2.png'); background-repeat:no-repeat; background-position: center center; background-size: contain;"/>
<Button width="50" height="50" text="5.5" tap="applyTap" tag="margin: 20; background-color: lightgreen; background-image: url('~/pages/test2.png'); background-repeat:no-repeat; background-position: center center; background-size: 100 100; background-color: lightgreen;"/>
<Button width="50" height="50" text="11" tap="applyTap" tag="background-image: url('~/pages/test2.png'); background-repeat:no-repeat; background-position: center center; background-size: 100 100;"/>
<Button width="50" height="50" text="12" tap="applyTap" tag="background-image: url('~/pages/test2.png'); background-repeat:no-repeat; background-position: center center; background-size: 100% 100%;"/>
<Button width="50" height="50" text="13" tap="applyTap" tag="background-image: url('~/pages/test2.png'); background-repeat:no-repeat; background-position: center center; background-size: cover;"/>
<Button width="50" height="50" text="14" tap="applyTap" tag="background-image: url('~/pages/test2.png'); background-repeat:no-repeat; background-position: center center; background-size: contain;"/>
<Button width="50" height="50" text="15" tap="applyTap" tag="background-image: url('~/pages/test2.png'); background-repeat:no-repeat; background-position: center center; background-size: 100 100; background-color: green;"/>
<Button width="50" height="50" text="16" tap="applyTap" tag="background-image: url('~/pages/test2.png'); background-repeat:repeat-x; background-position: 20% 80%; background-color: green; background-size: 25% 50%; border-radius: 20; border-width: 4; border-color: red;"/>
<!-- All -->
<Button width="50" height="50" text="6" tap="applyTap" tag="margin: 20; background-image: url('~/pages/test2.png'); background-repeat:repeat-x; background-position: 20% 80%; background-color: lightgreen; background-size: 25% 50%; border-radius: 20; border-width: 4; border-color: lightpink;"/>
</WrapLayout>
<GridLayout id="test-element" row="1">

View File

@ -39,8 +39,32 @@ export function test_setting_backgroundColor_property_from_CSS_is_applied_to_Sty
test_property_from_CSS_is_applied_to_style("backgroundColor", "background-color", new color.Color("#FF0000"), "#FF0000");
}
export function test_setting_fontSize_property_from_CSS_is_applied_to_Style() {
test_property_from_CSS_is_applied_to_style("fontSize", "font-size", 32);
export function test_setting_backgroundRepeat_property_from_CSS_is_applied_to_Style() {
test_property_from_CSS_is_applied_to_style("backgroundRepeat", "background-repeat", "repeat-x");
}
export function test_setting_backgroundSize_property_from_CSS_is_applied_to_Style() {
test_property_from_CSS_is_applied_to_style("backgroundSize", "background-size", "10% 20%");
}
export function test_setting_backgroundPosition_property_from_CSS_is_applied_to_Style() {
test_property_from_CSS_is_applied_to_style("backgroundPosition", "background-position", "left center");
}
export function test_setting_backgroundImage_property_from_CSS_is_applied_to_Style() {
test_property_from_CSS_is_applied_to_style("backgroundImage", "background-image", "url('~/pages/test2.png')");
}
export function test_setting_borderWidth_property_from_CSS_is_applied_to_Style() {
test_property_from_CSS_is_applied_to_style("borderWidth", "border-width", 5);
}
export function test_setting_borderColor_property_from_CSS_is_applied_to_Style() {
test_property_from_CSS_is_applied_to_style("borderColor", "border-color", new color.Color("#FF0000"), "#FF0000");
}
export function test_setting_borderRadius_property_from_CSS_is_applied_to_Style() {
test_property_from_CSS_is_applied_to_style("borderRadius", "border-radius", 20);
}
export function test_setting_textAlignment_property_from_CSS_is_applied_to_Style() {
@ -81,6 +105,10 @@ export function test_setting_opacity_property_from_CSS_is_applied_to_Style() {
test_property_from_CSS_is_applied_to_style("opacity", "opacity", 0.5);
}
export function test_setting_fontSize_property_from_CSS_is_applied_to_Style() {
test_property_from_CSS_is_applied_to_style("fontSize", "font-size", 32);
}
export function test_setting_fontFamily_property_from_CSS_is_applied_to_Style() {
test_property_from_CSS_is_applied_to_style("fontFamily", "font-family", "Helvetica");
}

View File

@ -7,48 +7,44 @@ require("utils/module-merge").merge(common, exports);
// We are using "ad" here to avoid namespace collision with the global android object
export module ad {
export class BorderGradientDrawable extends android.graphics.drawable.GradientDrawable implements dts.ad.BorderGradientDrawable {
export class BorderDrawable extends android.graphics.drawable.ColorDrawable implements dts.ad.BorderDrawable {
private _density = utils.layout.getDisplayDensity();
private _borderWidth: number;
private _cornerRadius: number;
private _borderColor: number;
constructor() {
super();
return global.__native(this);
}
private _borderWidth: number;
get borderWidth(): number {
return this._borderWidth;
}
set borderWidth(value: number) {
if (this._borderWidth !== value) {
this._borderWidth = value;
this.setStroke(this._borderWidth * this._density, this._borderColor);
this.invalidateSelf();
}
}
private _cornerRadius: number;
get cornerRadius(): number {
return this._cornerRadius;
}
set cornerRadius(value: number) {
if (this._cornerRadius !== value) {
this._cornerRadius = value;
this.setCornerRadius(this._cornerRadius * this._density);
this.invalidateSelf();
}
}
private _borderColor: number;
get borderColor(): number {
return this._borderColor;
}
set borderColor(value: number) {
if (this._borderColor !== value) {
this._borderColor = value;
this.setStroke(this._borderWidth * this._density, this._borderColor);
this.invalidateSelf();
}
}
@ -65,60 +61,73 @@ export module ad {
}
public draw(canvas: android.graphics.Canvas): void {
super.draw(canvas);
console.log("BorderGradientDrawable.draw()");
//super.draw(canvas);
console.log("BorderDrawable.draw()");
var bounds = this.getBounds();
var boundsF = new android.graphics.RectF(bounds);
var boundsWidth = bounds.width();
var boundsHeight = bounds.height();
if (this.background && !this.background.isEmpty() && boundsWidth > 0 && boundsHeight > 0) {
var radius = this._cornerRadius * this._density;
var stroke = this._borderWidth * this._density;
var radius = this._cornerRadius * this._density;
var stroke = this._borderWidth * this._density;
// TODO: check this path
// set clip first
if (radius > 0) {
var path = new android.graphics.Path();
path.addRoundRect(new android.graphics.RectF(stroke, stroke, bounds.right - stroke, bounds.bottom - stroke), radius, radius, android.graphics.Path.Direction.CW);
path.addRoundRect(boundsF, radius, radius, android.graphics.Path.Direction.CW);
canvas.clipPath(path);
}
if (this.background.color && this.background.color.android) {
var c = this.background.color;
canvas.drawARGB(c.a, c.r, c.g, c.b);
// draw background
if (this.background.color && this.background.color.android) {
let c = this.background.color;
canvas.drawARGB(c.a, c.r, c.g, c.b);
}
// draw image
if (this.background.image) {
let bitmap = this.background.image.android;
let params = this.background.getDrawParams(boundsWidth, boundsHeight);
var matrix = new android.graphics.Matrix();
if (params.sizeX > 0 && params.sizeY > 0) {
var scaleX = params.sizeX / bitmap.getWidth();
var scaleY = params.sizeY / bitmap.getHeight();
matrix.setScale(scaleX, scaleY, 0, 0);
}
if (this.background.image) {
let bitmap = this.background.image.android;
let params = this.background.getDrawParams(boundsWidth, boundsHeight);
var matrix = new android.graphics.Matrix();
if (params.sizeX > 0 && params.sizeY > 0) {
var scaleX = params.sizeX / bitmap.getWidth();
var scaleY = params.sizeY / bitmap.getHeight();
matrix.setScale(scaleX, scaleY, 0, 0);
}
else {
params.sizeX = bitmap.getWidth();
params.sizeY = bitmap.getHeight();
}
matrix.postTranslate(params.posX, params.posY);
if (!params.repeatX && !params.repeatY) {
canvas.drawBitmap(bitmap, matrix, undefined);
}
else {
var shader = new android.graphics.BitmapShader(bitmap, android.graphics.Shader.TileMode.REPEAT, android.graphics.Shader.TileMode.REPEAT);
shader.setLocalMatrix(matrix);
var paint = new android.graphics.Paint();
paint.setShader(shader);
var w = params.repeatX ? bounds.width() : params.sizeX;
var h = params.repeatY ? bounds.height() : params.sizeY;
params.posX = params.repeatX ? 0 : params.posX;
params.posY = params.repeatY ? 0 : params.posY;
canvas.drawRect(params.posX, params.posY, params.posX + w, params.posY + h, paint);
}
else {
params.sizeX = bitmap.getWidth();
params.sizeY = bitmap.getHeight();
}
matrix.postTranslate(params.posX, params.posY);
if (!params.repeatX && !params.repeatY) {
canvas.drawBitmap(bitmap, matrix, undefined);
}
else {
var shader = new android.graphics.BitmapShader(bitmap, android.graphics.Shader.TileMode.REPEAT, android.graphics.Shader.TileMode.REPEAT);
shader.setLocalMatrix(matrix);
var paint = new android.graphics.Paint();
paint.setShader(shader);
var w = params.repeatX ? bounds.width() : params.sizeX;
var h = params.repeatY ? bounds.height() : params.sizeY;
params.posX = params.repeatX ? 0 : params.posX;
params.posY = params.repeatY ? 0 : params.posY;
canvas.drawRect(params.posX, params.posY, params.posX + w, params.posY + h, paint);
}
}
// draw border (topmost)
if (stroke > 0 && this._borderColor && this._borderColor) {
let borderPaint = new android.graphics.Paint();
borderPaint.setStyle(android.graphics.Paint.Style.STROKE);
borderPaint.setColor(this._borderColor);
// Notes double the stroke as the outer part will be clipped
borderPaint.setStrokeWidth(stroke * 2);
canvas.drawRoundRect(boundsF, radius, radius, borderPaint)
}
}
}

View File

@ -49,7 +49,7 @@ declare module "ui/styling/background" {
// We are using "ad" here to avoid namespace collision with the global android object
export module ad {
export class BorderGradientDrawable extends android.graphics.drawable.GradientDrawable {
export class BorderDrawable extends android.graphics.drawable.ColorDrawable {
borderWidth: number;
cornerRadius: number;
borderColor: number;

View File

@ -9,15 +9,17 @@ export module ios {
export function createBackgroundUIColor(view: viewModule.View): UIColor {
var background = <common.Background> view.style._getValue(style.backgroundInternalProperty);
var frame = (<UIView>view._nativeView).frame;
var boundsWidth = frame.size.width;
var boundsHeight = frame.size.height;
var result: UIColor;
if (background && !background.isEmpty() && frame.size.width > 0 && frame.size.height) {
if (background && !background.isEmpty() && boundsWidth > 0 && boundsHeight) {
if (!background.image) {
result = background.color.ios;
}
else {
var img = <UIImage>background.image.ios;
var params = background.getDrawParams(frame.size.width, frame.size.height);
var params = background.getDrawParams(boundsWidth, boundsHeight);
if (params.sizeX > 0 && params.sizeY > 0) {
var resizeRect = CGRectMake(0, 0, params.sizeX, params.sizeY);
@ -32,15 +34,15 @@ export module ios {
if (background.color && background.color.ios) {
CGContextSetFillColorWithColor(context, background.color.ios.CGColor);
CGContextFillRect(context, frame);
CGContextFillRect(context, CGRectMake(0, 0, boundsWidth, boundsHeight));
}
if (!params.repeatX && !params.repeatY) {
img.drawAtPoint(CGPointMake(params.posX, params.posY));
}
else {
var w = params.repeatX ? frame.size.width : img.size.width;
var h = params.repeatY ? frame.size.height : img.size.height;
var w = params.repeatX ? boundsWidth : img.size.width;
var h = params.repeatY ? boundsHeight : img.size.height;
CGContextSetPatternPhase(context, CGSizeMake(params.posX, params.posY));

View File

@ -26,9 +26,9 @@ function onBackgroundOrBorderPropertyChanged(v: view.View) {
if (v.borderWidth !== 0 || v.borderRadius !== 0 || !backgroundValue.isEmpty()) {
var nativeView = <android.view.View>v._nativeView;
var bkg = <background.ad.BorderGradientDrawable>nativeView.getBackground();
if (!(bkg instanceof background.ad.BorderGradientDrawable)) {
bkg = new background.ad.BorderGradientDrawable();
var bkg = <background.ad.BorderDrawable>nativeView.getBackground();
if (!(bkg instanceof background.ad.BorderDrawable)) {
bkg = new background.ad.BorderDrawable();
let viewClass = types.getClass(view);
if (!_defaultBackgrounds.has(viewClass)) {
_defaultBackgrounds.set(viewClass, nativeView.getBackground());

View File

@ -83,6 +83,13 @@ export class DefaultStyler implements definition.stylers.Styler {
}
}
private static getBorderWidthProperty(view: view.View): any {
if (view._nativeView instanceof UIView){
return (<UIView>view._nativeView).layer.borderWidth;
}
return 0;
}
//Border color methods
private static setBorderColorProperty(view: view.View, newValue: any) {
if (view._nativeView instanceof UIView && newValue instanceof UIColor) {
@ -92,10 +99,17 @@ export class DefaultStyler implements definition.stylers.Styler {
private static resetBorderColorProperty(view: view.View, nativeValue: any) {
if (view._nativeView instanceof UIView && nativeValue instanceof UIColor) {
(<UIView>view._nativeView).layer.borderColor = (<UIColor>nativeValue).CGColor;
(<UIView>view._nativeView).layer.borderColor = nativeValue;
}
}
private static getBorderColorProperty(view: view.View): any {
if (view._nativeView instanceof UIView) {
return (<UIView>view._nativeView).layer.borderColor;
}
return undefined;
}
//Border radius methods
private static setBorderRadiusProperty(view: view.View, newValue: any) {
if (view._nativeView instanceof UIView) {
@ -109,6 +123,13 @@ export class DefaultStyler implements definition.stylers.Styler {
}
}
private static getBorderRadiusProperty(view: view.View): any {
if (view._nativeView instanceof UIView) {
return (<UIView>view._nativeView).layer.cornerRadius;
}
return 0;
}
public static registerHandlers() {
style.registerHandler(style.backgroundInternalProperty, new stylersCommon.StylePropertyChangedHandler(
DefaultStyler.setBackgroundInternalProperty,
@ -125,15 +146,18 @@ export class DefaultStyler implements definition.stylers.Styler {
style.registerHandler(style.borderWidthProperty, new stylersCommon.StylePropertyChangedHandler(
DefaultStyler.setBorderWidthProperty,
DefaultStyler.resetBorderWidthProperty));
DefaultStyler.resetBorderWidthProperty,
DefaultStyler.getBorderWidthProperty));
style.registerHandler(style.borderColorProperty, new stylersCommon.StylePropertyChangedHandler(
DefaultStyler.setBorderColorProperty,
DefaultStyler.resetBorderColorProperty));
DefaultStyler.resetBorderColorProperty,
DefaultStyler.getBorderColorProperty));
style.registerHandler(style.borderRadiusProperty, new stylersCommon.StylePropertyChangedHandler(
DefaultStyler.setBorderRadiusProperty,
DefaultStyler.resetBorderRadiusProperty));
DefaultStyler.resetBorderRadiusProperty,
DefaultStyler.getBorderRadiusProperty));
}
}