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,7 +88,8 @@ private val roomModule = module {
|
|||
}
|
||||
private val autoModule = module {
|
||||
single {
|
||||
AutoMusicProvider(androidContext(),
|
||||
AutoMusicProvider(
|
||||
androidContext(),
|
||||
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.
|
||||
*/
|
||||
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))
|
||||
|
|
|
@ -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) {
|
||||
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