Skip to content

Commit

Permalink
fix(android): gif borderRadius not working and radius scale issue
Browse files Browse the repository at this point in the history
  • Loading branch information
iPel authored and zoomchan-cxj committed Aug 23, 2022
1 parent 258f9ac commit bb84fcd
Show file tree
Hide file tree
Showing 2 changed files with 112 additions and 60 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Movie;
import android.graphics.Path;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.text.TextUtils;
Expand All @@ -44,6 +46,7 @@
import com.tencent.mtt.hippy.views.common.CommonBorder;
import com.tencent.mtt.hippy.views.list.HippyRecycler;
import com.tencent.mtt.supportui.adapters.image.IDrawableTarget;
import com.tencent.mtt.supportui.utils.CommonTool;
import com.tencent.mtt.supportui.views.asyncimage.AsyncImageView;
import com.tencent.mtt.supportui.views.asyncimage.BackgroundDrawable;
import com.tencent.mtt.supportui.views.asyncimage.ContentDrawable;
Expand Down Expand Up @@ -74,6 +77,7 @@ public class HippyImageView extends AsyncImageView implements CommonBorder, Hipp
private int mGifStartY = 0;
private float mGifScaleX = 1;
private float mGifScaleY = 1;
private Path mGifPath;
private boolean mGifMatrixComputed = false;
private long mGifProgress = 0;
private long mGifLastPlayTime = -1;
Expand All @@ -92,6 +96,7 @@ public void resetProps() {
mImageType = null;
setBackgroundDrawable(null);
Arrays.fill(mShouldSendImageEvent, false);
mGifMatrixComputed = false;
}

@Override
Expand Down Expand Up @@ -157,6 +162,7 @@ protected void setImageEventEnable(int index, boolean enable) {
protected void resetContent() {
super.resetContent();
mGifMovie = null;
mGifMatrixComputed = false;
mGifProgress = 0;
mGifLastPlayTime = -1;
}
Expand Down Expand Up @@ -301,6 +307,7 @@ protected void updateContentDrawableProperty(int sourceType) {
if (mContentDrawable instanceof HippyContentDrawable && sourceType == SOURCE_TYPE_SRC) {
((HippyContentDrawable) mContentDrawable).setNinePatchCoordinate(mNinePatchRect);
}
mGifMatrixComputed = false;
}

@Override
Expand Down Expand Up @@ -429,10 +436,38 @@ private void computeMatrixParams() {
mGifStartX = (int) ((getWidth() / mGifScaleX - mGifMovie.width()) / 2f);
mGifStartY = (int) ((getHeight() / mGifScaleY - mGifMovie.height()) / 2f);
}
if (mGifPath == null) {
mGifPath = new Path();
} else {
mGifPath.rewind();
}
if (mBGDrawable != null) {
float[] borderWidthArray = mBGDrawable.getBorderWidthArray();
float fullBorderWidth = borderWidthArray == null ? 0 : borderWidthArray[0];
RectF bounds = new RectF(fullBorderWidth, fullBorderWidth, getWidth() - fullBorderWidth,
getHeight() - fullBorderWidth);
float[] borderRadiusArray = mBGDrawable.getBorderRadiusArray();
if (CommonTool.hasPositiveItem(borderRadiusArray)) {
float fullRadius = borderRadiusArray[0];
float topLeftRadius = calculateBorderRadius(borderRadiusArray[1], fullRadius, fullBorderWidth);
float topRightRadius = calculateBorderRadius(borderRadiusArray[2], fullRadius, fullBorderWidth);
float bottomRightRadius = calculateBorderRadius(borderRadiusArray[3], fullRadius, fullBorderWidth);
float bottomLeftRadius = calculateBorderRadius(borderRadiusArray[4], fullRadius, fullBorderWidth);
float[] radii = new float[] { topLeftRadius, topLeftRadius, topRightRadius, topRightRadius,
bottomRightRadius, bottomRightRadius, bottomLeftRadius, bottomLeftRadius };
mGifPath.addRoundRect(bounds, radii, Path.Direction.CW);
} else {
mGifPath.addRect(bounds, Path.Direction.CW);
}
}
mGifMatrixComputed = true;
}
}

private static float calculateBorderRadius(float value, float fullValue, float inset) {
return Math.max(0, (value != 0 ? value : fullValue) - inset * .5f);
}

