BarInsta/app/src/main/java/awais/instagrabber/customviews/masoudss_waveform/WaveformSeekBar.java

225 lines
8.0 KiB
Java
Executable File

package awais.instagrabber.customviews.masoudss_waveform;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.Shader;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import awais.instagrabber.R;
import awais.instagrabber.utils.Utils;
public final class WaveformSeekBar extends View {
private final int mScaledTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
private final Paint mWavePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
private final RectF mWaveRect = new RectF();
private final Canvas mProgressCanvas = new Canvas();
private final WaveGravity waveGravity = WaveGravity.BOTTOM;
private final int waveBackgroundColor;
private final int waveProgressColor;
private final float waveWidth = Utils.convertDpToPx(3);
private final float waveMinHeight = Utils.convertDpToPx(4);
private final float waveCornerRadius = Utils.convertDpToPx(2);
private final float waveGap = Utils.convertDpToPx(1);
private int mCanvasWidth = 0;
private int mCanvasHeight = 0;
private float mTouchDownX = 0F;
private int[] sample;
private int progress = 0;
private WaveFormProgressChangeListener progressChangeListener;
public WaveformSeekBar(final Context context) {
this(context, null);
}
public WaveformSeekBar(final Context context, @Nullable final AttributeSet attrs) {
this(context, attrs, 0);
}
public WaveformSeekBar(final Context context, @Nullable final AttributeSet attrs, final int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.waveBackgroundColor = ContextCompat.getColor(context, R.color.text_color_light);
this.waveProgressColor = ContextCompat.getColor(context, R.color.text_color_dark);
}
private int getSampleMax() {
int max = -1;
if (sample != null) for (final int i : sample) if (i >= max) max = i;
return max;
}
@SuppressLint("DrawAllocation")
@Override
protected void onDraw(final Canvas canvas) {
super.onDraw(canvas);
if (sample != null && sample.length != 0) {
final int availableWidth = getAvailableWidth();
final int availableHeight = getAvailableHeight();
final float step = availableWidth / (waveGap + waveWidth) / sample.length;
float i = 0F;
float lastWaveRight = (float) getPaddingLeft();
final int sampleMax = getSampleMax();
while (i < sample.length) {
float waveHeight = availableHeight * ((float) sample[(int) i] / sampleMax);
if (waveHeight < waveMinHeight)
waveHeight = waveMinHeight;
final float top;
if (waveGravity == WaveGravity.TOP) {
top = (float) getPaddingTop();
} else if (waveGravity == WaveGravity.CENTER) {
top = (float) getPaddingTop() + availableHeight / 2F - waveHeight / 2F;
} else if (waveGravity == WaveGravity.BOTTOM) {
top = mCanvasHeight - (float) getPaddingBottom() - waveHeight;
} else {
top = 0;
}
mWaveRect.set(lastWaveRight, top, lastWaveRight + waveWidth, top + waveHeight);
if (mWaveRect.contains(availableWidth * progress / 100F, mWaveRect.centerY())) {
int bitHeight = (int) mWaveRect.height();
if (bitHeight <= 0) bitHeight = (int) waveWidth;
final Bitmap bitmap = Bitmap.createBitmap(availableWidth, bitHeight, Bitmap.Config.ARGB_8888);
mProgressCanvas.setBitmap(bitmap);
float fillWidth = availableWidth * progress / 100F;
mWavePaint.setColor(waveProgressColor);
mProgressCanvas.drawRect(0F, 0F, fillWidth, mWaveRect.bottom, mWavePaint);
mWavePaint.setColor(waveBackgroundColor);
mProgressCanvas.drawRect(fillWidth, 0F, (float) availableWidth, mWaveRect.bottom, mWavePaint);
mWavePaint.setShader(new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP));
} else {
mWavePaint.setColor(mWaveRect.right <= availableWidth * progress / 100F ? waveProgressColor : waveBackgroundColor);
mWavePaint.setShader(null);
}
canvas.drawRoundRect(mWaveRect, waveCornerRadius, waveCornerRadius, mWavePaint);
lastWaveRight = mWaveRect.right + waveGap;
if (lastWaveRight + waveWidth > availableWidth + getPaddingLeft())
break;
i += 1 / step;
}
}
}
@Override
public boolean onTouchEvent(final MotionEvent event) {
if (!isEnabled()) return false;
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
if (isParentScrolling()) mTouchDownX = event.getX();
else updateProgress(event);
break;
case MotionEvent.ACTION_MOVE:
updateProgress(event);
break;
case MotionEvent.ACTION_UP:
if (Math.abs(event.getX() - mTouchDownX) > mScaledTouchSlop)
updateProgress(event);
performClick();
break;
}
return true;
}
@Override
protected void onSizeChanged(final int w, final int h, final int oldw, final int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mCanvasWidth = w;
mCanvasHeight = h;
}
@Override
public boolean performClick() {
super.performClick();
return true;
}
private boolean isParentScrolling() {
View parent = (View) getParent();
final View root = getRootView();
while (true) {
if (parent.canScrollHorizontally(1) || parent.canScrollHorizontally(-1) ||
parent.canScrollVertically(1) || parent.canScrollVertically(-1))
return true;
if (parent == root) return false;
parent = (View) parent.getParent();
}
}
private void updateProgress(@NonNull final MotionEvent event) {
progress = (int) (100 * event.getX() / getAvailableWidth());
invalidate();
if (progressChangeListener != null)
progressChangeListener.onProgressChanged(this, Math.min(Math.max(0, progress), 100), true);
}
private int getAvailableWidth() {
return mCanvasWidth - getPaddingLeft() - getPaddingRight();
}
private int getAvailableHeight() {
return mCanvasHeight - getPaddingTop() - getPaddingBottom();
}
// public void setSampleFrom(final String path, final boolean ignoreExtension) { // was false
// try {
// final SoundParser soundFile = SoundParser.create(path, ignoreExtension);
// sample = soundFile.frameGains;
// } catch (final Exception e) {
// sample = null;
// }
// }
//
// public void setSampleFrom(@NonNull final File file, final boolean ignoreExtension) { // was false
// setSampleFrom(file.getAbsolutePath(), ignoreExtension);
// }
public void setProgress(final int progress) {
this.progress = progress;
invalidate();
}
public void setProgressChangeListener(final WaveFormProgressChangeListener progressChangeListener) {
this.progressChangeListener = progressChangeListener;
}
public void setSample(final int[] sample) {
if (sample != this.sample) {
this.sample = sample;
invalidate();
}
}
}