Exposed properties to allow image to be cropped when there is border radius

This commit is contained in:
vakrilov
2015-08-18 11:42:27 +03:00
parent 62efc37c25
commit aee834c88e

View File

@@ -4,122 +4,165 @@
package org.nativescript.widgets; package org.nativescript.widgets;
import android.content.Context; import android.content.Context;
import android.graphics.*;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
/** /**
* @author hhristov * @author hhristov
* *
*/ */
public class ImageView extends android.widget.ImageView { public class ImageView extends android.widget.ImageView {
private float cornerRadius = 0;
private float borderWidth = 0;
private double scaleW = 1; private Path path = new Path();
private double scaleH = 1; private RectF rect = new RectF();
public ImageView(Context context) {
super(context);
this.setScaleType(ScaleType.FIT_CENTER);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = MeasureSpec.getSize(widthMeasureSpec); private double scaleW = 1;
int widthMode = MeasureSpec.getMode(widthMeasureSpec); private double scaleH = 1;
int height = MeasureSpec.getSize(heightMeasureSpec); public ImageView(Context context) {
int heightMode = MeasureSpec.getMode(heightMeasureSpec); super(context);
this.setScaleType(ScaleType.FIT_CENTER);
}
public float getCornerRadius() {
return this.cornerRadius;
}
public void setCornerRadius(float radius) {
if (radius != this.cornerRadius) {
this.cornerRadius = radius;
this.invalidate();
}
}
public float getBorderWidth() {
return this.borderWidth;
}
public void setBorderWidth(float radius) {
if (radius != this.borderWidth) {
this.borderWidth = radius;
this.invalidate();
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = MeasureSpec.getSize(widthMeasureSpec);
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
Drawable drawable = this.getDrawable(); Drawable drawable = this.getDrawable();
int measureWidth; int measureWidth;
int measureHeight; int measureHeight;
if (drawable != null) { if (drawable != null) {
measureWidth = drawable.getIntrinsicWidth(); measureWidth = drawable.getIntrinsicWidth();
measureHeight = drawable.getIntrinsicHeight(); measureHeight = drawable.getIntrinsicHeight();
} else {
measureWidth = 0;
measureHeight = 0;
}
boolean finiteWidth = widthMode != MeasureSpec.UNSPECIFIED;
boolean finiteHeight = heightMode != MeasureSpec.UNSPECIFIED;
if (measureWidth != 0 && measureHeight != 0 && (finiteWidth || finiteHeight)) {
this.computeScaleFactor(width, height, finiteWidth, finiteHeight, measureWidth, measureHeight);
int resultW = (int) Math.floor(measureWidth * this.scaleW);
int resultH = (int) Math.floor(measureHeight * this.scaleH);
measureWidth = finiteWidth ? Math.min(resultW, width) : resultW;
measureHeight = finiteHeight ? Math.min(resultH, height) : resultH;
}
measureWidth += this.getPaddingLeft() + this.getPaddingRight();
measureHeight += this.getPaddingTop() + this.getPaddingBottom();
measureWidth = Math.max(measureWidth, getSuggestedMinimumWidth());
measureHeight = Math.max(measureHeight, getSuggestedMinimumHeight());
if (CommonLayoutParams.debuggable > 0) {
StringBuilder sb = CommonLayoutParams.getStringBuilder();
sb.append("ImageView onMeasure: ");
sb.append(MeasureSpec.toString(widthMeasureSpec));
sb.append(", ");
sb.append(MeasureSpec.toString(heightMeasureSpec));
sb.append(", stretch: ");
sb.append(this.getScaleType());
sb.append(", measureWidth: ");
sb.append(measureWidth);
sb.append(", measureHeight: ");
sb.append(measureHeight);
CommonLayoutParams.log(CommonLayoutParams.tag, sb.toString());
} }
else {
measureWidth = 0;
measureHeight = 0;
}
boolean finiteWidth = widthMode != MeasureSpec.UNSPECIFIED;
boolean finiteHeight = heightMode != MeasureSpec.UNSPECIFIED;
if (measureWidth != 0 && measureHeight != 0 && (finiteWidth || finiteHeight)) {
this.computeScaleFactor(width, height, finiteWidth, finiteHeight, measureWidth, measureHeight);
int resultW = (int) Math.floor(measureWidth * this.scaleW);
int resultH = (int) Math.floor(measureHeight * this.scaleH);
measureWidth = finiteWidth ? Math.min(resultW, width) : resultW;
measureHeight = finiteHeight ? Math.min(resultH, height) : resultH;
}
measureWidth += this.getPaddingLeft() + this.getPaddingRight();
measureHeight += this.getPaddingTop() + this.getPaddingBottom();
measureWidth = Math.max(measureWidth, getSuggestedMinimumWidth());
measureHeight = Math.max(measureHeight, getSuggestedMinimumHeight());
if (CommonLayoutParams.debuggable > 0) {
StringBuilder sb = CommonLayoutParams.getStringBuilder();
sb.append("ImageView onMeasure: ");
sb.append(MeasureSpec.toString(widthMeasureSpec));
sb.append(", ");
sb.append(MeasureSpec.toString(heightMeasureSpec));
sb.append(", stretch: ");
sb.append(this.getScaleType());
sb.append(", measureWidth: ");
sb.append(measureWidth);
sb.append(", measureHeight: ");
sb.append(measureHeight);
CommonLayoutParams.log(CommonLayoutParams.tag, sb.toString());
}
int widthSizeAndState = resolveSizeAndState(measureWidth, widthMeasureSpec, 0); int widthSizeAndState = resolveSizeAndState(measureWidth, widthMeasureSpec, 0);
int heightSizeAndState = resolveSizeAndState(measureHeight, heightMeasureSpec, 0); int heightSizeAndState = resolveSizeAndState(measureHeight, heightMeasureSpec, 0);
this.setMeasuredDimension(widthSizeAndState, heightSizeAndState); this.setMeasuredDimension(widthSizeAndState, heightSizeAndState);
} }
private void computeScaleFactor( private void computeScaleFactor(int measureWidth, int measureHeight, boolean widthIsFinite, boolean heightIsFinite, double nativeWidth, double nativeHeight) {
int measureWidth,
int measureHeight,
boolean widthIsFinite,
boolean heightIsFinite,
double nativeWidth,
double nativeHeight) {
this.scaleW = 1;
this.scaleH = 1;
ScaleType scale = this.getScaleType(); this.scaleW = 1;
this.scaleH = 1;
ScaleType scale = this.getScaleType();
if ((scale == ScaleType.CENTER_CROP || scale == ScaleType.FIT_CENTER || scale == ScaleType.FIT_XY) && if ((scale == ScaleType.CENTER_CROP || scale == ScaleType.FIT_CENTER || scale == ScaleType.FIT_XY) &&
(widthIsFinite || heightIsFinite)) { (widthIsFinite || heightIsFinite)) {
this.scaleW = (nativeWidth > 0) ? measureWidth / nativeWidth : 0d; this.scaleW = (nativeWidth > 0) ? measureWidth / nativeWidth : 0d;
this.scaleH = (nativeHeight > 0) ? measureHeight / nativeHeight : 0d; this.scaleH = (nativeHeight > 0) ? measureHeight / nativeHeight : 0d;
if (!widthIsFinite) { if (!widthIsFinite) {
this.scaleW = scaleH; this.scaleW = scaleH;
} } else if (!heightIsFinite) {
else if (!heightIsFinite) { this.scaleH = scaleW;
this.scaleH = scaleW; } else {
}
else {
// No infinite dimensions. // No infinite dimensions.
switch (scale) { switch (scale) {
case FIT_CENTER: case FIT_CENTER:
this.scaleH = this.scaleW < this.scaleH ? this.scaleW : this.scaleH; this.scaleH = this.scaleW < this.scaleH ? this.scaleW : this.scaleH;
this.scaleW = this.scaleH; this.scaleW = this.scaleH;
break; break;
case CENTER_CROP: case CENTER_CROP:
this.scaleH = this.scaleW > this.scaleH ? this.scaleW : this.scaleH; this.scaleH = this.scaleW > this.scaleH ? this.scaleW : this.scaleH;
this.scaleW = this.scaleH; this.scaleW = this.scaleH;
break; break;
default: default:
break; break;
} }
} }
} }
} }
@Override
protected void onDraw(Canvas canvas) {
// floor the border width to avoid gaps between the border and the image
float roundedBorderWidth = (float) Math.floor(this.borderWidth);
float innerRadius = Math.max(0, this.cornerRadius - roundedBorderWidth);
// The border width is included in the padding so there is no need for
// clip if there is no inner border radius.
if (innerRadius != 0) {
this.rect.set(
roundedBorderWidth,
roundedBorderWidth,
this.getWidth() - roundedBorderWidth,
this.getHeight() - roundedBorderWidth);
this.path.reset();
this.path.addRoundRect(rect, innerRadius, innerRadius, android.graphics.Path.Direction.CW);
canvas.clipPath(this.path);
}
super.onDraw(canvas);
}
} }