@Override
protected void handleImageRequest(IDrawableTarget target, int sourceType, Object requestInfo) {
if (target != null && !TextUtils.isEmpty(target.getImageType())) {
Expand All @@ -441,6 +476,7 @@ protected void handleImageRequest(IDrawableTarget target, int sourceType, Object

if (target instanceof HippyDrawable && ((HippyDrawable)target).isAnimated()) {
mGifMovie = ((HippyDrawable) target).getGIF();
mGifMatrixComputed = false;
setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}

Expand All @@ -465,6 +501,36 @@ protected void handleImageRequest(IDrawableTarget target, int sourceType, Object
}
}

@Override
public void setBorderRadius(float radius, int position) {
super.setBorderRadius(radius, position);
mGifMatrixComputed = false;
}

@Override
public void setBorderWidth(float width, int position) {
super.setBorderWidth(width, position);
mGifMatrixComputed = false;
}

@Override
public void setBorderColor(int color, int position) {
super.setBorderColor(color, position);
mGifMatrixComputed = false;
}

@Override
public void setBorderStyle(int borderStyle) {
super.setBorderStyle(borderStyle);
mGifMatrixComputed = false;
}

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mGifMatrixComputed = false;
}

protected boolean drawGIF(Canvas canvas) {
if (mGifMovie == null) {
return false;
Expand Down Expand Up @@ -492,6 +558,9 @@ protected boolean drawGIF(Canvas canvas) {
int progress = mGifProgress > Integer.MAX_VALUE ? 0 : (int) mGifProgress;
mGifMovie.setTime(progress);
canvas.save(); // 保存变换矩阵
if (!mGifPath.isEmpty()) {
canvas.clipPath(mGifPath);
}
canvas.scale(mGifScaleX, mGifScaleY);
mGifMovie.draw(canvas, mGifStartX, mGifStartY);
canvas.restore(); // 恢复变换矩阵
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ public class ContentDrawable extends BaseDrawable

private boolean mNeedUpdateBorderPath;
private Path mBorderPath;
private RectF mTempRectForBorderRadius;

private int mImagePositionX;
private int mImagePositionY;
Expand Down Expand Up @@ -125,14 +124,10 @@ private void updatePath()
if (mBorderPath == null) {
mBorderPath = new Path();
} else {
mBorderPath.reset();
mBorderPath.rewind();
}
mNeedUpdateBorderPath = false;
if (mTempRectForBorderRadius == null)
{
mTempRectForBorderRadius = new RectF();
}
mTempRectForBorderRadius.set(mRect);
RectF tempRectF = new RectF(mRect);
// calc scale here
int bitmapWidth = mContentBitmap.getWidth();
int bitmapHeight = mContentBitmap.getHeight();
Expand All @@ -157,17 +152,17 @@ private void updatePath()
break;
case ORIGIN:
// 不拉伸,居左上
mTempRectForBorderRadius.top = 0;
mTempRectForBorderRadius.bottom = bitmapHeight;
mTempRectForBorderRadius.left = 0;
mTempRectForBorderRadius.right = bitmapWidth;
tempRectF.top = 0;
tempRectF.bottom = bitmapHeight;
tempRectF.left = 0;
tempRectF.right = bitmapWidth;
break;
case CENTER:
// 居中不拉伸
mTempRectForBorderRadius.top = (boundHeight - bitmapHeight) / 2;
mTempRectForBorderRadius.bottom = (boundHeight + bitmapHeight) / 2;
mTempRectForBorderRadius.left = (boundWidth - bitmapWidth) / 2;
mTempRectForBorderRadius.right = (boundWidth + bitmapWidth) / 2;
tempRectF.top = (boundHeight - bitmapHeight) / 2;
tempRectF.bottom = (boundHeight + bitmapHeight) / 2;
tempRectF.left = (boundWidth - bitmapWidth) / 2;
tempRectF.right = (boundWidth + bitmapWidth) / 2;
break;
case CENTER_INSIDE:
// 在保持图片宽高比的前提下缩放图片,直到宽度和高度都小于等于容器视图的尺寸
Expand All @@ -176,17 +171,17 @@ private void updatePath()
{
if (xScale > yScale)
{ // y到顶
mTempRectForBorderRadius.top = 0;
mTempRectForBorderRadius.bottom = boundHeight;
mTempRectForBorderRadius.left = (int) ((boundWidth - bitmapWidth * yScale) / 2);
mTempRectForBorderRadius.right = (int) ((boundWidth + bitmapWidth * yScale) / 2);
tempRectF.top = 0;
tempRectF.bottom = boundHeight;
tempRectF.left = (int) ((boundWidth - bitmapWidth * yScale) / 2);
tempRectF.right = (int) ((boundWidth + bitmapWidth * yScale) / 2);
}
else
{ // x到顶
mTempRectForBorderRadius.top = (int) ((boundHeight - bitmapHeight * xScale) / 2);
mTempRectForBorderRadius.bottom = (int) ((boundHeight + bitmapHeight * xScale) / 2);
mTempRectForBorderRadius.left = 0;
mTempRectForBorderRadius.right = boundWidth;
tempRectF.top = (int) ((boundHeight - bitmapHeight * xScale) / 2);
tempRectF.bottom = (int) ((boundHeight + bitmapHeight * xScale) / 2);
tempRectF.left = 0;
tempRectF.right = boundWidth;
}
}
break;
Expand All @@ -196,52 +191,40 @@ private void updatePath()
break;
}

mTempRectForBorderRadius.top += mImagePositionY;
mTempRectForBorderRadius.bottom += mImagePositionY;
mTempRectForBorderRadius.left += mImagePositionX;
mTempRectForBorderRadius.right += mImagePositionX;
tempRectF.top += mImagePositionY;
tempRectF.bottom += mImagePositionY;
tempRectF.left += mImagePositionX;
tempRectF.right += mImagePositionX;

float fullBorderWidth = mBorderWidthArray == null ? 0 : mBorderWidthArray[0];
if (fullBorderWidth > 1)
{
mTempRectForBorderRadius.inset(fullBorderWidth * 0.5f, fullBorderWidth * 0.5f);
if (fullBorderWidth != 0) {
tempRectF.inset(fullBorderWidth, fullBorderWidth);
}

if (CommonTool.hasPositiveItem(mBorderRadiusArray))
{
mBorderPath.addRect(tempRectF, Path.Direction.CW);

float topLeftRadius = mBorderRadiusArray[1];
if (topLeftRadius == 0 && mBorderRadiusArray[0] > 0)
{
topLeftRadius = mBorderRadiusArray[0];
}
float topRightRadius = mBorderRadiusArray[2];
if (topRightRadius == 0 && mBorderRadiusArray[0] > 0)
{
topRightRadius = mBorderRadiusArray[0];
}
float bottomRightRadius = mBorderRadiusArray[3];
if (bottomRightRadius == 0 && mBorderRadiusArray[0] > 0)
{
bottomRightRadius = mBorderRadiusArray[0];
}
float bottomLeftRadius = mBorderRadiusArray[4];
if (bottomLeftRadius == 0 && mBorderRadiusArray[0] > 0)
{
bottomLeftRadius = mBorderRadiusArray[0];
}

mBorderPath.addRoundRect(mTempRectForBorderRadius, new float[] { topLeftRadius, topLeftRadius, topRightRadius, topRightRadius,
bottomRightRadius, bottomRightRadius, bottomLeftRadius, bottomLeftRadius }, Path.Direction.CW);
}
else
{
// no border radius
mBorderPath.addRect(mTempRectForBorderRadius, Path.Direction.CW);
if (CommonTool.hasPositiveItem(mBorderRadiusArray)) {
Path tempPath = new Path();

float fullRadius = mBorderRadiusArray[0];
float topLeftRadius = calculateBorderRadius(mBorderRadiusArray[1], fullRadius, fullBorderWidth);
float topRightRadius = calculateBorderRadius(mBorderRadiusArray[2], fullRadius, fullBorderWidth);
float bottomRightRadius = calculateBorderRadius(mBorderRadiusArray[3], fullRadius, fullBorderWidth);
float bottomLeftRadius = calculateBorderRadius(mBorderRadiusArray[4], fullRadius, fullBorderWidth);

tempRectF.set(mRect);
tempRectF.inset(fullBorderWidth, fullBorderWidth);
tempPath.addRoundRect(tempRectF, new float[] { topLeftRadius, topLeftRadius, topRightRadius, topRightRadius,
bottomRightRadius, bottomRightRadius, bottomLeftRadius, bottomLeftRadius }, Path.Direction.CW);
mBorderPath.op(tempPath, Path.Op.INTERSECT);
}
}
}

private static float calculateBorderRadius(float value, float fullValue, float inset) {
return Math.max(0, (value != 0 ? value : fullValue) - inset * .5f);
}

@Override
protected void onBoundsChange(Rect bounds)
{
Expand Down

0 comments on commit bb84fcd

Please sign in to comment.