Skip to content

Commit

Permalink
feat(android): implement borderRadius corner support
Browse files Browse the repository at this point in the history
  • Loading branch information
garymathews authored and sgtcoolguy committed Jul 7, 2020
1 parent 3c2c584 commit 545f8d5
Show file tree
Hide file tree
Showing 2 changed files with 116 additions and 35 deletions.
@@ -1,16 +1,19 @@
/**
* Appcelerator Titanium Mobile
* Copyright (c) 2012-2017 by Axway, Inc. All Rights Reserved.
* Copyright (c) 2020 by Axway, Inc. All Rights Reserved.
* Licensed under the terms of the Apache Public License
* Please see the LICENSE included with this distribution for details.
*/
package org.appcelerator.titanium.view;

import com.nineoldandroids.view.ViewHelper;
import org.appcelerator.kroll.common.Log;
import org.appcelerator.titanium.TiDimension;
import org.appcelerator.titanium.util.TiConvert;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Outline;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Path.Direction;
Expand All @@ -19,9 +22,10 @@
import android.graphics.RectF;
import android.os.Build;
import android.view.View;
import android.widget.FrameLayout;
import android.view.ViewOutlineProvider;
import android.graphics.Outline;
import android.widget.FrameLayout;

import com.nineoldandroids.view.ViewHelper;

