Converted Java View classes to Kotlin
This commit is contained in:
parent
ad90694879
commit
a4d44406d6
18 changed files with 274 additions and 994 deletions
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -88,13 +88,14 @@ private val roomModule = module {
|
||||||
}
|
}
|
||||||
private val autoModule = module {
|
private val autoModule = module {
|
||||||
single {
|
single {
|
||||||
AutoMusicProvider(androidContext(),
|
AutoMusicProvider(
|
||||||
get(),
|
androidContext(),
|
||||||
get(),
|
get(),
|
||||||
get(),
|
get(),
|
||||||
get(),
|
get(),
|
||||||
get(),
|
get(),
|
||||||
get()
|
get(),
|
||||||
|
get()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
|
@ -27,29 +27,16 @@ import code.name.monkey.retromusic.extensions.show
|
||||||
/**
|
/**
|
||||||
* Created by hemanths on 2019-10-02.
|
* 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
|
private var binding =
|
||||||
|
ListItemViewNoCardBinding.inflate(LayoutInflater.from(context), this, true)
|
||||||
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)
|
|
||||||
|
|
||||||
|
init {
|
||||||
context.withStyledAttributes(attrs, R.styleable.ListItemView) {
|
context.withStyledAttributes(attrs, R.styleable.ListItemView) {
|
||||||
if (hasValue(R.styleable.ListItemView_listItemIcon)) {
|
if (hasValue(R.styleable.ListItemView_listItemIcon)) {
|
||||||
binding.icon.setImageDrawable(getDrawable(R.styleable.ListItemView_listItemIcon))
|
binding.icon.setImageDrawable(getDrawable(R.styleable.ListItemView_listItemIcon))
|
||||||
|
|
|
@ -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());
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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()
|
||||||
|
}
|
||||||
|
}
|
|
@ -44,6 +44,6 @@ class PermissionItem @JvmOverloads constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setButtonClick(callBack: () -> Unit) {
|
fun setButtonClick(callBack: () -> Unit) {
|
||||||
binding.button.setOnClickListener { callBack.invoke() }
|
binding.button.setOnClickListener { callBack() }
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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()));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue