Converted Java View classes to Kotlin

This commit is contained in:
Prathamesh More 2022-04-13 00:04:36 +05:30
parent ad90694879
commit a4d44406d6
18 changed files with 274 additions and 994 deletions

View file

@ -1,38 +0,0 @@
package code.name.monkey.retromusic;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.LocaleList;
import com.google.android.gms.common.annotation.KeepName;
import java.util.Locale;
import code.name.monkey.appthemehelper.util.VersionUtils;
public class LanguageContextWrapper extends ContextWrapper {
public LanguageContextWrapper(Context base) {
super(base);
}
@KeepName
public static LanguageContextWrapper wrap(Context context, Locale newLocale) {
Resources res = context.getResources();
Configuration configuration = res.getConfiguration();
if (VersionUtils.INSTANCE.hasNougatMR()) {
configuration.setLocale(newLocale);
LocaleList localeList = new LocaleList(newLocale);
LocaleList.setDefault(localeList);
configuration.setLocales(localeList);
} else {
configuration.setLocale(newLocale);
}
context = context.createConfigurationContext(configuration);
return new LanguageContextWrapper(context);
}
}

View file

@ -0,0 +1,27 @@
package code.name.monkey.retromusic
import android.content.Context
import android.content.ContextWrapper
import android.os.LocaleList
import code.name.monkey.appthemehelper.util.VersionUtils.hasNougatMR
import com.google.android.gms.common.annotation.KeepName
import java.util.*
class LanguageContextWrapper(base: Context?) : ContextWrapper(base) {
companion object {
@KeepName
fun wrap(context: Context?, newLocale: Locale?): LanguageContextWrapper {
if (context == null) return LanguageContextWrapper(context)
val configuration = context.resources.configuration
if (hasNougatMR()) {
configuration.setLocale(newLocale)
val localeList = LocaleList(newLocale)
LocaleList.setDefault(localeList)
configuration.setLocales(localeList)
} else {
configuration.setLocale(newLocale)
}
return LanguageContextWrapper(context.createConfigurationContext(configuration))
}
}
}

View file

