Skip to content
This repository has been archived by the owner on Aug 1, 2023. It is now read-only.

Commit

Permalink
Use matrix transformations to draw the shimmer instead of rotating a …
Browse files Browse the repository at this point in the history
…drawn rect

Summary: Instead of trying to compute the correct size of the shimmer draw rect by an incorrect heuristic, we instead apply a matrix transformation to the shader. This means we dont have to calculate a specially sized draw rect to ensure we cover the entire view, but it does mean that we need to enlongate the translation distance by the opposite dimension of the right triangle that is formed with the shimer's tilt and the non primary axis.

Reviewed By: sjkirby

Differential Revision: D8729182

fbshipit-source-id: eb8d948a9006a6193713113013fb8d82a94af3a8
  • Loading branch information
xiphirx authored and facebook-github-bot committed Jul 5, 2018
1 parent 6728c38 commit 58af197
Showing 1 changed file with 15 additions and 14 deletions.
29 changes: 15 additions & 14 deletions shimmer/src/main/java/com/facebook/shimmer/ShimmerDrawable.java
Expand Up @@ -11,13 +11,13 @@
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.LinearGradient;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.RadialGradient;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.drawable.Drawable;
import android.support.annotation.NonNull;
Expand All @@ -33,7 +33,8 @@ public void onAnimationUpdate(ValueAnimator animation) {
};

private final Paint mShimmerPaint = new Paint();
private final RectF mDrawRect = new RectF();
private final Rect mDrawRect = new Rect();
private final Matrix mShaderMatrix = new Matrix();

private @Nullable ValueAnimator mValueAnimator;

Expand Down Expand Up @@ -80,7 +81,7 @@ public void onBoundsChange(Rect bounds) {
super.onBoundsChange(bounds);
final int width = bounds.width();
final int height = bounds.height();
mDrawRect.set(2 * -width, 2 * -height, 4 * width, 4 * height);
mDrawRect.set(0, 0, width, height);
updateShader();
maybeStartShimmer();
}
Expand All @@ -91,37 +92,37 @@ public void draw(@NonNull Canvas canvas) {
return;
}

final Rect bounds = getBounds();
final float width = bounds.width();
final float height = bounds.height();
final float tiltTan = (float) Math.tan(Math.toRadians(mShimmer.tilt));
final float translateHeight = mDrawRect.height() + tiltTan * mDrawRect.width();
final float translateWidth = mDrawRect.width() + tiltTan * mDrawRect.height();
final float dx;
final float dy;
final float animatedValue = mValueAnimator != null ? mValueAnimator.getAnimatedFraction() : 0f;
switch (mShimmer.direction) {
default:
case Shimmer.Direction.LEFT_TO_RIGHT:
dx = offset(-width, width, animatedValue);
dx = offset(-translateWidth, translateWidth, animatedValue);
dy = 0;
break;
case Shimmer.Direction.RIGHT_TO_LEFT:
dx = offset(width, -width, animatedValue);
dx = offset(translateWidth, -translateWidth, animatedValue);
dy = 0f;
break;
case Shimmer.Direction.TOP_TO_BOTTOM:
dx = 0f;
dy = offset(-height, height, animatedValue);
dy = offset(-translateHeight, translateHeight, animatedValue);
break;
case Shimmer.Direction.BOTTOM_TO_TOP:
dx = 0f;
dy = offset(height, -height, animatedValue);
dy = offset(translateHeight, -translateHeight, animatedValue);
break;
}

final int saveCount = canvas.save();
canvas.rotate(mShimmer.tilt, width / 2f, height / 2f);
canvas.translate(dx, dy);
mShaderMatrix.reset();
mShaderMatrix.setRotate(mShimmer.tilt, mDrawRect.width() / 2f, mDrawRect.height() / 2f);
mShaderMatrix.postTranslate(dx, dy);
mShimmerPaint.getShader().setLocalMatrix(mShaderMatrix);
canvas.drawRect(mDrawRect, mShimmerPaint);
canvas.restoreToCount(saveCount);
}

@Override
Expand Down

0 comments on commit 58af197

Please sign in to comment.