PlayerAndroid/app/src/main/java/code/name/monkey/retromusic/views/PopupBackground.java

160 lines
4.7 KiB
Java

/*
* Copyright (c) 2020 Hemanth Savarala.
*
* Licensed under the GNU General Public License v3
*
* This is free software: you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by
* the Free Software Foundation either version 3 of the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*/
package code.name.monkey.retromusic.views;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.Matrix;
import android.graphics.Outline;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.graphics.drawable.DrawableCompat;
import code.name.monkey.appthemehelper.ThemeStore;
import code.name.monkey.retromusic.R;
public class PopupBackground extends Drawable {
private final int mPaddingEnd;
private final int mPaddingStart;
@NonNull
private final Paint mPaint;
@NonNull
private final Path mPath = new Path();
@NonNull
private final Matrix mTempMatrix = new Matrix();
public PopupBackground(@NonNull Context context) {
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setColor(ThemeStore.Companion.accentColor(context));
mPaint.setStyle(Paint.Style.FILL);
Resources resources = context.getResources();
mPaddingStart = resources.getDimensionPixelOffset(R.dimen.afs_md2_popup_padding_start);
mPaddingEnd = resources.getDimensionPixelOffset(R.dimen.afs_md2_popup_padding_end);
}
private static void pathArcTo(@NonNull Path path, float centerX, float centerY, float radius,
float startAngle, float sweepAngle) {
path.arcTo(centerX - radius, centerY - radius, centerX + radius, centerY + radius,
startAngle, sweepAngle, false);
}
@Override
public void draw(@NonNull Canvas canvas) {
canvas.drawPath(mPath, mPaint);
}
@Override
public int getOpacity() {
return PixelFormat.TRANSLUCENT;
}
@Override
public void getOutline(@NonNull Outline outline) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q && !mPath.isConvex()) {
// The outline path must be convex before Q, but we may run into floating point error
// caused by calculation involving sqrt(2) or OEM implementation difference, so in this
// case we just omit the shadow instead of crashing.
super.getOutline(outline);
return;
}
outline.setConvexPath(mPath);
}
@Override
public void setAlpha(int alpha) {
}
@Override
public void setColorFilter(@Nullable ColorFilter colorFilter) {
}
@Override
public boolean getPadding(@NonNull Rect padding) {
if (needMirroring()) {
padding.set(mPaddingEnd, 0, mPaddingStart, 0);
} else {
padding.set(mPaddingStart, 0, mPaddingEnd, 0);
}
return true;
}
@Override
public boolean isAutoMirrored() {
return true;
}
@Override
public boolean onLayoutDirectionChanged(int layoutDirection) {
updatePath();
return true;
}
@Override
protected void onBoundsChange(@NonNull Rect bounds) {
updatePath();
}
private boolean needMirroring() {
return DrawableCompat.getLayoutDirection(this) == View.LAYOUT_DIRECTION_RTL;
}
private void updatePath() {
mPath.reset();
Rect bounds = getBounds();
float width = bounds.width();
float height = bounds.height();
float r = height / 2;
float sqrt2 = (float) Math.sqrt(2);
// Ensure we are convex.
width = Math.max(r + sqrt2 * r, width);
pathArcTo(mPath, r, r, r, 90, 180);
float o1X = width - sqrt2 * r;
pathArcTo(mPath, o1X, r, r, -90, 45f);
float r2 = r / 5;
float o2X = width - sqrt2 * r2;
pathArcTo(mPath, o2X, r, r2, -45, 90);
pathArcTo(mPath, o1X, r, r, 45f, 45f);
mPath.close();
if (needMirroring()) {
mTempMatrix.setScale(-1, 1, width / 2, 0);
} else {
mTempMatrix.reset();
}
mTempMatrix.postTranslate(bounds.left, bounds.top);
mPath.transform(mTempMatrix);
}
}