mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-11-05 13:26:48 +08:00
Merge pull request #103 from NativeScript/image-and-corners
Implement non uniform border corner radiuses and fix blinking image-view radiuses
This commit is contained in:
6
.gitignore
vendored
6
.gitignore
vendored
@@ -46,3 +46,9 @@ local.properties
|
|||||||
ios/TNSWidgets/TNSWidgets.xcodeproj/project.xcworkspace/xcuserdata/
|
ios/TNSWidgets/TNSWidgets.xcodeproj/project.xcworkspace/xcuserdata/
|
||||||
ios/TNSWidgets/TNSWidgets.xcodeproj/xcuserdata/
|
ios/TNSWidgets/TNSWidgets.xcodeproj/xcuserdata/
|
||||||
ios/TNSWidgets/DerivedData/
|
ios/TNSWidgets/DerivedData/
|
||||||
|
|
||||||
|
android/widgets/bin
|
||||||
|
android/widgets/.settings
|
||||||
|
android/.project
|
||||||
|
android/widgets/.project
|
||||||
|
android/.settings
|
||||||
@@ -14,6 +14,7 @@ import android.graphics.Rect;
|
|||||||
import android.graphics.RectF;
|
import android.graphics.RectF;
|
||||||
import android.graphics.drawable.ColorDrawable;
|
import android.graphics.drawable.ColorDrawable;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.graphics.Shader;
|
||||||
|
|
||||||
import org.nativescript.widgets.image.BitmapOwner;
|
import org.nativescript.widgets.image.BitmapOwner;
|
||||||
import org.nativescript.widgets.image.Fetcher;
|
import org.nativescript.widgets.image.Fetcher;
|
||||||
@@ -160,6 +161,13 @@ public class BorderDrawable extends ColorDrawable implements BitmapOwner {
|
|||||||
return backgroundSize;
|
return backgroundSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean hasBorderWidth() {
|
||||||
|
return this.borderTopWidth != 0
|
||||||
|
|| this.borderRightWidth != 0
|
||||||
|
|| this.borderBottomWidth != 0
|
||||||
|
|| this.borderLeftWidth != 0;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean hasUniformBorderColor() {
|
public boolean hasUniformBorderColor() {
|
||||||
return this.borderTopColor == this.borderRightColor &&
|
return this.borderTopColor == this.borderRightColor &&
|
||||||
this.borderTopColor == this.borderBottomColor &&
|
this.borderTopColor == this.borderBottomColor &&
|
||||||
@@ -260,23 +268,36 @@ public class BorderDrawable extends ColorDrawable implements BitmapOwner {
|
|||||||
@Override
|
@Override
|
||||||
public void draw(Canvas canvas) {
|
public void draw(Canvas canvas) {
|
||||||
Rect bounds = this.getBounds();
|
Rect bounds = this.getBounds();
|
||||||
if (bounds.width() <= 0 || bounds.height() <= 0) {
|
float width = (float)bounds.width();
|
||||||
|
float height = (float)bounds.height();
|
||||||
|
|
||||||
|
if (width <= 0 || height <= 0) {
|
||||||
// When the view is off-screen the bounds might be empty and we don't have anything to draw.
|
// When the view is off-screen the bounds might be empty and we don't have anything to draw.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RectF backgroundBoundsF = new RectF(bounds.left, bounds.top, bounds.right, bounds.bottom);
|
||||||
|
|
||||||
float topBackoffAntialias = calculateBackoffAntialias(this.borderTopColor, this.borderTopWidth);
|
float topBackoffAntialias = calculateBackoffAntialias(this.borderTopColor, this.borderTopWidth);
|
||||||
float rightBackoffAntialias = calculateBackoffAntialias(this.borderRightColor, this.borderRightWidth);
|
float rightBackoffAntialias = calculateBackoffAntialias(this.borderRightColor, this.borderRightWidth);
|
||||||
float bottomBackoffAntialias = calculateBackoffAntialias(this.borderBottomColor, this.borderBottomWidth);
|
float bottomBackoffAntialias = calculateBackoffAntialias(this.borderBottomColor, this.borderBottomWidth);
|
||||||
float leftBackoffAntialias = calculateBackoffAntialias(this.borderLeftColor, this.borderLeftWidth);
|
float leftBackoffAntialias = calculateBackoffAntialias(this.borderLeftColor, this.borderLeftWidth);
|
||||||
|
|
||||||
RectF backgroundBoundsF = new RectF(
|
float[] backgroundRadii = {
|
||||||
bounds.left + leftBackoffAntialias,
|
Math.max(0, borderTopLeftRadius + leftBackoffAntialias), Math.max(0, borderTopLeftRadius + topBackoffAntialias),
|
||||||
bounds.top + topBackoffAntialias,
|
Math.max(0, borderTopRightRadius + rightBackoffAntialias), Math.max(0, borderTopRightRadius + topBackoffAntialias),
|
||||||
bounds.right - rightBackoffAntialias,
|
Math.max(0, borderBottomRightRadius + rightBackoffAntialias), Math.max(0, borderBottomRightRadius + bottomBackoffAntialias),
|
||||||
bounds.bottom - bottomBackoffAntialias);
|
Math.max(0, borderBottomLeftRadius + leftBackoffAntialias), Math.max(0, borderBottomLeftRadius + bottomBackoffAntialias)
|
||||||
|
};
|
||||||
|
|
||||||
float outerRadius = this.getUniformBorderRadius();
|
Path backgroundPath = new Path();
|
||||||
|
RectF backgroundRect = new RectF(
|
||||||
|
leftBackoffAntialias,
|
||||||
|
topBackoffAntialias,
|
||||||
|
width - rightBackoffAntialias,
|
||||||
|
height - bottomBackoffAntialias
|
||||||
|
);
|
||||||
|
backgroundPath.addRoundRect(backgroundRect, backgroundRadii, Path.Direction.CW);
|
||||||
|
|
||||||
// draw background
|
// draw background
|
||||||
if (this.backgroundColor != 0) {
|
if (this.backgroundColor != 0) {
|
||||||
@@ -288,12 +309,12 @@ public class BorderDrawable extends ColorDrawable implements BitmapOwner {
|
|||||||
if (this.clipPath != null && !this.clipPath.isEmpty()) {
|
if (this.clipPath != null && !this.clipPath.isEmpty()) {
|
||||||
drawClipPath(this.clipPath, canvas, backgroundColorPaint, backgroundBoundsF, this.density);
|
drawClipPath(this.clipPath, canvas, backgroundColorPaint, backgroundBoundsF, this.density);
|
||||||
} else {
|
} else {
|
||||||
canvas.drawRoundRect(backgroundBoundsF, outerRadius, outerRadius, backgroundColorPaint);
|
canvas.drawPath(backgroundPath, backgroundColorPaint);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.backgroundBitmap != null) {
|
if (this.backgroundBitmap != null) {
|
||||||
BackgroundDrawParams params = this.getDrawParams(bounds.width(), bounds.height());
|
BackgroundDrawParams params = this.getDrawParams(width, height);
|
||||||
Matrix transform = new Matrix();
|
Matrix transform = new Matrix();
|
||||||
if (params.sizeX > 0 && params.sizeY > 0) {
|
if (params.sizeX > 0 && params.sizeY > 0) {
|
||||||
float scaleX = params.sizeX / this.backgroundBitmap.getWidth();
|
float scaleX = params.sizeX / this.backgroundBitmap.getWidth();
|
||||||
@@ -303,16 +324,21 @@ public class BorderDrawable extends ColorDrawable implements BitmapOwner {
|
|||||||
params.sizeX = this.backgroundBitmap.getWidth();
|
params.sizeX = this.backgroundBitmap.getWidth();
|
||||||
params.sizeY = this.backgroundBitmap.getHeight();
|
params.sizeY = this.backgroundBitmap.getHeight();
|
||||||
}
|
}
|
||||||
transform.postTranslate(params.posX - leftBackoffAntialias, params.posY - topBackoffAntialias);
|
transform.postTranslate(params.posX, params.posY);
|
||||||
|
|
||||||
BitmapShader shader = new BitmapShader(this.backgroundBitmap, android.graphics.Shader.TileMode.REPEAT, android.graphics.Shader.TileMode.REPEAT);
|
|
||||||
shader.setLocalMatrix(transform);
|
|
||||||
|
|
||||||
Paint backgroundImagePaint = new Paint();
|
Paint backgroundImagePaint = new Paint();
|
||||||
|
BitmapShader shader = new BitmapShader(
|
||||||
|
this.backgroundBitmap,
|
||||||
|
params.repeatX ? Shader.TileMode.REPEAT : Shader.TileMode.CLAMP,
|
||||||
|
params.repeatY ? Shader.TileMode.REPEAT : Shader.TileMode.CLAMP
|
||||||
|
);
|
||||||
|
shader.setLocalMatrix(transform);
|
||||||
|
backgroundImagePaint.setAntiAlias(true);
|
||||||
|
backgroundImagePaint.setFilterBitmap(true);
|
||||||
backgroundImagePaint.setShader(shader);
|
backgroundImagePaint.setShader(shader);
|
||||||
|
|
||||||
float imageWidth = params.repeatX ? bounds.width() : params.sizeX;
|
float imageWidth = params.repeatX ? width : params.sizeX;
|
||||||
float imageHeight = params.repeatY ? bounds.height() : params.sizeY;
|
float imageHeight = params.repeatY ? height : params.sizeY;
|
||||||
params.posX = params.repeatX ? 0 : params.posX;
|
params.posX = params.repeatX ? 0 : params.posX;
|
||||||
params.posY = params.repeatY ? 0 : params.posY;
|
params.posY = params.repeatY ? 0 : params.posY;
|
||||||
|
|
||||||
@@ -321,60 +347,66 @@ public class BorderDrawable extends ColorDrawable implements BitmapOwner {
|
|||||||
} else {
|
} else {
|
||||||
boolean supportsPathOp = android.os.Build.VERSION.SDK_INT >= 19;
|
boolean supportsPathOp = android.os.Build.VERSION.SDK_INT >= 19;
|
||||||
if (supportsPathOp) {
|
if (supportsPathOp) {
|
||||||
// Path.Op can be used in API level 19+ to achieve the perfect geometry.
|
|
||||||
Path backgroundPath = new Path();
|
|
||||||
backgroundPath.addRoundRect(backgroundBoundsF, outerRadius, outerRadius, Path.Direction.CCW);
|
|
||||||
Path backgroundNoRepeatPath = new Path();
|
Path backgroundNoRepeatPath = new Path();
|
||||||
backgroundNoRepeatPath.addRect(params.posX, params.posY, params.posX + imageWidth, params.posY + imageHeight, Path.Direction.CCW);
|
backgroundNoRepeatPath.addRect(params.posX, params.posY, params.posX + imageWidth, params.posY + imageHeight, Path.Direction.CCW);
|
||||||
intersect(backgroundPath, backgroundNoRepeatPath);
|
intersect(backgroundNoRepeatPath, backgroundPath);
|
||||||
canvas.drawPath(backgroundPath, backgroundImagePaint);
|
canvas.drawPath(backgroundNoRepeatPath, backgroundImagePaint);
|
||||||
} else {
|
} else {
|
||||||
// Clipping here will not be anti-aliased but at least it won't shine through the rounded corners.
|
// Clipping here will not be anti-aliased but at least it won't shine through the rounded corners.
|
||||||
canvas.save();
|
canvas.save();
|
||||||
canvas.clipRect(params.posX, params.posY, params.posX + imageWidth, params.posY + imageHeight);
|
canvas.clipRect(params.posX, params.posY, params.posX + imageWidth, params.posY + imageHeight);
|
||||||
canvas.drawRoundRect(backgroundBoundsF, outerRadius, outerRadius, backgroundImagePaint);
|
canvas.drawPath(backgroundPath, backgroundImagePaint);
|
||||||
canvas.restore();
|
canvas.restore();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// draw border
|
// draw border
|
||||||
if (this.hasUniformBorder()) {
|
|
||||||
float borderWidth = this.getUniformBorderWidth();
|
|
||||||
int borderColor = this.getUniformBorderColor();
|
|
||||||
|
|
||||||
// iOS and browsers use black when no color is specified.
|
|
||||||
if (borderWidth > 0) {
|
|
||||||
float halfBorderWidth = borderWidth / 2.0f;
|
|
||||||
RectF middleBoundsF = new RectF(bounds.left + halfBorderWidth, bounds.top + halfBorderWidth, bounds.right - halfBorderWidth, bounds.bottom - halfBorderWidth);
|
|
||||||
Paint borderPaint = new Paint();
|
|
||||||
borderPaint.setColor(borderColor);
|
|
||||||
borderPaint.setAntiAlias(true);
|
|
||||||
if (this.clipPath != null && !this.clipPath.isEmpty()) {
|
if (this.clipPath != null && !this.clipPath.isEmpty()) {
|
||||||
|
float borderWidth = this.getUniformBorderWidth();
|
||||||
|
if (borderWidth > 0) {
|
||||||
|
Paint borderPaint = new Paint();
|
||||||
|
borderPaint.setColor(this.getUniformBorderColor());
|
||||||
borderPaint.setStyle(Paint.Style.STROKE);
|
borderPaint.setStyle(Paint.Style.STROKE);
|
||||||
borderPaint.setStrokeWidth(borderWidth);
|
borderPaint.setStrokeWidth(borderWidth);
|
||||||
drawClipPath(this.clipPath, canvas, borderPaint, backgroundBoundsF, this.density);
|
drawClipPath(this.clipPath, canvas, borderPaint, backgroundBoundsF, this.density);
|
||||||
} else {
|
}
|
||||||
if (outerRadius <= 0) {
|
} else if (!this.hasBorderWidth()) {
|
||||||
borderPaint.setStyle(Paint.Style.STROKE);
|
// No borders trap.
|
||||||
borderPaint.setStrokeWidth(borderWidth);
|
} else if (this.hasUniformBorderColor()) {
|
||||||
canvas.drawRect(middleBoundsF, borderPaint);
|
// iOS and browsers use black when no color is specified.
|
||||||
} else if (outerRadius >= borderWidth) {
|
if (borderLeftWidth > 0 || borderTopWidth > 0 || borderRightWidth > 0 || borderBottomWidth > 0) {
|
||||||
borderPaint.setStyle(Paint.Style.STROKE);
|
Paint borderPaint = new Paint();
|
||||||
borderPaint.setStrokeWidth(borderWidth);
|
borderPaint.setColor(this.getUniformBorderColor());
|
||||||
float middleRadius = Math.max(0, outerRadius - halfBorderWidth);
|
|
||||||
canvas.drawRoundRect(middleBoundsF, middleRadius, middleRadius, borderPaint);
|
|
||||||
} else {
|
|
||||||
Path borderPath = new Path();
|
|
||||||
RectF borderOuterBoundsF = new RectF(bounds.left, bounds.top, bounds.right, bounds.bottom);
|
|
||||||
borderPath.addRoundRect(borderOuterBoundsF, outerRadius, outerRadius, Path.Direction.CCW);
|
|
||||||
RectF borderInnerBoundsF = new RectF(bounds.left + borderWidth, bounds.top + borderWidth, bounds.right - borderWidth, bounds.bottom - borderWidth);
|
|
||||||
borderPath.addRect(borderInnerBoundsF, Path.Direction.CW);
|
|
||||||
borderPaint.setStyle(Paint.Style.FILL);
|
borderPaint.setStyle(Paint.Style.FILL);
|
||||||
|
borderPaint.setAntiAlias(true);
|
||||||
|
Path borderPath = new Path();
|
||||||
|
|
||||||
|
RectF borderOuterRect = new RectF(0, 0, width, height);
|
||||||
|
float[] borderOuterRadii = {
|
||||||
|
borderTopLeftRadius, borderTopLeftRadius,
|
||||||
|
borderTopRightRadius, borderTopRightRadius,
|
||||||
|
borderBottomRightRadius, borderBottomRightRadius,
|
||||||
|
borderBottomLeftRadius, borderBottomLeftRadius
|
||||||
|
};
|
||||||
|
borderPath.addRoundRect(borderOuterRect, borderOuterRadii, Path.Direction.CW);
|
||||||
|
|
||||||
|
RectF borderInnerRect = new RectF(
|
||||||
|
borderLeftWidth,
|
||||||
|
borderTopWidth,
|
||||||
|
width - borderRightWidth,
|
||||||
|
height - borderBottomWidth
|
||||||
|
);
|
||||||
|
float[] borderInnerRadii = {
|
||||||
|
Math.max(0, borderTopLeftRadius - borderLeftWidth), Math.max(0, borderTopLeftRadius - borderTopWidth),
|
||||||
|
Math.max(0, borderTopRightRadius - borderRightWidth), Math.max(0, borderTopRightRadius - borderTopWidth),
|
||||||
|
Math.max(0, borderBottomRightRadius - borderRightWidth), Math.max(0, borderBottomRightRadius - borderBottomWidth),
|
||||||
|
Math.max(0, borderBottomLeftRadius - borderLeftWidth), Math.max(0, borderBottomLeftRadius - borderBottomWidth)
|
||||||
|
};
|
||||||
|
borderPath.addRoundRect(borderInnerRect, borderInnerRadii, Path.Direction.CCW);
|
||||||
|
|
||||||
canvas.drawPath(borderPath, borderPaint);
|
canvas.drawPath(borderPath, borderPaint);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
float top = this.borderTopWidth;
|
float top = this.borderTopWidth;
|
||||||
float right = this.borderRightWidth;
|
float right = this.borderRightWidth;
|
||||||
@@ -467,7 +499,7 @@ public class BorderDrawable extends ColorDrawable implements BitmapOwner {
|
|||||||
// If the border is transparent we will backoff less, and we will not backoff more than half a pixel or half the border width.
|
// If the border is transparent we will backoff less, and we will not backoff more than half a pixel or half the border width.
|
||||||
float halfBorderWidth = borderWidth / 2.0f;
|
float halfBorderWidth = borderWidth / 2.0f;
|
||||||
float normalizedBorderAlpha = ((float) Color.alpha(borderColor)) / 255.0f;
|
float normalizedBorderAlpha = ((float) Color.alpha(borderColor)) / 255.0f;
|
||||||
return Math.min(0.5f, halfBorderWidth) * normalizedBorderAlpha;
|
return Math.min(1f, halfBorderWidth) * normalizedBorderAlpha;
|
||||||
}
|
}
|
||||||
|
|
||||||
@TargetApi(19)
|
@TargetApi(19)
|
||||||
|
|||||||
@@ -6,11 +6,11 @@ package org.nativescript.widgets;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.graphics.*;
|
import android.graphics.*;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.graphics.drawable.shapes.RoundRectShape;
|
||||||
|
|
||||||
import org.nativescript.widgets.image.BitmapOwner;
|
import org.nativescript.widgets.image.BitmapOwner;
|
||||||
import org.nativescript.widgets.image.Fetcher;
|
import org.nativescript.widgets.image.Fetcher;
|
||||||
import org.nativescript.widgets.image.Worker;
|
import org.nativescript.widgets.image.Worker;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author hhristov
|
* @author hhristov
|
||||||
*/
|
*/
|
||||||
@@ -208,78 +208,108 @@ public class ImageView extends android.widget.ImageView implements BitmapOwner {
|
|||||||
@Override
|
@Override
|
||||||
protected void onDraw(Canvas canvas) {
|
protected void onDraw(Canvas canvas) {
|
||||||
BorderDrawable background = this.getBackground() instanceof BorderDrawable ? (BorderDrawable) this.getBackground() : null;
|
BorderDrawable background = this.getBackground() instanceof BorderDrawable ? (BorderDrawable) this.getBackground() : null;
|
||||||
float uniformBorderWidth = background != null ? background.getUniformBorderWidth() : 0;
|
|
||||||
float uniformBorderRadius = background != null ? background.getUniformBorderRadius() : 0;
|
|
||||||
|
|
||||||
// floor the border width to avoid gaps between the border and the image
|
if (this.mBitmap != null) {
|
||||||
float roundedBorderWidth = (float) Math.floor(uniformBorderWidth);
|
float borderTopLeftRadius, borderTopRightRadius, borderBottomRightRadius, borderBottomLeftRadius;
|
||||||
float innerRadius = Math.max(0, uniformBorderRadius - roundedBorderWidth);
|
|
||||||
|
|
||||||
if (background != null) {
|
if (background != null) {
|
||||||
background.draw(canvas);
|
background.draw(canvas);
|
||||||
|
|
||||||
|
borderTopLeftRadius = background.getBorderTopLeftRadius();
|
||||||
|
borderTopRightRadius = background.getBorderTopRightRadius();
|
||||||
|
borderBottomRightRadius = background.getBorderBottomRightRadius();
|
||||||
|
borderBottomLeftRadius = background.getBorderBottomLeftRadius();
|
||||||
|
} else {
|
||||||
|
borderTopLeftRadius = borderTopRightRadius = borderBottomRightRadius = borderBottomLeftRadius = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The border width is included in the padding so there is no need for
|
// Padding?
|
||||||
// clip if there is no inner border radius.
|
float borderTopWidth = this.getPaddingTop();
|
||||||
if (innerRadius > 0) {
|
float borderRightWidth = this.getPaddingRight();
|
||||||
this.rect.set(
|
float borderBottomWidth = this.getPaddingBottom();
|
||||||
roundedBorderWidth,
|
float borderLeftWidth = this.getPaddingLeft();
|
||||||
roundedBorderWidth,
|
|
||||||
this.getWidth() - roundedBorderWidth,
|
|
||||||
this.getHeight() - roundedBorderWidth);
|
|
||||||
|
|
||||||
this.path.reset();
|
float innerWidth, innerHeight;
|
||||||
this.path.addRoundRect(rect, innerRadius, innerRadius, Path.Direction.CW);
|
|
||||||
|
|
||||||
canvas.clipPath(this.path);
|
|
||||||
}
|
|
||||||
|
|
||||||
float rotationDegree = this.getRotationAngle();
|
float rotationDegree = this.getRotationAngle();
|
||||||
|
boolean swap = Math.abs(rotationDegree % 180) > 45 && Math.abs(rotationDegree % 180) < 135;
|
||||||
|
|
||||||
if (Math.abs(rotationDegree) > ImageView.EPSILON && Math.abs((rotationDegree % 90) - 0.0) < ImageView.EPSILON) {
|
innerWidth = this.getWidth() - borderLeftWidth - borderRightWidth;
|
||||||
ScaleType scaleType = this.getScaleType();
|
innerHeight = this.getHeight() - borderTopWidth - borderBottomWidth;
|
||||||
|
|
||||||
|
// TODO: Capture all created objects here in locals and update them instead...
|
||||||
|
Path path = new Path();
|
||||||
|
float[] radii = {
|
||||||
|
Math.max(0, borderTopLeftRadius - borderLeftWidth), Math.max(0, borderTopLeftRadius - borderTopWidth),
|
||||||
|
Math.max(0, borderTopRightRadius - borderRightWidth), Math.max(0, borderTopRightRadius - borderTopWidth),
|
||||||
|
Math.max(0, borderBottomRightRadius - borderRightWidth), Math.max(0, borderBottomRightRadius - borderBottomWidth),
|
||||||
|
Math.max(0, borderBottomLeftRadius - borderLeftWidth), Math.max(0, borderBottomLeftRadius - borderBottomWidth)
|
||||||
|
};
|
||||||
|
path.addRoundRect(new RectF(borderLeftWidth, borderTopWidth, borderLeftWidth + innerWidth, borderTopWidth + innerHeight), radii, Path.Direction.CW);
|
||||||
|
|
||||||
|
Paint paint = new Paint();
|
||||||
|
BitmapShader bitmapShader = new BitmapShader(this.mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
|
||||||
|
|
||||||
float viewWidth = this.getWidth() - (2 * roundedBorderWidth);
|
|
||||||
float viewHeight = this.getHeight() - (2 * roundedBorderWidth);
|
|
||||||
float bitmapWidth = (float) mBitmap.getWidth();
|
float bitmapWidth = (float) mBitmap.getWidth();
|
||||||
float bitmapHeight = (float) mBitmap.getHeight();
|
float bitmapHeight = (float) mBitmap.getHeight();
|
||||||
|
|
||||||
float scaleX;
|
|
||||||
float scaleY;
|
|
||||||
float decision = (rotationDegree / 90) % 2;
|
|
||||||
if (Math.abs(Math.floor(decision) - 0) < ImageView.EPSILON) {
|
|
||||||
scaleX = viewWidth / bitmapWidth;
|
|
||||||
scaleY = viewHeight / bitmapHeight;
|
|
||||||
} else {
|
|
||||||
scaleX = viewHeight / bitmapWidth;
|
|
||||||
scaleY = viewWidth / bitmapHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
float scale = 1.0f;
|
|
||||||
|
|
||||||
if (scaleType == ScaleType.FIT_CENTER || scaleType == ScaleType.MATRIX) {
|
|
||||||
scale = (scaleX < scaleY) ? scaleX : scaleY;
|
|
||||||
} else if (scaleType == ScaleType.CENTER_CROP) {
|
|
||||||
scale = (scaleX < scaleY) ? scaleY : scaleX;
|
|
||||||
}
|
|
||||||
|
|
||||||
Matrix matrix = this.mMatrix;
|
Matrix matrix = this.mMatrix;
|
||||||
matrix.reset();
|
matrix.reset();
|
||||||
|
|
||||||
if (scaleType == ScaleType.CENTER_CROP || scaleType == ScaleType.FIT_CENTER || scaleType == ScaleType.MATRIX) {
|
matrix.postRotate(rotationDegree, bitmapWidth / 2, bitmapHeight / 2);
|
||||||
matrix.postScale(scale, scale);
|
if (swap) {
|
||||||
matrix.postTranslate(-(bitmapWidth * scale) / 2, -(bitmapHeight * scale) / 2);
|
matrix.postTranslate((bitmapHeight - bitmapWidth) / 2, (bitmapWidth - bitmapHeight) / 2);
|
||||||
} else if (scaleType == ScaleType.FIT_XY) {
|
float temp = bitmapWidth;
|
||||||
matrix.postScale(scaleX, scaleY);
|
bitmapWidth = bitmapHeight;
|
||||||
matrix.postTranslate(-((bitmapWidth * scaleX) + roundedBorderWidth) / 2, -((bitmapHeight * scaleY) + roundedBorderWidth) / 2);
|
bitmapHeight = temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
matrix.postRotate(rotationDegree);
|
float fittingScaleX = innerWidth / bitmapWidth;
|
||||||
matrix.postTranslate(viewWidth / 2 + roundedBorderWidth, viewHeight / 2 + roundedBorderWidth);
|
float fittingScaleY = innerHeight / bitmapHeight;
|
||||||
|
|
||||||
canvas.drawBitmap(this.mBitmap, matrix, null);
|
float uniformScale;
|
||||||
} else {
|
float pivotX, pivotY;
|
||||||
super.onDraw(canvas);
|
switch(this.getScaleType()) {
|
||||||
|
case FIT_CENTER: // aspectFit
|
||||||
|
uniformScale = Math.min(fittingScaleX, fittingScaleY);
|
||||||
|
matrix.postTranslate((innerWidth - bitmapWidth) / 2, (innerHeight - bitmapHeight) / 2);
|
||||||
|
matrix.postScale(uniformScale, uniformScale, innerWidth / 2, innerHeight / 2);
|
||||||
|
canvas.clipRect(
|
||||||
|
borderLeftWidth + (innerWidth - bitmapWidth * uniformScale) / 2,
|
||||||
|
borderTopWidth + (innerHeight - bitmapHeight * uniformScale) / 2,
|
||||||
|
borderLeftWidth + (innerWidth + bitmapWidth * uniformScale) / 2,
|
||||||
|
borderTopWidth + (innerHeight + bitmapHeight * uniformScale) / 2
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case CENTER_CROP: // aspectFill
|
||||||
|
uniformScale = Math.max(fittingScaleX, fittingScaleY);
|
||||||
|
matrix.postTranslate((innerWidth - bitmapWidth) / 2, (innerHeight - bitmapHeight) / 2);
|
||||||
|
matrix.postScale(uniformScale, uniformScale, innerWidth / 2, innerHeight / 2);
|
||||||
|
canvas.clipRect(
|
||||||
|
borderLeftWidth + (innerWidth - bitmapWidth * uniformScale) / 2,
|
||||||
|
borderTopWidth + (innerHeight - bitmapHeight * uniformScale) / 2,
|
||||||
|
borderLeftWidth + (innerWidth + bitmapWidth * uniformScale) / 2,
|
||||||
|
borderTopWidth + (innerHeight + bitmapHeight * uniformScale) / 2
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case FIT_XY: // fill
|
||||||
|
matrix.postScale(fittingScaleX, fittingScaleY);
|
||||||
|
break;
|
||||||
|
case MATRIX: // none
|
||||||
|
canvas.clipRect(
|
||||||
|
borderLeftWidth,
|
||||||
|
borderTopWidth,
|
||||||
|
borderLeftWidth + bitmapWidth,
|
||||||
|
borderTopWidth + bitmapHeight
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
matrix.postTranslate(borderLeftWidth, borderTopWidth);
|
||||||
|
bitmapShader.setLocalMatrix(matrix);
|
||||||
|
paint.setAntiAlias(true);
|
||||||
|
paint.setFilterBitmap(true);
|
||||||
|
paint.setShader(bitmapShader);
|
||||||
|
canvas.drawPath(path, paint);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ mkdir dist/package/platforms
|
|||||||
echo "Build android"
|
echo "Build android"
|
||||||
mkdir dist/package/platforms/android
|
mkdir dist/package/platforms/android
|
||||||
cd android
|
cd android
|
||||||
./gradlew assembleRelease
|
./gradlew --quiet assembleRelease
|
||||||
cd ..
|
cd ..
|
||||||
cp android/widgets/build/outputs/aar/widgets-release.aar dist/package/platforms/android/widgets-release.aar
|
cp android/widgets/build/outputs/aar/widgets-release.aar dist/package/platforms/android/widgets-release.aar
|
||||||
|
|
||||||
|
|||||||
2
build.sh
2
build.sh
@@ -15,7 +15,7 @@ mkdir dist/package/platforms
|
|||||||
echo "Build android"
|
echo "Build android"
|
||||||
mkdir dist/package/platforms/android
|
mkdir dist/package/platforms/android
|
||||||
cd android
|
cd android
|
||||||
./gradlew assembleRelease
|
./gradlew --quiet assembleRelease
|
||||||
cd ..
|
cd ..
|
||||||
cp android/widgets/build/outputs/aar/widgets-release.aar dist/package/platforms/android/widgets-release.aar
|
cp android/widgets/build/outputs/aar/widgets-release.aar dist/package/platforms/android/widgets-release.aar
|
||||||
|
|
||||||
|
|||||||
@@ -4,10 +4,10 @@ echo "Set exit on simple errors"
|
|||||||
set -e
|
set -e
|
||||||
|
|
||||||
echo "Build for iphonesimulator"
|
echo "Build for iphonesimulator"
|
||||||
xcodebuild -project TNSWidgets/TNSWidgets.xcodeproj -sdk iphonesimulator -target TNSWidgets -configuration Release clean build CONFIGURATION_BUILD_DIR=build/Release-iphonesimulator
|
xcodebuild -project TNSWidgets/TNSWidgets.xcodeproj -sdk iphonesimulator -target TNSWidgets -configuration Release clean build CONFIGURATION_BUILD_DIR=build/Release-iphonesimulator -quiet
|
||||||
|
|
||||||
echo "Build for iphoneos"
|
echo "Build for iphoneos"
|
||||||
xcodebuild -project TNSWidgets/TNSWidgets.xcodeproj -sdk iphoneos -target TNSWidgets -configuration Release clean build CONFIGURATION_BUILD_DIR=build/Release-iphoneos CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO
|
xcodebuild -project TNSWidgets/TNSWidgets.xcodeproj -sdk iphoneos -target TNSWidgets -configuration Release clean build CONFIGURATION_BUILD_DIR=build/Release-iphoneos CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO -quiet
|
||||||
|
|
||||||
echo "Build fat framework at TNSWidgets/build/TNSWidgets.framework"
|
echo "Build fat framework at TNSWidgets/build/TNSWidgets.framework"
|
||||||
rm -rf TNSWidgets/build/TNSWidgets.framework
|
rm -rf TNSWidgets/build/TNSWidgets.framework
|
||||||
|
|||||||
Reference in New Issue
Block a user