From 8601856cfafa888f6d46f7acf380b0a86355d38b Mon Sep 17 00:00:00 2001 From: Kurt Aaholst Date: Thu, 17 Oct 2024 23:13:11 +0200 Subject: [PATCH] Embed radial seek bar to remove dependy of JCenter artifact repository --- Squeezer/build.gradle | 3 - .../org/ngo/squeezer/NowPlayingFragment.java | 18 +- .../uk/org/ngo/squeezer/widget/Croller.java | 42 - .../widget/OnRadialSeekBarChangeListener.java | 9 + .../ngo/squeezer/widget/RadialSeekBar.java | 814 ++++++++++++++++++ .../src/main/res/layout/volume_adjust.xml | 2 +- Squeezer/src/main/res/values/seekbarattrs.xml | 40 + build.gradle | 4 +- 8 files changed, 875 insertions(+), 57 deletions(-) delete mode 100644 Squeezer/src/main/java/uk/org/ngo/squeezer/widget/Croller.java create mode 100644 Squeezer/src/main/java/uk/org/ngo/squeezer/widget/OnRadialSeekBarChangeListener.java create mode 100644 Squeezer/src/main/java/uk/org/ngo/squeezer/widget/RadialSeekBar.java create mode 100644 Squeezer/src/main/res/values/seekbarattrs.xml diff --git a/Squeezer/build.gradle b/Squeezer/build.gradle index e46c11dbc..26dfdeb9b 100644 --- a/Squeezer/build.gradle +++ b/Squeezer/build.gradle @@ -30,9 +30,6 @@ dependencies { // Changelogs, see https://github.com/cketti/ckChangeLog. implementation 'de.cketti.library.changelog:ckchangelog:1.2.0' - // Radial SeekBar - implementation 'com.sdsmdg.harjot:croller:1.0.7' - // Fastscroller implementation 'com.quiph.ui:recyclerviewfastscroller:1.0.0' diff --git a/Squeezer/src/main/java/uk/org/ngo/squeezer/NowPlayingFragment.java b/Squeezer/src/main/java/uk/org/ngo/squeezer/NowPlayingFragment.java index 57ded4394..5fbad461a 100644 --- a/Squeezer/src/main/java/uk/org/ngo/squeezer/NowPlayingFragment.java +++ b/Squeezer/src/main/java/uk/org/ngo/squeezer/NowPlayingFragment.java @@ -60,8 +60,6 @@ import com.google.android.material.button.MaterialButton; import com.google.android.material.dialog.MaterialAlertDialogBuilder; import com.google.android.material.slider.Slider; -import com.sdsmdg.harjot.crollerTest.Croller; -import com.sdsmdg.harjot.crollerTest.OnCrollerChangeListener; import org.greenrobot.eventbus.Subscribe; import org.greenrobot.eventbus.ThreadMode; @@ -107,9 +105,11 @@ import uk.org.ngo.squeezer.service.event.SongTimeChanged; import uk.org.ngo.squeezer.util.ImageFetcher; import uk.org.ngo.squeezer.widget.CallStatePermissionLauncher; +import uk.org.ngo.squeezer.widget.RadialSeekBar; +import uk.org.ngo.squeezer.widget.OnRadialSeekBarChangeListener; import uk.org.ngo.squeezer.widget.OnSwipeListener; -public class NowPlayingFragment extends Fragment implements OnCrollerChangeListener, CallStateDialog.CallStateDialogHost { +public class NowPlayingFragment extends Fragment implements OnRadialSeekBarChangeListener, CallStateDialog.CallStateDialogHost { private static final String TAG = "NowPlayingFragment"; @@ -188,7 +188,7 @@ public class NowPlayingFragment extends Fragment implements OnCrollerChangeList // For the small artwork layout private CheckBox muteToggle; - private Croller volumeWheel; + private RadialSeekBar volumeWheel; private int currentProgress = 0; private boolean trackingTouch; @@ -445,7 +445,7 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { mActivity.recreate(); }); - volumeWheel.setOnCrollerChangeListener(this); + volumeWheel.setOnRadialSeekBarChangeListener(this); muteToggle.setOnClickListener(view -> requireService().toggleMute()); v.findViewById(R.id.settings).setOnClickListener(view1 -> { @@ -900,7 +900,7 @@ private void updateVolumeInfo() { volumeWheel.setIndicatorColor(ColorUtils.setAlphaComponent(volumeWheel.getIndicatorColor(), volumeInfo.muted ? 63 : 255)); volumeWheel.setProgressPrimaryColor(ColorUtils.setAlphaComponent(volumeWheel.getProgressPrimaryColor(), volumeInfo.muted ? 63 : 255)); volumeWheel.setProgressSecondaryColor(ColorUtils.setAlphaComponent(volumeWheel.getProgressSecondaryColor(), volumeInfo.muted ? 63 : 255)); - volumeWheel.setOnCrollerChangeListener(volumeInfo.muted ? null : this); + volumeWheel.setOnRadialSeekBarChangeListener(volumeInfo.muted ? null : this); volumeWheel.setOnTouchListener(volumeInfo.muted ? (view, motionEvent) -> true : null); } } @@ -1272,7 +1272,7 @@ public void onEvent(PlayerVolume event) { } @Override - public void onProgressChanged(Croller croller, int progress) { + public void onProgressChanged(RadialSeekBar seekBar, int progress) { if (currentProgress != progress) { currentProgress = progress; volumeWheel.setLabel(String.valueOf(progress)); @@ -1281,12 +1281,12 @@ public void onProgressChanged(Croller croller, int progress) { } @Override - public void onStartTrackingTouch(Croller croller) { + public void onStartTrackingTouch(RadialSeekBar seekBar) { trackingTouch = true; } @Override - public void onStopTrackingTouch(Croller croller) { + public void onStopTrackingTouch(RadialSeekBar seekBar) { trackingTouch = false; } diff --git a/Squeezer/src/main/java/uk/org/ngo/squeezer/widget/Croller.java b/Squeezer/src/main/java/uk/org/ngo/squeezer/widget/Croller.java deleted file mode 100644 index a2144a402..000000000 --- a/Squeezer/src/main/java/uk/org/ngo/squeezer/widget/Croller.java +++ /dev/null @@ -1,42 +0,0 @@ -package uk.org.ngo.squeezer.widget; - -import android.content.Context; -import android.content.res.TypedArray; -import android.graphics.Canvas; -import android.util.AttributeSet; - -import uk.org.ngo.squeezer.R; - -public class Croller extends com.sdsmdg.harjot.crollerTest.Croller { - final int textSize; - - public Croller(Context context) { - super(context); - textSize = initTextSize(); - } - - public Croller(Context context, AttributeSet attrs) { - super(context, attrs); - textSize = initTextSize(); - } - - public Croller(Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - textSize = initTextSize(); - } - - private int initTextSize() { - int[] textSizeAttr = new int[] { android.R.attr.textSize }; - TypedArray a = getContext().obtainStyledAttributes(R.style.SqueezerTextAppearance_Medium, textSizeAttr); - int textSize = a.getDimensionPixelSize(0, -1); - a.recycle(); - return textSize; - } - - @Override - protected void onDraw(Canvas canvas) { - setIndicatorWidth((float) ((float) getWidth() / 64.0)); - setLabelSize(textSize); - super.onDraw(canvas); - } -} diff --git a/Squeezer/src/main/java/uk/org/ngo/squeezer/widget/OnRadialSeekBarChangeListener.java b/Squeezer/src/main/java/uk/org/ngo/squeezer/widget/OnRadialSeekBarChangeListener.java new file mode 100644 index 000000000..6551925aa --- /dev/null +++ b/Squeezer/src/main/java/uk/org/ngo/squeezer/widget/OnRadialSeekBarChangeListener.java @@ -0,0 +1,9 @@ +package uk.org.ngo.squeezer.widget; + +public interface OnRadialSeekBarChangeListener { + void onProgressChanged(RadialSeekBar seekBar, int progress); + + void onStartTrackingTouch(RadialSeekBar seekBar); + + void onStopTrackingTouch(RadialSeekBar seekBar); +} diff --git a/Squeezer/src/main/java/uk/org/ngo/squeezer/widget/RadialSeekBar.java b/Squeezer/src/main/java/uk/org/ngo/squeezer/widget/RadialSeekBar.java new file mode 100644 index 000000000..2f7b6c071 --- /dev/null +++ b/Squeezer/src/main/java/uk/org/ngo/squeezer/widget/RadialSeekBar.java @@ -0,0 +1,814 @@ +package uk.org.ngo.squeezer.widget; + +import android.content.Context; +import android.content.res.AssetManager; +import android.content.res.Resources; +import android.content.res.TypedArray; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.RectF; +import android.graphics.Typeface; +import android.util.AttributeSet; +import android.util.TypedValue; +import android.view.MotionEvent; +import android.view.View; + +import androidx.annotation.NonNull; + +import uk.org.ngo.squeezer.R; + +public class RadialSeekBar extends View { + + private float midx, midy; + private Paint textPaint, circlePaint, circlePaint2, linePaint; + private float deg = 3; + private float downdeg = 0; + + private boolean isContinuous = false; + + private int backCircleColor = Color.parseColor("#222222"); + private int mainCircleColor = Color.parseColor("#000000"); + private int indicatorColor = Color.parseColor("#FFA036"); + private int progressPrimaryColor = Color.parseColor("#FFA036"); + private int progressSecondaryColor = Color.parseColor("#111111"); + + private int backCircleDisabledColor = Color.parseColor("#82222222"); + private int mainCircleDisabledColor = Color.parseColor("#82000000"); + private int indicatorDisabledColor = Color.parseColor("#82FFA036"); + private int progressPrimaryDisabledColor = Color.parseColor("#82FFA036"); + private int progressSecondaryDisabledColor = Color.parseColor("#82111111"); + + private float progressPrimaryCircleSize = -1; + private float progressSecondaryCircleSize = -1; + + private float progressPrimaryStrokeWidth = 25; + private float progressSecondaryStrokeWidth = 10; + + private float mainCircleRadius = -1; + private float backCircleRadius = -1; + private float progressRadius = -1; + + private int max = 25; + private int min = 1; + + private String label = "Label"; + private String labelFont; + private int labelStyle = 0; + private int labelColor = Color.WHITE; + + private int labelDisabledColor = Color.BLACK; + + private int startOffset = 30; + private int sweepAngle = -1; + + private boolean isEnabled = true; + + private boolean isAntiClockwise = false; + + private boolean startEventSent = false; + + RectF oval; + + private onProgressChangedListener progressChangedListener; + private OnRadialSeekBarChangeListener seekBarChangeListener; + + public interface onProgressChangedListener { + void onProgressChanged(int progress); + } + + public void setOnProgressChangedListener(onProgressChangedListener mProgressChangeListener) { + this.progressChangedListener = mProgressChangeListener; + } + + public void setOnRadialSeekBarChangeListener(OnRadialSeekBarChangeListener onRadialSeekBarChangeListener) { + this.seekBarChangeListener = onRadialSeekBarChangeListener; + } + + public RadialSeekBar(Context context) { + super(context); + init(); + } + + public RadialSeekBar(Context context, AttributeSet attrs) { + super(context, attrs); + initXMLAttrs(context, attrs); + init(); + } + + public RadialSeekBar(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + initXMLAttrs(context, attrs); + init(); + } + + private void init() { + + textPaint = new Paint(); + textPaint.setAntiAlias(true); + textPaint.setStyle(Paint.Style.FILL); + textPaint.setFakeBoldText(true); + textPaint.setTextAlign(Paint.Align.CENTER); + + generateTypeface(); + + circlePaint = new Paint(); + circlePaint.setAntiAlias(true); + circlePaint.setStrokeWidth(progressSecondaryStrokeWidth); + circlePaint.setStyle(Paint.Style.FILL); + + circlePaint2 = new Paint(); + circlePaint2.setAntiAlias(true); + circlePaint2.setStrokeWidth(progressPrimaryStrokeWidth); + circlePaint2.setStyle(Paint.Style.FILL); + + linePaint = new Paint(); + linePaint.setAntiAlias(true); + + if (isEnabled) { + circlePaint2.setColor(progressPrimaryColor); + circlePaint.setColor(progressSecondaryColor); + linePaint.setColor(indicatorColor); + textPaint.setColor(labelColor); + } else { + circlePaint2.setColor(progressPrimaryDisabledColor); + circlePaint.setColor(progressSecondaryDisabledColor); + linePaint.setColor(indicatorDisabledColor); + textPaint.setColor(labelDisabledColor); + } + + oval = new RectF(); + } + + private int calcTextSize() { + int[] textSizeAttr = new int[] { android.R.attr.textSize }; + try (TypedArray a = getContext().obtainStyledAttributes(R.style.SqueezerTextAppearance_Medium, textSizeAttr)) { + return a.getDimensionPixelSize(0, -1); + } + } + + private void generateTypeface() { + Typeface plainLabel = Typeface.DEFAULT; + if (getLabelFont() != null && !getLabelFont().isEmpty()) { + AssetManager assetMgr = getContext().getAssets(); + plainLabel = Typeface.createFromAsset(assetMgr, getLabelFont()); + } + + switch (getLabelStyle()) { + case 0: + textPaint.setTypeface(plainLabel); + break; + case 1: + textPaint.setTypeface(Typeface.create(plainLabel, Typeface.BOLD)); + break; + case 2: + textPaint.setTypeface(Typeface.create(plainLabel, Typeface.ITALIC)); + break; + case 3: + textPaint.setTypeface(Typeface.create(plainLabel, Typeface.BOLD_ITALIC)); + break; + + } + + } + + private void initXMLAttrs(Context context, AttributeSet attrs) { + try (TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.RadialSeekBar)) { + setEnabled(a.getBoolean(R.styleable.RadialSeekBar_enabled, true)); + setProgress(a.getInt(R.styleable.RadialSeekBar_start_progress, 1)); + setLabel(a.getString(R.styleable.RadialSeekBar_label)); + + setBackCircleColor(a.getColor(R.styleable.RadialSeekBar_back_circle_color, backCircleColor)); + setMainCircleColor(a.getColor(R.styleable.RadialSeekBar_main_circle_color, mainCircleColor)); + setIndicatorColor(a.getColor(R.styleable.RadialSeekBar_indicator_color, indicatorColor)); + setProgressPrimaryColor(a.getColor(R.styleable.RadialSeekBar_progress_primary_color, progressPrimaryColor)); + setProgressSecondaryColor(a.getColor(R.styleable.RadialSeekBar_progress_secondary_color, progressSecondaryColor)); + + setBackCircleDisabledColor(a.getColor(R.styleable.RadialSeekBar_back_circle_disable_color, backCircleDisabledColor)); + setMainCircleDisabledColor(a.getColor(R.styleable.RadialSeekBar_main_circle_disable_color, mainCircleDisabledColor)); + setIndicatorDisabledColor(a.getColor(R.styleable.RadialSeekBar_indicator_disable_color, indicatorDisabledColor)); + setProgressPrimaryDisabledColor(a.getColor(R.styleable.RadialSeekBar_progress_primary_disable_color, progressPrimaryDisabledColor)); + setProgressSecondaryDisabledColor(a.getColor(R.styleable.RadialSeekBar_progress_secondary_disable_color, progressSecondaryDisabledColor)); + + setLabelColor(a.getColor(R.styleable.RadialSeekBar_label_color, labelColor)); + setlabelDisabledColor(a.getColor(R.styleable.RadialSeekBar_label_disabled_color, labelDisabledColor)); + setLabelFont(a.getString(R.styleable.RadialSeekBar_label_font)); + setLabelStyle(a.getInt(R.styleable.RadialSeekBar_label_style, 0)); + setIsContinuous(a.getBoolean(R.styleable.RadialSeekBar_is_continuous, false)); + setProgressPrimaryCircleSize(a.getFloat(R.styleable.RadialSeekBar_progress_primary_circle_size, -1)); + setProgressSecondaryCircleSize(a.getFloat(R.styleable.RadialSeekBar_progress_secondary_circle_size, -1)); + setProgressPrimaryStrokeWidth(a.getFloat(R.styleable.RadialSeekBar_progress_primary_stroke_width, 25)); + setProgressSecondaryStrokeWidth(a.getFloat(R.styleable.RadialSeekBar_progress_secondary_stroke_width, 10)); + setSweepAngle(a.getInt(R.styleable.RadialSeekBar_sweep_angle, -1)); + setStartOffset(a.getInt(R.styleable.RadialSeekBar_start_offset, 30)); + setMax(a.getInt(R.styleable.RadialSeekBar_max, 25)); + setMin(a.getInt(R.styleable.RadialSeekBar_min, 1)); + deg = min + 2; + setBackCircleRadius(a.getFloat(R.styleable.RadialSeekBar_back_circle_radius, -1)); + setProgressRadius(a.getFloat(R.styleable.RadialSeekBar_progress_radius, -1)); + setAntiClockwise(a.getBoolean(R.styleable.RadialSeekBar_anticlockwise, false)); + } + } + + private static float getDistance(float x1, float y1, float x2, float y2) { + return (float) Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)); + } + + private static int dpToPx(int dp, Context context) { + Resources r = context.getResources(); + return Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, r.getDisplayMetrics())); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + int minWidth = dpToPx(160, getContext()); + int minHeight = dpToPx(160, getContext()); + + int widthMode = MeasureSpec.getMode(widthMeasureSpec); + int widthSize = MeasureSpec.getSize(widthMeasureSpec); + int heightMode = MeasureSpec.getMode(heightMeasureSpec); + int heightSize = MeasureSpec.getSize(heightMeasureSpec); + + int width; + int height; + + if (widthMode == MeasureSpec.EXACTLY) { + width = widthSize; + } else if (widthMode == MeasureSpec.AT_MOST) { + width = Math.min(minWidth, widthSize); + } else { + // only in case of ScrollViews, otherwise MeasureSpec.UNSPECIFIED is never triggered + // If width is wrap_content i.e. MeasureSpec.UNSPECIFIED, then make width equal to height + width = heightSize; + } + + if (heightMode == MeasureSpec.EXACTLY) { + height = heightSize; + } else if (heightMode == MeasureSpec.AT_MOST) { + height = Math.min(minHeight, heightSize); + } else { + // only in case of ScrollViews, otherwise MeasureSpec.UNSPECIFIED is never triggered + // If height is wrap_content i.e. MeasureSpec.UNSPECIFIED, then make height equal to width + height = widthSize; + } + + if (widthMode == MeasureSpec.UNSPECIFIED && heightMode == MeasureSpec.UNSPECIFIED) { + width = minWidth; + height = minHeight; + } + + setMeasuredDimension(width, height); + } + + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + super.onLayout(changed, left, top, right, bottom); + + midx = (float) getWidth() / 2; + midy = (float) getHeight() / 2; + } + + @Override + protected void onDraw(@NonNull Canvas canvas) { + super.onDraw(canvas); + int textSize = calcTextSize(); + float indicatorWidth = (float) ((float) getWidth() / 64.0); + + if (progressChangedListener != null) + progressChangedListener.onProgressChanged((int) (deg - 2)); + + if (seekBarChangeListener != null) + seekBarChangeListener.onProgressChanged(this, (int) (deg - 2)); + + if (isEnabled) { + circlePaint2.setColor(progressPrimaryColor); + circlePaint.setColor(progressSecondaryColor); + linePaint.setColor(indicatorColor); + textPaint.setColor(labelColor); + } else { + circlePaint2.setColor(progressPrimaryDisabledColor); + circlePaint.setColor(progressSecondaryDisabledColor); + linePaint.setColor(indicatorDisabledColor); + textPaint.setColor(labelDisabledColor); + } + + if (!isContinuous) { + int startOffset2 = startOffset - 15; + + linePaint.setStrokeWidth(indicatorWidth); + textPaint.setTextSize(textSize); + + int radius = (int) (Math.min(midx, midy) * ((float) 14.5 / 16)); + + if (sweepAngle == -1) { + sweepAngle = 360 - (2 * startOffset2); + } + + if (mainCircleRadius == -1) { + mainCircleRadius = radius * ((float) 11 / 15); + } + if (backCircleRadius == -1) { + backCircleRadius = radius * ((float) 13 / 15); + } + if (progressRadius == -1) { + progressRadius = radius; + } + + float x, y; + float deg2 = Math.max(3, deg); + float deg3 = Math.min(deg, max + 2); + for (int i = (int) (deg2); i < max + 3; i++) { + float tmp = ((float) startOffset2 / 360) + ((float) sweepAngle / 360) * (float) i / (max + 5); + + if (isAntiClockwise) { + tmp = 1.0f - tmp; + } + + x = midx + (float) (progressRadius * Math.sin(2 * Math.PI * (1.0 - tmp))); + y = midy + (float) (progressRadius * Math.cos(2 * Math.PI * (1.0 - tmp))); + if (progressSecondaryCircleSize == -1) + canvas.drawCircle(x, y, ((float) radius / 30 * ((float) 20 / max) * ((float) sweepAngle / 270)), circlePaint); + else + canvas.drawCircle(x, y, progressSecondaryCircleSize, circlePaint); + } + for (int i = 3; i <= deg3; i++) { + float tmp = ((float) startOffset2 / 360) + ((float) sweepAngle / 360) * (float) i / (max + 5); + + if (isAntiClockwise) { + tmp = 1.0f - tmp; + } + + x = midx + (float) (progressRadius * Math.sin(2 * Math.PI * (1.0 - tmp))); + y = midy + (float) (progressRadius * Math.cos(2 * Math.PI * (1.0 - tmp))); + if (progressPrimaryCircleSize == -1) + canvas.drawCircle(x, y, (progressRadius / 15 * ((float) 20 / max) * ((float) sweepAngle / 270)), circlePaint2); + else + canvas.drawCircle(x, y, progressPrimaryCircleSize, circlePaint2); + } + + float tmp2 = ((float) startOffset2 / 360) + ((float) sweepAngle / 360) * deg / (max + 5); + + if (isAntiClockwise) { + tmp2 = 1.0f - tmp2; + } + + float x1 = midx + (float) (radius * ((float) 2 / 5) * Math.sin(2 * Math.PI * (1.0 - tmp2))); + float y1 = midy + (float) (radius * ((float) 2 / 5) * Math.cos(2 * Math.PI * (1.0 - tmp2))); + float x2 = midx + (float) (radius * ((float) 3 / 5) * Math.sin(2 * Math.PI * (1.0 - tmp2))); + float y2 = midy + (float) (radius * ((float) 3 / 5) * Math.cos(2 * Math.PI * (1.0 - tmp2))); + + if (isEnabled) + circlePaint.setColor(backCircleColor); + else + circlePaint.setColor(backCircleDisabledColor); + canvas.drawCircle(midx, midy, backCircleRadius, circlePaint); + if (isEnabled) + circlePaint.setColor(mainCircleColor); + else + circlePaint.setColor(mainCircleDisabledColor); + canvas.drawCircle(midx, midy, mainCircleRadius, circlePaint); + canvas.drawText(label, midx, midy + (float) (radius * 1.1)-textPaint.getFontMetrics().descent, textPaint); + canvas.drawLine(x1, y1, x2, y2, linePaint); + + } else { + + int radius = (int) (Math.min(midx, midy) * ((float) 14.5 / 16)); + + if (sweepAngle == -1) { + sweepAngle = 360 - (2 * startOffset); + } + + if (mainCircleRadius == -1) { + mainCircleRadius = radius * ((float) 11 / 15); + } + if (backCircleRadius == -1) { + backCircleRadius = radius * ((float) 13 / 15); + } + if (progressRadius == -1) { + progressRadius = radius; + } + + circlePaint.setStrokeWidth(progressSecondaryStrokeWidth); + circlePaint.setStyle(Paint.Style.STROKE); + circlePaint2.setStrokeWidth(progressPrimaryStrokeWidth); + circlePaint2.setStyle(Paint.Style.STROKE); + linePaint.setStrokeWidth(indicatorWidth); + textPaint.setTextSize(textSize); + + float deg3 = Math.min(deg, max + 2); + + oval.set(midx - progressRadius, midy - progressRadius, midx + progressRadius, midy + progressRadius); + + canvas.drawArc(oval, (float) 90 + startOffset, (float) sweepAngle, false, circlePaint); + if (isAntiClockwise) { + canvas.drawArc(oval, (float) 90 - startOffset, -1 * ((deg3 - 2) * ((float) sweepAngle / max)), false, circlePaint2); + } else { + canvas.drawArc(oval, (float) 90 + startOffset, ((deg3 - 2) * ((float) sweepAngle / max)), false, circlePaint2); + } + + float tmp2 = ((float) startOffset / 360) + (((float) sweepAngle / 360) * ((deg - 2) / (max))); + + if (isAntiClockwise) { + tmp2 = 1.0f - tmp2; + } + + float x1 = midx + (float) (radius * ((float) 2 / 5) * Math.sin(2 * Math.PI * (1.0 - tmp2))); + float y1 = midy + (float) (radius * ((float) 2 / 5) * Math.cos(2 * Math.PI * (1.0 - tmp2))); + float x2 = midx + (float) (radius * ((float) 3 / 5) * Math.sin(2 * Math.PI * (1.0 - tmp2))); + float y2 = midy + (float) (radius * ((float) 3 / 5) * Math.cos(2 * Math.PI * (1.0 - tmp2))); + + circlePaint.setStyle(Paint.Style.FILL); + + if (isEnabled) + circlePaint.setColor(backCircleColor); + else + circlePaint.setColor(backCircleDisabledColor); + canvas.drawCircle(midx, midy, backCircleRadius, circlePaint); + if (isEnabled) + circlePaint.setColor(mainCircleColor); + else + circlePaint.setColor(mainCircleDisabledColor); + canvas.drawCircle(midx, midy, mainCircleRadius, circlePaint); + canvas.drawText(label, midx, midy + (float) (radius * 1.1)-textPaint.getFontMetrics().descent, textPaint); + canvas.drawLine(x1, y1, x2, y2, linePaint); + } + } + + @Override + public boolean onTouchEvent(MotionEvent e) { + + if (!isEnabled) + return false; + + if (getDistance(e.getX(), e.getY(), midx, midy) > Math.max(mainCircleRadius, Math.max(backCircleRadius, progressRadius))) { + if (startEventSent && seekBarChangeListener != null) { + seekBarChangeListener.onStopTrackingTouch(this); + startEventSent = false; + } + return super.onTouchEvent(e); + } + + if (e.getAction() == MotionEvent.ACTION_DOWN) { + + float dx = e.getX() - midx; + float dy = e.getY() - midy; + downdeg = (float) ((Math.atan2(dy, dx) * 180) / Math.PI); + downdeg -= 90; + if (downdeg < 0) { + downdeg += 360; + } + downdeg = (float) Math.floor((downdeg / 360) * (max + 5)); + + if (seekBarChangeListener != null) { + seekBarChangeListener.onStartTrackingTouch(this); + startEventSent = true; + } + + return true; + } + if (e.getAction() == MotionEvent.ACTION_MOVE) { + float dx = e.getX() - midx; + float dy = e.getY() - midy; + float currdeg = (float) ((Math.atan2(dy, dx) * 180) / Math.PI); + currdeg -= 90; + if (currdeg < 0) { + currdeg += 360; + } + currdeg = (float) Math.floor((currdeg / 360) * (max + 5)); + + if ((currdeg / (max + 4)) > 0.75f && ((downdeg - 0) / (max + 4)) < 0.25f) { + if (isAntiClockwise) { + deg++; + if (deg > max + 2) { + deg = max + 2; + } + } else { + deg--; + if (deg < (min + 2)) { + deg = (min + 2); + } + } + } else if ((downdeg / (max + 4)) > 0.75f && ((currdeg - 0) / (max + 4)) < 0.25f) { + if (isAntiClockwise) { + deg--; + if (deg < (min + 2)) { + deg = (min + 2); + } + } else { + deg++; + if (deg > max + 2) { + deg = max + 2; + } + } + } else { + if (isAntiClockwise) { + deg -= (currdeg - downdeg); + } else { + deg += (currdeg - downdeg); + } + if (deg > max + 2) { + deg = max + 2; + } + if (deg < (min + 2)) { + deg = (min + 2); + } + } + + downdeg = currdeg; + + invalidate(); + return true; + + } + if (e.getAction() == MotionEvent.ACTION_UP) { + if (seekBarChangeListener != null) { + seekBarChangeListener.onStopTrackingTouch(this); + startEventSent = false; + } + return true; + } + return super.onTouchEvent(e); + } + + @Override + public boolean dispatchTouchEvent(MotionEvent event) { + if (getParent() != null && event.getAction() == MotionEvent.ACTION_DOWN) { + getParent().requestDisallowInterceptTouchEvent(true); + } + return super.dispatchTouchEvent(event); + } + + public boolean isEnabled() { + return isEnabled; + } + + public void setEnabled(boolean enabled) { + this.isEnabled = enabled; + invalidate(); + } + + public int getProgress() { + return (int) (deg - 2); + } + + public void setProgress(int x) { + deg = x + 2; + invalidate(); + } + + public String getLabel() { + return label; + } + + public void setLabel(String txt) { + label = txt; + invalidate(); + } + + public int getBackCircleColor() { + return backCircleColor; + } + + public void setBackCircleColor(int backCircleColor) { + this.backCircleColor = backCircleColor; + invalidate(); + } + + public int getMainCircleColor() { + return mainCircleColor; + } + + public void setMainCircleColor(int mainCircleColor) { + this.mainCircleColor = mainCircleColor; + invalidate(); + } + + public int getIndicatorColor() { + return indicatorColor; + } + + public void setIndicatorColor(int indicatorColor) { + this.indicatorColor = indicatorColor; + invalidate(); + } + + public int getProgressPrimaryColor() { + return progressPrimaryColor; + } + + public void setProgressPrimaryColor(int progressPrimaryColor) { + this.progressPrimaryColor = progressPrimaryColor; + invalidate(); + } + + public int getProgressSecondaryColor() { + return progressSecondaryColor; + } + + public void setProgressSecondaryColor(int progressSecondaryColor) { + this.progressSecondaryColor = progressSecondaryColor; + invalidate(); + } + + public int getBackCircleDisabledColor() { + return backCircleDisabledColor; + } + + public void setBackCircleDisabledColor(int backCircleDisabledColor) { + this.backCircleDisabledColor = backCircleDisabledColor; + invalidate(); + } + + public int getMainCircleDisabledColor() { + return mainCircleDisabledColor; + } + + public void setMainCircleDisabledColor(int mainCircleDisabledColor) { + this.mainCircleDisabledColor = mainCircleDisabledColor; + invalidate(); + } + + public int getIndicatorDisabledColor() { + return indicatorDisabledColor; + } + + public void setIndicatorDisabledColor(int indicatorDisabledColor) { + this.indicatorDisabledColor = indicatorDisabledColor; + invalidate(); + } + + public int getProgressPrimaryDisabledColor() { + return progressPrimaryDisabledColor; + } + + public void setProgressPrimaryDisabledColor(int progressPrimaryDisabledColor) { + this.progressPrimaryDisabledColor = progressPrimaryDisabledColor; + invalidate(); + } + + public int getProgressSecondaryDisabledColor() { + return progressSecondaryDisabledColor; + } + + public void setProgressSecondaryDisabledColor(int progressSecondaryDisabledColor) { + this.progressSecondaryDisabledColor = progressSecondaryDisabledColor; + invalidate(); + } + + public int getLabelColor() { + return labelColor; + } + + public void setLabelColor(int labelColor) { + this.labelColor = labelColor; + invalidate(); + } + + public int getlabelDisabledColor() { + return labelDisabledColor; + } + + public void setlabelDisabledColor(int labelDisabledColor) { + this.labelDisabledColor = labelDisabledColor; + invalidate(); + } + + public String getLabelFont() { + return labelFont; + } + + public void setLabelFont(String labelFont) { + this.labelFont = labelFont; + if (textPaint != null) + generateTypeface(); + invalidate(); + } + + public int getLabelStyle() { + return labelStyle; + } + + public void setLabelStyle(int labelStyle) { + this.labelStyle = labelStyle; + invalidate(); + } + + public boolean isContinuous() { + return isContinuous; + } + + public void setIsContinuous(boolean isContinuous) { + this.isContinuous = isContinuous; + invalidate(); + } + + public float getProgressPrimaryCircleSize() { + return progressPrimaryCircleSize; + } + + public void setProgressPrimaryCircleSize(float progressPrimaryCircleSize) { + this.progressPrimaryCircleSize = progressPrimaryCircleSize; + invalidate(); + } + + public float getProgressSecondaryCircleSize() { + return progressSecondaryCircleSize; + } + + public void setProgressSecondaryCircleSize(float progressSecondaryCircleSize) { + this.progressSecondaryCircleSize = progressSecondaryCircleSize; + invalidate(); + } + + public float getProgressPrimaryStrokeWidth() { + return progressPrimaryStrokeWidth; + } + + public void setProgressPrimaryStrokeWidth(float progressPrimaryStrokeWidth) { + this.progressPrimaryStrokeWidth = progressPrimaryStrokeWidth; + invalidate(); + } + + public float getProgressSecondaryStrokeWidth() { + return progressSecondaryStrokeWidth; + } + + public void setProgressSecondaryStrokeWidth(float progressSecondaryStrokeWidth) { + this.progressSecondaryStrokeWidth = progressSecondaryStrokeWidth; + invalidate(); + } + + public int getSweepAngle() { + return sweepAngle; + } + + public void setSweepAngle(int sweepAngle) { + this.sweepAngle = sweepAngle; + invalidate(); + } + + public int getStartOffset() { + return startOffset; + } + + public void setStartOffset(int startOffset) { + this.startOffset = startOffset; + invalidate(); + } + + public int getMax() { + return max; + } + + public void setMax(int max) { + this.max = Math.max(max, min); + invalidate(); + } + + public int getMin() { + return min; + } + + public void setMin(int min) { + this.min = min < 0 ? 0 : Math.min(min, max); + invalidate(); + } + + public float getMainCircleRadius() { + return mainCircleRadius; + } + + public void setMainCircleRadius(float mainCircleRadius) { + this.mainCircleRadius = mainCircleRadius; + invalidate(); + } + + public float getBackCircleRadius() { + return backCircleRadius; + } + + public void setBackCircleRadius(float backCircleRadius) { + this.backCircleRadius = backCircleRadius; + invalidate(); + } + + public float getProgressRadius() { + return progressRadius; + } + + public void setProgressRadius(float progressRadius) { + this.progressRadius = progressRadius; + invalidate(); + } + + public boolean isAntiClockwise() { + return isAntiClockwise; + } + + public void setAntiClockwise(boolean antiClockwise) { + isAntiClockwise = antiClockwise; + invalidate(); + } +} + diff --git a/Squeezer/src/main/res/layout/volume_adjust.xml b/Squeezer/src/main/res/layout/volume_adjust.xml index 3dca7cc7a..0aebc341f 100644 --- a/Squeezer/src/main/res/layout/volume_adjust.xml +++ b/Squeezer/src/main/res/layout/volume_adjust.xml @@ -58,7 +58,7 @@ app:layout_constraintStart_toStartOf="parent" app:icon="@drawable/ic_settings"/> - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/build.gradle b/build.gradle index 1fba4b9a8..84d88e355 100644 --- a/build.gradle +++ b/build.gradle @@ -1,7 +1,7 @@ allprojects { repositories { google() - jcenter() + mavenCentral() } tasks.withType(Javadoc) { // Disable lint, due to issues in the EventBus code comments. @@ -13,7 +13,7 @@ allprojects { buildscript { repositories { google() - jcenter() + mavenCentral() } dependencies { classpath 'com.android.tools.build:gradle:8.5.0'