@ -88,13 +88,14 @@ private val roomModule = module {
}
private val autoModule = module {
single {
AutoMusicProvider(androidContext(),
get(),
get(),
get(),
get(),
get(),
get()
AutoMusicProvider(
androidContext(),
get(),
get(),
get(),
get(),
get(),
get()
)
}
}

View file

@ -1,79 +0,0 @@
/*
* Copyright (c) 2019 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 static code.name.monkey.retromusic.util.RetroUtil.openUrl;
import android.app.Activity;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import code.name.monkey.retromusic.R;
public class ContributorsView extends FrameLayout {
public ContributorsView(@NonNull Context context) {
super(context);
init(context, null);
}
public ContributorsView(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public ContributorsView(
@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}
private void init(Context context, AttributeSet attributeSet) {
final TypedArray attributes =
context.obtainStyledAttributes(attributeSet, R.styleable.ContributorsView, 0, 0);
if (attributes != null) {
final View layout = LayoutInflater.from(context).inflate(R.layout.item_contributor, this);
NetworkImageView networkImageView = layout.findViewById(R.id.image);
String url = attributes.getString(R.styleable.ContributorsView_profile_url);
networkImageView.setImageUrl(url);
String name = attributes.getString(R.styleable.ContributorsView_profile_name);
TextView title = layout.findViewById(R.id.title);
title.setText(name);
String summary = attributes.getString(R.styleable.ContributorsView_profile_summary);
TextView text = layout.findViewById(R.id.text);
text.setText(summary);
String link = attributes.getString(R.styleable.ContributorsView_profile_link);
layout.setOnClickListener(
v -> {
if (link == null) {
return;
}
openUrl((Activity) getContext(), link);
});
attributes.recycle();
}
}
}

View file

@ -1,53 +0,0 @@
/*
* Copyright (c) 2019 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.annotation.TargetApi;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.FrameLayout;
public class HeightFitSquareLayout extends FrameLayout {
private boolean forceSquare = true;
public HeightFitSquareLayout(Context context) {
super(context);
}
public HeightFitSquareLayout(Context context, AttributeSet attributeSet) {
super(context, attributeSet);
}
public HeightFitSquareLayout(Context context, AttributeSet attributeSet, int i) {
super(context, attributeSet, i);
}
@TargetApi(21)
public HeightFitSquareLayout(Context context, AttributeSet attributeSet, int i, int i2) {
super(context, attributeSet, i, i2);
}
public void forceSquare(boolean z) {
this.forceSquare = z;
requestLayout();
}
protected void onMeasure(int i, int i2) {
if (this.forceSquare) {
i = i2;
}
super.onMeasure(i, i2);
}
}

View file

@ -0,0 +1,39 @@
/*
* Copyright (c) 2019 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.util.AttributeSet
import android.widget.FrameLayout
class HeightFitSquareLayout @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = -1
) : FrameLayout(context, attrs, defStyleAttr){
private var forceSquare = true
fun setForceSquare(forceSquare: Boolean) {
this.forceSquare = forceSquare
requestLayout()
}
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
var i = widthMeasureSpec
if (forceSquare) {
i = heightMeasureSpec
}
super.onMeasure(i, heightMeasureSpec)
}
}

View file

@ -27,29 +27,16 @@ import code.name.monkey.retromusic.extensions.show
/**
* Created by hemanths on 2019-10-02.
*/
class ListItemView : FrameLayout {
class ListItemView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = -1
) : FrameLayout(context, attrs, defStyleAttr) {
private lateinit var binding: ListItemViewNoCardBinding
constructor(context: Context) : super(context) {
init(context, null)
}
constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
init(context, attrs)
}
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(
context,
attrs,
defStyleAttr
) {
init(context, attrs)
}
private fun init(context: Context, attrs: AttributeSet?) {
binding = ListItemViewNoCardBinding.inflate(LayoutInflater.from(context), this, true)
private var binding =
ListItemViewNoCardBinding.inflate(LayoutInflater.from(context), this, true)
init {
context.withStyledAttributes(attrs, R.styleable.ListItemView) {
if (hasValue(R.styleable.ListItemView_listItemIcon)) {
binding.icon.setImageDrawable(getDrawable(R.styleable.ListItemView_listItemIcon))

View file

@ -1,51 +0,0 @@
/*
* Copyright (c) 2019 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.annotation.TargetApi;
import android.content.Context;
import android.content.res.Configuration;
import android.os.Build;
import android.util.AttributeSet;
import android.webkit.WebView;
public class LollipopFixedWebView extends WebView {
public LollipopFixedWebView(Context context) {
super(getFixedContext(context));
}
public LollipopFixedWebView(Context context, AttributeSet attrs) {
super(getFixedContext(context), attrs);
}
public LollipopFixedWebView(Context context, AttributeSet attrs, int defStyleAttr) {
super(getFixedContext(context), attrs, defStyleAttr);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public LollipopFixedWebView(
Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(getFixedContext(context), attrs, defStyleAttr, defStyleRes);
}
public LollipopFixedWebView(
Context context, AttributeSet attrs, int defStyleAttr, boolean privateBrowsing) {
super(getFixedContext(context), attrs, defStyleAttr, privateBrowsing);
}
public static Context getFixedContext(Context context) {
return context.createConfigurationContext(new Configuration());
}
}

View file

@ -0,0 +1,32 @@
/*
* Copyright (c) 2019 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.Configuration
import android.util.AttributeSet
import android.webkit.WebView
class LollipopFixedWebView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = -1
) : WebView(getFixedContext(context), attrs, defStyleAttr){
companion object {
fun getFixedContext(context: Context): Context {
return context.createConfigurationContext(Configuration())
}
}
}

View file

@ -1,66 +0,0 @@
/*
* Copyright (c) 2019 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.TypedArray;
import android.util.AttributeSet;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.bumptech.glide.Glide;
import code.name.monkey.retromusic.R;
/** @author Hemanth S (h4h13). */
public class NetworkImageView extends CircularImageView {
public NetworkImageView(@NonNull Context context) {
super(context);
init(context, null);
}
public NetworkImageView(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public NetworkImageView(
@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}
public void setImageUrl(@NonNull String imageUrl) {
setImageUrl(getContext(), imageUrl);
}
public void setImageUrl(@NonNull Context context, @NonNull String imageUrl) {
Glide.with(context)
.load(imageUrl)
.error(R.drawable.ic_account)
.placeholder(R.drawable.ic_account)
.into(this);
}
private void init(Context context, AttributeSet attributeSet) {
TypedArray attributes =
context.obtainStyledAttributes(attributeSet, R.styleable.NetworkImageView, 0, 0);
String url = attributes.getString(R.styleable.NetworkImageView_url_link);
setImageUrl(context, url);
attributes.recycle();
}
}

View file

@ -0,0 +1,57 @@
/*
* Copyright (c) 2019 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.util.AttributeSet
import code.name.monkey.retromusic.R
import com.bumptech.glide.Glide
/** @author Hemanth S (h4h13).
*/
class NetworkImageView : CircularImageView {
constructor(context: Context) : super(context) {
init(context, null)
}
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) {
init(context, attrs)
}
constructor(
context: Context, attrs: AttributeSet?, defStyleAttr: Int
) : super(context, attrs, defStyleAttr) {
init(context, attrs)
}
fun setImageUrl(imageUrl: String) {
setImageUrl(context, imageUrl)
}
private fun setImageUrl(context: Context, imageUrl: String) {
Glide.with(context)
.load(imageUrl)
.error(R.drawable.ic_account)
.placeholder(R.drawable.ic_account)
.into(this)
}
private fun init(context: Context, attributeSet: AttributeSet?) {
val attributes =
context.obtainStyledAttributes(attributeSet, R.styleable.NetworkImageView, 0, 0)
val url = attributes.getString(R.styleable.NetworkImageView_url_link)
setImageUrl(context, url!!)
attributes.recycle()
}
}

View file

@ -44,6 +44,6 @@ class PermissionItem @JvmOverloads constructor(
}
fun setButtonClick(callBack: () -> Unit) {
binding.button.setOnClickListener { callBack.invoke() }
binding.button.setOnClickListener { callBack() }
}
}

View file

@ -1,509 +0,0 @@
/*
* 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.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import code.name.monkey.retromusic.R;
/**
* SeekArc.java
*
* <p>This is a class that functions much like a SeekBar but follows a circle path instead of a
* straight line.
*
* @author Neil Davies
*/
public class SeekArc extends View {
private static final String TAG = SeekArc.class.getSimpleName();
private static final int INVALID_PROGRESS_VALUE = -1;
private Paint mArcPaint;
// Internal variables
private int mArcRadius = 0;
private final RectF mArcRect = new RectF();
/**
* The Width of the background arc for the SeekArc
*/
private int mArcWidth = 2;
/** Will the progress increase clockwise or anti-clockwise */
private boolean mClockwise = true;
/** is the control enabled/touchable */
private boolean mEnabled = true;
/** The Maximum value that this SeekArc can be set to */
private int mMax = 100;
private OnSeekArcChangeListener mOnSeekArcChangeListener;
/** The Current value that the SeekArc is set to */
private int mProgress = 0;
private Paint mProgressPaint;
private float mProgressSweep = 0;
/** The width of the progress line for this SeekArc */
private int mProgressWidth = 4;
/** The rotation of the SeekArc- 0 is twelve o'clock */
private int mRotation = 0;
/** Give the SeekArc rounded edges */
private boolean mRoundedEdges = false;
/** The Angle to start drawing this Arc from */
private int mStartAngle = 0;
/** The Angle through which to draw the arc (Max is 360) */
private int mSweepAngle = 360;
/** The Drawable for the seek arc thumbnail */
private Drawable mThumb;
private int mThumbXPos;
private int mThumbYPos;
private float mTouchIgnoreRadius;
/** Enable touch inside the SeekArc */
private boolean mTouchInside = true;
private int mTranslateX;
private int mTranslateY;
public SeekArc(Context context) {
super(context);
init(context, null, 0);
}
public SeekArc(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs, R.attr.seekArcStyle);
}
public SeekArc(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context, attrs, defStyle);
}
public int getArcColor() {
return mArcPaint.getColor();
}
public void setArcColor(int color) {
mArcPaint.setColor(color);
invalidate();
}
public int getArcRotation() {
return mRotation;
}
public void setArcRotation(int mRotation) {
this.mRotation = mRotation;
updateThumbPosition();
}
public int getArcWidth() {
return mArcWidth;
}
public void setArcWidth(int mArcWidth) {
this.mArcWidth = mArcWidth;
mArcPaint.setStrokeWidth(mArcWidth);
}
public int getMax() {
return mMax;
}
public void setMax(int mMax) {
this.mMax = mMax;
}
public int getProgress() {
return mProgress;
}
public void setProgress(int progress) {
updateProgress(progress, false);
}
public int getProgressColor() {
return mProgressPaint.getColor();
}
public void setProgressColor(int color) {
mProgressPaint.setColor(color);
invalidate();
}
public int getProgressWidth() {
return mProgressWidth;
}
public void setProgressWidth(int mProgressWidth) {
this.mProgressWidth = mProgressWidth;
mProgressPaint.setStrokeWidth(mProgressWidth);
}
public int getStartAngle() {
return mStartAngle;
}
public void setStartAngle(int mStartAngle) {
this.mStartAngle = mStartAngle;
updateThumbPosition();
}
public int getSweepAngle() {
return mSweepAngle;
}
public void setSweepAngle(int mSweepAngle) {
this.mSweepAngle = mSweepAngle;
updateThumbPosition();
}
public boolean isClockwise() {
return mClockwise;
}
public void setClockwise(boolean isClockwise) {
mClockwise = isClockwise;
}
public boolean isEnabled() {
return mEnabled;
}
public void setEnabled(boolean enabled) {
this.mEnabled = enabled;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (mEnabled) {
this.getParent().requestDisallowInterceptTouchEvent(true);
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
onStartTrackingTouch();
updateOnTouch(event);
break;
case MotionEvent.ACTION_MOVE:
updateOnTouch(event);
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
onStopTrackingTouch();
setPressed(false);
this.getParent().requestDisallowInterceptTouchEvent(false);
break;
}
return true;
}
return false;
}
/**
* Sets a listener to receive notifications of changes to the SeekArc's progress level. Also
* provides notifications of when the user starts and stops a touch gesture within the SeekArc.
*
* @param l The seek bar notification listener
* @see SeekArc.OnSeekArcChangeListener
*/
public void setOnSeekArcChangeListener(OnSeekArcChangeListener l) {
mOnSeekArcChangeListener = l;
}
public void setRoundedEdges(boolean isEnabled) {
mRoundedEdges = isEnabled;
if (mRoundedEdges) {
mArcPaint.setStrokeCap(Paint.Cap.ROUND);
mProgressPaint.setStrokeCap(Paint.Cap.ROUND);
} else {
mArcPaint.setStrokeCap(Paint.Cap.SQUARE);
mProgressPaint.setStrokeCap(Paint.Cap.SQUARE);
}
}
public void setTouchInSide(boolean isEnabled) {
int thumbHalfheight = mThumb.getIntrinsicHeight() / 2;
int thumbHalfWidth = mThumb.getIntrinsicWidth() / 2;
mTouchInside = isEnabled;
if (mTouchInside) {
mTouchIgnoreRadius = (float) mArcRadius / 4;
} else {
// Don't use the exact radius makes interaction too tricky
mTouchIgnoreRadius = mArcRadius - Math.min(thumbHalfWidth, thumbHalfheight);
}
}
@Override
protected void drawableStateChanged() {
super.drawableStateChanged();
if (mThumb != null && mThumb.isStateful()) {
int[] state = getDrawableState();
mThumb.setState(state);
}
invalidate();
}
@Override
protected void onDraw(Canvas canvas) {
if (!mClockwise) {
canvas.scale(-1, 1, mArcRect.centerX(), mArcRect.centerY());
}
// Draw the arcs
// The initial rotational offset -90 means we start at 12 o'clock
int mAngleOffset = -90;
final int arcStart = mStartAngle + mAngleOffset + mRotation;
final int arcSweep = mSweepAngle;
canvas.drawArc(mArcRect, arcStart, arcSweep, false, mArcPaint);
canvas.drawArc(mArcRect, arcStart, mProgressSweep, false, mProgressPaint);
if (mEnabled) {
// Draw the thumb nail
canvas.translate(mTranslateX - mThumbXPos, mTranslateY - mThumbYPos);
mThumb.draw(canvas);
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
final int height = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec);
final int width = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);
final int min = Math.min(width, height);
float top = 0;
float left = 0;
int arcDiameter = 0;
mTranslateX = (int) (width * 0.5f);
mTranslateY = (int) (height * 0.5f);
arcDiameter = min - getPaddingLeft();
mArcRadius = arcDiameter / 2;
top = height / 2 - (arcDiameter / 2);
left = width / 2 - (arcDiameter / 2);
mArcRect.set(left, top, left + arcDiameter, top + arcDiameter);
int arcStart = (int) mProgressSweep + mStartAngle + mRotation + 90;
mThumbXPos = (int) (mArcRadius * Math.cos(Math.toRadians(arcStart)));
mThumbYPos = (int) (mArcRadius * Math.sin(Math.toRadians(arcStart)));
setTouchInSide(mTouchInside);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
private int getProgressForAngle(double angle) {
int touchProgress = (int) Math.round(valuePerDegree() * angle);
touchProgress = (touchProgress < 0) ? INVALID_PROGRESS_VALUE : touchProgress;
touchProgress = (touchProgress > mMax) ? INVALID_PROGRESS_VALUE : touchProgress;
return touchProgress;
}
private double getTouchDegrees(float xPos, float yPos) {
float x = xPos - mTranslateX;
float y = yPos - mTranslateY;
// invert the x-coord if we are rotating anti-clockwise
x = (mClockwise) ? x : -x;
// convert to arc Angle
double angle = Math.toDegrees(Math.atan2(y, x) + (Math.PI / 2) - Math.toRadians(mRotation));
if (angle < 0) {
angle = 360 + angle;
}
angle -= mStartAngle;
return angle;
}
private boolean ignoreTouch(float xPos, float yPos) {
boolean ignore = false;
float x = xPos - mTranslateX;
float y = yPos - mTranslateY;
float touchRadius = (float) Math.sqrt(((x * x) + (y * y)));
if (touchRadius < mTouchIgnoreRadius) {
ignore = true;
}
return ignore;
}
private void init(Context context, AttributeSet attrs, int defStyle) {
Log.d(TAG, "Initialising SeekArc");
final Resources res = getResources();
float density = context.getResources().getDisplayMetrics().density;
// Defaults, may need to link this into theme settings
int arcColor = res.getColor(R.color.progress_gray);
int progressColor = res.getColor(R.color.default_blue_light);
int thumbHalfheight = 0;
int thumbHalfWidth = 0;
mThumb = res.getDrawable(R.drawable.switch_thumb_material);
// Convert progress width to pixels for current density
mProgressWidth = (int) (mProgressWidth * density);
if (attrs != null) {
// Attribute initialization
final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SeekArc, defStyle, 0);
Drawable thumb = a.getDrawable(R.styleable.SeekArc_thumb);
if (thumb != null) {
mThumb = thumb;
}
thumbHalfheight = mThumb.getIntrinsicHeight() / 2;
thumbHalfWidth = mThumb.getIntrinsicWidth() / 2;
mThumb.setBounds(-thumbHalfWidth, -thumbHalfheight, thumbHalfWidth, thumbHalfheight);
mMax = a.getInteger(R.styleable.SeekArc_max, mMax);
mProgress = a.getInteger(R.styleable.SeekArc_seekProgress, mProgress);
mProgressWidth = (int) a.getDimension(R.styleable.SeekArc_progressWidth, mProgressWidth);
mArcWidth = (int) a.getDimension(R.styleable.SeekArc_arcWidth, mArcWidth);
mStartAngle = a.getInt(R.styleable.SeekArc_startAngle, mStartAngle);
mSweepAngle = a.getInt(R.styleable.SeekArc_sweepAngle, mSweepAngle);
mRotation = a.getInt(R.styleable.SeekArc_rotation, mRotation);
mRoundedEdges = a.getBoolean(R.styleable.SeekArc_roundEdges, mRoundedEdges);
mTouchInside = a.getBoolean(R.styleable.SeekArc_touchInside, mTouchInside);
mClockwise = a.getBoolean(R.styleable.SeekArc_clockwise, mClockwise);
mEnabled = a.getBoolean(R.styleable.SeekArc_enabled, mEnabled);
arcColor = a.getColor(R.styleable.SeekArc_arcColor, arcColor);
progressColor = a.getColor(R.styleable.SeekArc_progressColor, progressColor);
a.recycle();
}
mProgress = Math.min(mProgress, mMax);
mProgress = Math.max(mProgress, 0);
mSweepAngle = Math.min(mSweepAngle, 360);
mSweepAngle = Math.max(mSweepAngle, 0);
mProgressSweep = (float) mProgress / mMax * mSweepAngle;
mStartAngle = (mStartAngle > 360) ? 0 : mStartAngle;
mStartAngle = Math.max(mStartAngle, 0);
mArcPaint = new Paint();
mArcPaint.setColor(arcColor);
mArcPaint.setAntiAlias(true);
mArcPaint.setStyle(Paint.Style.STROKE);
mArcPaint.setStrokeWidth(mArcWidth);
// mArcPaint.setAlpha(45);
mProgressPaint = new Paint();
mProgressPaint.setColor(progressColor);
mProgressPaint.setAntiAlias(true);
mProgressPaint.setStyle(Paint.Style.STROKE);
mProgressPaint.setStrokeWidth(mProgressWidth);
if (mRoundedEdges) {
mArcPaint.setStrokeCap(Paint.Cap.ROUND);
mProgressPaint.setStrokeCap(Paint.Cap.ROUND);
}
}
private void onProgressRefresh(int progress, boolean fromUser) {
updateProgress(progress, fromUser);
}
private void onStartTrackingTouch() {
if (mOnSeekArcChangeListener != null) {
mOnSeekArcChangeListener.onStartTrackingTouch(this);
}
}
private void onStopTrackingTouch() {
if (mOnSeekArcChangeListener != null) {
mOnSeekArcChangeListener.onStopTrackingTouch(this);
}
}
private void updateOnTouch(MotionEvent event) {
boolean ignoreTouch = ignoreTouch(event.getX(), event.getY());
if (ignoreTouch) {
return;
}
setPressed(true);
double mTouchAngle = getTouchDegrees(event.getX(), event.getY());
int progress = getProgressForAngle(mTouchAngle);
onProgressRefresh(progress, true);
}
private void updateProgress(int progress, boolean fromUser) {
if (progress == INVALID_PROGRESS_VALUE) {
return;
}
progress = Math.min(progress, mMax);
progress = Math.max(progress, 0);
mProgress = progress;
if (mOnSeekArcChangeListener != null) {
mOnSeekArcChangeListener.onProgressChanged(this, progress, fromUser);
}
mProgressSweep = (float) progress / mMax * mSweepAngle;
updateThumbPosition();
invalidate();
}
private void updateThumbPosition() {
int thumbAngle = (int) (mStartAngle + mProgressSweep + mRotation + 90);
mThumbXPos = (int) (mArcRadius * Math.cos(Math.toRadians(thumbAngle)));
mThumbYPos = (int) (mArcRadius * Math.sin(Math.toRadians(thumbAngle)));
}
private float valuePerDegree() {
return (float) mMax / mSweepAngle;
}
public interface OnSeekArcChangeListener {
/**
* Notification that the progress level has changed. Clients can use the fromUser parameter to
* distinguish user-initiated changes from those that occurred programmatically.
*
* @param seekArc The SeekArc whose progress has changed
* @param progress The current progress level. This will be in the range 0..max where max was
* set by {@link ProgressArc#setMax(int)}. (The default value for max is 100.)
* @param fromUser True if the progress change was initiated by the user.
*/
void onProgressChanged(SeekArc seekArc, int progress, boolean fromUser);
/**
* Notification that the user has started a touch gesture. Clients may want to use this to
* disable advancing the seekbar.
*
* @param seekArc The SeekArc in which the touch gesture began
*/
void onStartTrackingTouch(SeekArc seekArc);
/**
* Notification that the user has finished a touch gesture. Clients may want to use this to
* re-enable advancing the seekarc.
*
* @param seekArc The SeekArc in which the touch gesture began
*/
void onStopTrackingTouch(SeekArc seekArc);
}
}

