Fixed the check drawable getting black when on white background. Replaced the check drawable with lower dp. Moved two files to another package.

This commit is contained in:
Karim Abou Zeid 2015-04-22 12:41:33 +02:00
commit cc910143e1
19 changed files with 36 additions and 30 deletions

View file

@ -15,38 +15,38 @@ import android.widget.FrameLayout;
import com.kabouzeid.gramophone.R;
public class CircleView extends FrameLayout {
private final Bitmap mCheck;
private final Paint paint;
private final Paint paintBorder;
private Paint paintCheck;
private final int borderWidth;
public CircleView(Context context) {
this(context, null, 0);
}
public CircleView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public CircleView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
final int checkSize = (int) context.getResources().getDimension(R.dimen.circle_view_check);
mCheck = getResizedBitmap(BitmapFactory.decodeResource(context.getResources(),
R.drawable.ic_check), checkSize, checkSize);
R.drawable.ic_check_white_24dp), checkSize, checkSize);
borderWidth = (int) getResources().getDimension(R.dimen.circle_view_border);
paint = new Paint();
paint.setAntiAlias(true);
paintBorder = new Paint();
paintBorder.setAntiAlias(true);
paintBorder.setColor(Color.BLACK);
setWillNotDraw(false);
}
private static Bitmap getResizedBitmap(Bitmap bm, int newHeight, int newWidth) {
int width = bm.getWidth();
int height = bm.getHeight();
@ -55,29 +55,32 @@ public class CircleView extends FrameLayout {
Matrix matrix = new Matrix();
matrix.postScale(scaleWidth, scaleHeight);
Bitmap resizedBitmap = Bitmap.createBitmap(bm, 0, 0, width, height, matrix, false);
bm.recycle();
if (bm != resizedBitmap) {
bm.recycle();
}
return resizedBitmap;
}
@Override
public void setBackgroundColor(int color) {
paint.setColor(color);
requestLayout();
invalidate();
}
public void setBorderColor(int color) {
paintBorder.setColor(color);
requestLayout();
invalidate();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
if (widthMode == MeasureSpec.EXACTLY && heightMode != MeasureSpec.EXACTLY) {
int width = MeasureSpec.getSize(widthMeasureSpec);
//noinspection SuspiciousNameCombination
int height = width;
if (heightMode == MeasureSpec.AT_MOST) {
height = Math.min(height, MeasureSpec.getSize(heightMeasureSpec));
@ -87,25 +90,28 @@ public class CircleView extends FrameLayout {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int canvasSize = canvas.getWidth();
if (canvas.getHeight() < canvasSize)
canvasSize = canvas.getHeight();
int circleCenter = (canvasSize - (borderWidth * 2)) / 2;
canvas.drawCircle(circleCenter + borderWidth, circleCenter + borderWidth, ((canvasSize - (borderWidth * 2)) / 2) + borderWidth - 4.0f, paintBorder);
canvas.drawCircle(circleCenter + borderWidth, circleCenter + borderWidth, ((canvasSize - (borderWidth * 2)) / 2) - 4.0f, paint);
if (isActivated()) {
final int offset = (canvasSize / 2) - (mCheck.getWidth() / 2);
if (paint.getColor() == Color.WHITE && paintCheck == null) {
paintCheck = new Paint();
paintCheck.setAntiAlias(true);
paintCheck.setColorFilter(new PorterDuffColorFilter(Color.BLACK, PorterDuff.Mode.SRC_IN));
if (paint.getColor() == Color.WHITE) {
if (paintCheck == null) {
paintCheck = new Paint();
paintCheck.setAntiAlias(true);
paintCheck.setColorFilter(new PorterDuffColorFilter(Color.BLACK, PorterDuff.Mode.SRC_IN));
}
} else {
paintCheck = null;
}

View file

@ -0,0 +1,214 @@
package com.kabouzeid.gramophone.views;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.util.Property;
import android.view.animation.DecelerateInterpolator;
import com.kabouzeid.gramophone.R;
public class PlayPauseDrawable extends Drawable {
private static final long PLAY_PAUSE_ANIMATION_DURATION = 250;
private static final Property<PlayPauseDrawable, Float> PROGRESS =
new Property<PlayPauseDrawable, Float>(Float.class, "progress") {
@Override
public Float get(PlayPauseDrawable d) {
return d.getProgress();
}
@Override
public void set(PlayPauseDrawable d, Float value) {
d.setProgress(value);
}
};
private final Path leftPauseBar = new Path();
private final Path rightPauseBar = new Path();
private final Paint paint = new Paint();
private final float pauseBarWidth;
private final float pauseBarHeight;
private final float pauseBarDistance;
private float width;
private float height;
private final float fallBackWidth;
private final float fallBackHeight;
private float progress;
private boolean isPlay;
private boolean isPlaySet;
private AnimatorSet animatorSet;
public PlayPauseDrawable(Context context) {
final Resources res = context.getResources();
paint.setAntiAlias(true);
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.WHITE);
pauseBarWidth = res.getDimensionPixelSize(R.dimen.pause_bar_width);
pauseBarHeight = res.getDimensionPixelSize(R.dimen.pause_bar_height);
pauseBarDistance = res.getDimensionPixelSize(R.dimen.pause_bar_distance);
fallBackWidth = res.getDimensionPixelSize(R.dimen.fab_icon_bound_width);
fallBackHeight = res.getDimensionPixelSize(R.dimen.fab_icon_bound_height);
}
@Override
protected void onBoundsChange(final Rect bounds) {
super.onBoundsChange(bounds);
if (bounds.width() > 0 && bounds.height() > 0) {
width = bounds.width();
height = bounds.height();
} else {
width = fallBackWidth;
height = fallBackHeight;
}
}
@Override
public void draw(Canvas canvas) {
leftPauseBar.rewind();
rightPauseBar.rewind();
// The current distance between the two pause bars.
final float barDist = lerp(pauseBarDistance, 0, progress);
// The current width of each pause bar.
final float barWidth = lerp(pauseBarWidth, pauseBarHeight / 1.75f, progress);
// The current position of the left pause bar's top left coordinate.
final float firstBarTopLeft = lerp(0, barWidth, progress);
// The current position of the right pause bar's top right coordinate.
final float secondBarTopRight = lerp(2 * barWidth + barDist, barWidth + barDist, progress);
// Draw the left pause bar. The left pause bar transforms into the
// top half of the play button triangle by animating the position of the
// rectangle's top left coordinate and expanding its bottom width.
leftPauseBar.moveTo(0, 0);
leftPauseBar.lineTo(firstBarTopLeft, -pauseBarHeight);
leftPauseBar.lineTo(barWidth, -pauseBarHeight);
leftPauseBar.lineTo(barWidth, 0);
leftPauseBar.close();
// Draw the right pause bar. The right pause bar transforms into the
// bottom half of the play button triangle by animating the position of the
// rectangle's top right coordinate and expanding its bottom width.
rightPauseBar.moveTo(barWidth + barDist, 0);
rightPauseBar.lineTo(barWidth + barDist, -pauseBarHeight);
rightPauseBar.lineTo(secondBarTopRight, -pauseBarHeight);
rightPauseBar.lineTo(2 * barWidth + barDist, 0);
rightPauseBar.close();
canvas.save();
// Translate the play button a tiny bit to the right so it looks more centered.
canvas.translate(lerp(0, pauseBarHeight / 8f, progress), 0);
// (1) Pause --> Play: rotate 0 to 90 degrees clockwise.
// (2) Play --> Pause: rotate 90 to 180 degrees clockwise.
final float rotationProgress = isPlay ? 1 - progress : progress;
final float startingRotation = isPlay ? 90 : 0;
canvas.rotate(lerp(startingRotation, startingRotation + 90, rotationProgress), width / 2f, height / 2f);
// Position the pause/play button in the center of the drawable's bounds.
canvas.translate(width / 2f - ((2 * barWidth + barDist) / 2f), height / 2f + (pauseBarHeight / 2f));
// Draw the two bars that form the animated pause/play button.
canvas.drawPath(leftPauseBar, paint);
canvas.drawPath(rightPauseBar, paint);
canvas.restore();
}
private Animator getPausePlayAnimator() {
isPlaySet = !isPlaySet;
final Animator anim = ObjectAnimator.ofFloat(this, PROGRESS, isPlay ? 1 : 0, isPlay ? 0 : 1);
anim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
isPlay = !isPlay;
}
});
return anim;
}
private void setProgress(float progress) {
this.progress = progress;
invalidateSelf();
}
private float getProgress() {
return progress;
}
@Override
public void setAlpha(int alpha) {
paint.setAlpha(alpha);
invalidateSelf();
}
@Override
public void setColorFilter(ColorFilter cf) {
paint.setColorFilter(cf);
invalidateSelf();
}
@Override
public int getOpacity() {
return PixelFormat.TRANSLUCENT;
}
/**
* Linear interpolate between a and b with parameter t.
*/
private static float lerp(float a, float b, float t) {
return a + (b - a) * t;
}
public void animatedPlay() {
if (!isPlaySet) {
togglePlayPause();
}
}
public void animatedPause() {
if (isPlaySet) {
togglePlayPause();
}
}
public void setPlay() {
isPlaySet = true;
isPlay = true;
setProgress(1);
}
public void setPause() {
isPlaySet = false;
isPlay = false;
setProgress(0);
}
public void togglePlayPause() {
if (animatorSet != null) {
animatorSet.cancel();
}
animatorSet = new AnimatorSet();
final Animator pausePlayAnim = getPausePlayAnimator();
animatorSet.setInterpolator(new DecelerateInterpolator());
animatorSet.setDuration(PLAY_PAUSE_ANIMATION_DURATION);
animatorSet.playTogether(pausePlayAnim);
animatorSet.start();
}
}

View file

@ -0,0 +1,30 @@
package com.kabouzeid.gramophone.views;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.ImageView;
/**
* @author Karim Abou Zeid (kabouzeid)
*/
public class SquareImageView extends ImageView {
public SquareImageView(Context context) {
super(context);
}
public SquareImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public SquareImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//noinspection SuspiciousNameCombination
super.onMeasure(widthMeasureSpec, widthMeasureSpec);
}
}