/**
* This class is a wrapper for Titanium Views with borders. Any view that specifies a border
Expand All @@ -33,7 +37,7 @@ public class TiBorderWrapperView extends FrameLayout

private int color = Color.TRANSPARENT;
private int backgroundColor = Color.TRANSPARENT;
private float radius = 0;
private float[] radius = { 0, 0, 0, 0, 0, 0, 0, 0 };
private float borderWidth = 0;
private int alpha = -1;
private Paint paint;
Expand Down Expand Up @@ -66,17 +70,26 @@ protected void onDraw(Canvas canvas)
}

Path outerPath = new Path();
if (radius > 0f) {
float innerRadius = radius - padding;
if (innerRadius > 0f) {
outerPath.addRoundRect(innerRect, innerRadius, innerRadius, Direction.CW);
if (hasRadius()) {
float[] innerRadius = new float[this.radius.length];
for (int i = 0; i < this.radius.length; i++) {
innerRadius[i] = this.radius[i] - padding;
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
// Set specified border corners.
outerPath.addRoundRect(innerRect, innerRadius, Direction.CW);
} else {
outerPath.addRect(innerRect, Direction.CW);
outerPath.addRoundRect(innerRect, innerRadius[0], innerRadius[0], Direction.CW);
}
Path innerPath = new Path(outerPath);

// draw border
outerPath.addRoundRect(outerRect, radius, radius, Direction.CCW);
// Draw border.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
// Set specified border corners.
outerPath.addRoundRect(outerRect, this.radius, Direction.CW);
} else {
outerPath.addRoundRect(outerRect, this.radius[0], this.radius[0], Direction.CCW);
}
canvas.drawPath(outerPath, paint);

// TIMOB-16909: hack to fix anti-aliasing
Expand All @@ -101,7 +114,7 @@ protected void onDraw(Canvas canvas)
@Override
public void getOutline(View view, Outline outline)
{
outline.setRoundRect(bounds, radius);
outline.setRoundRect(bounds, radius[0]);
}
};
setOutlineProvider(viewOutlineProvider);
Expand All @@ -128,9 +141,92 @@ public void setBgColor(int color)
this.backgroundColor = color;
}

public void setRadius(float radius)
public boolean hasRadius()
{
for (float r : this.radius) {
if (r > 0f) {
return true;
}
}
return false;
}

public void setRadius(Object obj)
{
this.radius = radius;
if (obj instanceof Object[]) {
final Object[] cornerObjects = (Object[]) obj;
final float[] cornerPixels = new float[cornerObjects.length];

for (int i = 0; i < cornerObjects.length; i++) {
final Object corner = cornerObjects[i];
final TiDimension radiusDimension = TiConvert.toTiDimension(corner, TiDimension.TYPE_WIDTH);
if (radiusDimension != null) {
cornerPixels[i] = (float) radiusDimension.getPixels(this);
} else {
Log.w(TAG, "Invalid value specified for borderRadius[" + i + "].");
cornerPixels[i] = 0;
}
}

if (cornerPixels.length >= 4) {

// Top-Left, Top-Right, Bottom-Right, Bottom-Left
this.radius[0] = cornerPixels[0];
this.radius[1] = cornerPixels[0];
this.radius[2] = cornerPixels[1];
this.radius[3] = cornerPixels[1];
this.radius[4] = cornerPixels[2];
this.radius[5] = cornerPixels[2];
this.radius[6] = cornerPixels[3];
this.radius[7] = cornerPixels[3];

} else if (cornerPixels.length >= 2) {

// Top-Left, Bottom-Right and Top-Right, Bottom-Left
this.radius[0] = cornerPixels[0];
this.radius[1] = cornerPixels[0];
this.radius[2] = cornerPixels[0];
this.radius[3] = cornerPixels[0];
this.radius[4] = cornerPixels[1];
this.radius[5] = cornerPixels[1];
this.radius[6] = cornerPixels[1];
this.radius[7] = cornerPixels[1];

} else if (cornerPixels.length == 1) {

// Set all radius.
for (int i = 0; i < radius.length; i++) {
this.radius[i] = cornerPixels[0];
}

} else {
Log.w(TAG, "Could not set borderRadius, empty array.");
}

} else if (obj instanceof Object) {

// Support string formatting for multiple corners.
if (obj instanceof String) {
final String[] corners = ((String) obj).split("\\s");
if (corners != null && corners.length > 1) {
setRadius(corners);
return;
}
}

final TiDimension radiusDimension = TiConvert.toTiDimension(obj, TiDimension.TYPE_WIDTH);
float pixels = 0;

if (radiusDimension != null) {
pixels = (float) radiusDimension.getPixels(this);
} else {
Log.w(TAG, "Invalid value specified for borderRadius.");
}

for (int i = 0; i < radius.length; i++) {
this.radius[i] = pixels;
}
}
}

public void setBorderWidth(float borderWidth)
Expand Down
Expand Up @@ -438,9 +438,7 @@ protected boolean hasBorder(KrollDict d)
|| (d.containsKeyAndNotNull(TiC.PROPERTY_BORDER_WIDTH)
&& TiConvert.toTiDimension(d.getString(TiC.PROPERTY_BORDER_WIDTH), TiDimension.TYPE_WIDTH).getValue()
> 0f)
|| (d.containsKeyAndNotNull(TiC.PROPERTY_BORDER_RADIUS)
&& TiConvert.toTiDimension(d.getString(TiC.PROPERTY_BORDER_RADIUS), TiDimension.TYPE_WIDTH).getValue()
> 0f);
|| (d.containsKeyAndNotNull(TiC.PROPERTY_BORDER_RADIUS));
}

private boolean hasColorState(KrollDict d)
Expand Down Expand Up @@ -1460,17 +1458,10 @@ private void initializeBorder(KrollDict d, Integer bgColor)
}

if (d.containsKey(TiC.PROPERTY_BORDER_RADIUS)) {
final float FLOAT_EPSILON = Math.ulp(1.0f);
float radius = 0;
TiDimension radiusDim =
TiConvert.toTiDimension(d.get(TiC.PROPERTY_BORDER_RADIUS), TiDimension.TYPE_WIDTH);
if (radiusDim != null) {
radius = (float) radiusDim.getPixels(getNativeView());
}
if ((radius >= FLOAT_EPSILON) && (d.containsKey(TiC.PROPERTY_OPACITY) && LOWER_THAN_MARSHMALLOW)) {
if (d.containsKey(TiC.PROPERTY_OPACITY) && LOWER_THAN_MARSHMALLOW) {
disableHWAcceleration();
}
borderView.setRadius(radius);
borderView.setRadius(d.get(TiC.PROPERTY_BORDER_RADIUS));
}

if (bgColor != null) {
Expand Down Expand Up @@ -1515,16 +1506,10 @@ private void handleBorderProperty(String property, Object value)
borderView.setBorderWidth(1);
}
} else if (TiC.PROPERTY_BORDER_RADIUS.equals(property)) {
final float FLOAT_EPSILON = Math.ulp(1.0f);
float radius = 0;
TiDimension radiusDim = TiConvert.toTiDimension(value, TiDimension.TYPE_WIDTH);
if (radiusDim != null) {
radius = (float) radiusDim.getPixels(getNativeView());
}
if ((radius > FLOAT_EPSILON) && (proxy.hasProperty(TiC.PROPERTY_OPACITY) && LOWER_THAN_MARSHMALLOW)) {
if (proxy.hasProperty(TiC.PROPERTY_OPACITY) && LOWER_THAN_MARSHMALLOW) {
disableHWAcceleration();
}
borderView.setRadius(radius);
borderView.setRadius(value);
} else if (TiC.PROPERTY_BORDER_WIDTH.equals(property)) {
float width = 0;
TiDimension bwidth = TiConvert.toTiDimension(value, TiDimension.TYPE_WIDTH);
Expand Down

0 comments on commit 545f8d5

Please sign in to comment.