View file

@ -1,48 +0,0 @@
/*
* Copyright (c) 2019 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.util.AttributeSet;
import android.view.WindowInsets;
import android.widget.FrameLayout;
import androidx.annotation.NonNull;
public class StatusBarMarginFrameLayout extends FrameLayout {
public StatusBarMarginFrameLayout(@NonNull Context context) {
super(context);
}
public StatusBarMarginFrameLayout(@NonNull Context context, @NonNull AttributeSet attrs) {
super(context, attrs);
}
public StatusBarMarginFrameLayout(
@NonNull Context context, @NonNull AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@NonNull
@Override
public WindowInsets onApplyWindowInsets(@NonNull WindowInsets insets) {
MarginLayoutParams lp = (MarginLayoutParams) getLayoutParams();
lp.topMargin = insets.getSystemWindowInsetTop();
lp.bottomMargin = insets.getSystemWindowInsetBottom();
setLayoutParams(lp);
return super.onApplyWindowInsets(insets);
}
}

View file

@ -1,56 +0,0 @@
/*
* Copyright (c) 2019 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.util.AttributeSet;
import android.view.View;
import androidx.annotation.NonNull;
public class StatusBarView extends View {
public StatusBarView(@NonNull Context context) {
super(context);
init(context);
}
public StatusBarView(@NonNull Context context, @NonNull AttributeSet attrs) {
super(context, attrs);
init(context);
}
public StatusBarView(@NonNull Context context, @NonNull AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
public static int getStatusBarHeight(@NonNull Resources r) {
int result = 0;
int resourceId = r.getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
result = r.getDimensionPixelSize(resourceId);
}
return result;
}
private void init(Context context) {}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), getStatusBarHeight(getResources()));
}
}

View file

@ -0,0 +1,45 @@
/*
* Copyright (c) 2019 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.util.AttributeSet
import android.view.View
class StatusBarView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = -1
) : View(context, attrs, defStyleAttr) {
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
setMeasuredDimension(
MeasureSpec.getSize(widthMeasureSpec), getStatusBarHeight(
resources
)
)
}
companion object {
fun getStatusBarHeight(r: Resources): Int {
var result = 0
val resourceId = r.getIdentifier("status_bar_height", "dimen", "android")
if (resourceId > 0) {
result = r.getDimensionPixelSize(resourceId)
}
return result
}
}
}

View file

@ -1,65 +0,0 @@
/*
* Copyright (c) 2019 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.graphics.Canvas;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.view.Gravity;
import androidx.appcompat.widget.AppCompatTextView;
public class VerticalTextView extends AppCompatTextView {
final boolean topDown;
public VerticalTextView(Context context, AttributeSet attrs) {
super(context, attrs);
final int gravity = getGravity();
if (Gravity.isVertical(gravity)
&& (gravity & Gravity.VERTICAL_GRAVITY_MASK) == Gravity.BOTTOM) {
setGravity((gravity & Gravity.HORIZONTAL_GRAVITY_MASK) | Gravity.TOP);
topDown = false;
} else topDown = true;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(heightMeasureSpec, widthMeasureSpec);
setMeasuredDimension(getMeasuredHeight(), getMeasuredWidth());
}
@Override
protected void onDraw(Canvas canvas) {
TextPaint textPaint = getPaint();
textPaint.setColor(getCurrentTextColor());
textPaint.drawableState = getDrawableState();
canvas.save();
if (topDown) {
canvas.translate(getWidth(), 0);
canvas.rotate(90);
} else {
canvas.translate(0, getHeight());
canvas.rotate(-90);
}
canvas.translate(getCompoundPaddingLeft(), getExtendedPaddingTop());
getLayout().draw(canvas);
canvas.restore();
}
}

View file

@ -0,0 +1,57 @@
/*
* Copyright (c) 2019 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.graphics.Canvas
import android.util.AttributeSet
import android.view.Gravity
import androidx.appcompat.widget.AppCompatTextView
class VerticalTextView(context: Context, attrs: AttributeSet?) : AppCompatTextView(
context, attrs
) {
private var topDown = false
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
super.onMeasure(heightMeasureSpec, widthMeasureSpec)
setMeasuredDimension(measuredHeight, measuredWidth)
}
override fun onDraw(canvas: Canvas) {
val textPaint = paint
textPaint.color = currentTextColor
textPaint.drawableState = drawableState
canvas.save()
if (topDown) {
canvas.translate(width.toFloat(), 0f)
canvas.rotate(90f)
} else {
canvas.translate(0f, height.toFloat())
canvas.rotate(-90f)
}
canvas.translate(compoundPaddingLeft.toFloat(), extendedPaddingTop.toFloat())
layout.draw(canvas)
canvas.restore()
}
init {
val gravity = gravity
topDown = if (Gravity.isVertical(gravity)
&& gravity and Gravity.VERTICAL_GRAVITY_MASK == Gravity.BOTTOM
) {
setGravity(gravity and Gravity.HORIZONTAL_GRAVITY_MASK or Gravity.TOP)
false
} else true
}
}