Fix animations, aligment

This commit is contained in:
h4h13 2020-01-06 23:37:02 +05:30
parent caed1ee47c
commit a5e349380c
14 changed files with 858 additions and 26 deletions

View file

@ -121,7 +121,8 @@ class ArtistDetailActivity : AbsSlidingMusicPanelActivity(), ArtistDetailsView,
if (intent.extras!!.containsKey(EXTRA_ARTIST_ID)) {
intent.extras?.getInt(EXTRA_ARTIST_ID)?.let {
artistDetailsPresenter.loadArtist(it)
artistCoverContainer?.transitionName = "${getString(R.string.transition_artist_image)}_$it"
val name = "${getString(R.string.transition_artist_image)}_$it"
artistCoverContainer?.transitionName = name
}
} else {
finish()

View file

@ -8,11 +8,9 @@ import android.content.SharedPreferences
import android.os.Bundle
import android.provider.MediaStore
import android.util.Log
import android.view.Menu
import android.view.View
import androidx.core.app.ActivityCompat
import androidx.fragment.app.Fragment
import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.activities.base.AbsSlidingMusicPanelActivity
import code.name.monkey.retromusic.fragments.mainactivity.LibraryFragment
@ -251,7 +249,6 @@ class MainActivity : AbsSlidingMusicPanelActivity(), SharedPreferences.OnSharedP
}
}
companion object {
const val APP_INTRO_REQUEST = 2323
const val HOME = 0

View file

@ -19,6 +19,7 @@ import code.name.monkey.retromusic.fragments.NowPlayingScreen.ADAPTIVE
import code.name.monkey.retromusic.fragments.NowPlayingScreen.BLUR
import code.name.monkey.retromusic.fragments.NowPlayingScreen.BLUR_CARD
import code.name.monkey.retromusic.fragments.NowPlayingScreen.CARD
import code.name.monkey.retromusic.fragments.NowPlayingScreen.CIRCLE
import code.name.monkey.retromusic.fragments.NowPlayingScreen.COLOR
import code.name.monkey.retromusic.fragments.NowPlayingScreen.FIT
import code.name.monkey.retromusic.fragments.NowPlayingScreen.FLAT
@ -34,6 +35,7 @@ import code.name.monkey.retromusic.fragments.player.adaptive.AdaptiveFragment
import code.name.monkey.retromusic.fragments.player.blur.BlurPlayerFragment
import code.name.monkey.retromusic.fragments.player.card.CardFragment
import code.name.monkey.retromusic.fragments.player.cardblur.CardBlurFragment
import code.name.monkey.retromusic.fragments.player.circle.CirclePlayerFragment
import code.name.monkey.retromusic.fragments.player.color.ColorFragment
import code.name.monkey.retromusic.fragments.player.fit.FitFragment
import code.name.monkey.retromusic.fragments.player.flat.FlatPlayerFragment
@ -249,6 +251,7 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity(), AbsPlay
COLOR -> ColorFragment()
TINY -> TinyPlayerFragment()
PEAK -> PeakPlayerFragment()
CIRCLE -> CirclePlayerFragment()
else -> PlayerFragment()
} // must implement AbsPlayerFragment
supportFragmentManager.beginTransaction().replace(R.id.playerFragmentContainer, fragment)

View file

@ -18,6 +18,7 @@ enum class NowPlayingScreen constructor(
PEAK(R.string.peak, R.drawable.np_peak, 14),
ADAPTIVE(R.string.adaptive, R.drawable.np_adaptive, 10),
CIRCLE(R.string.circle, R.drawable.np_adaptive, 15),
BLUR(R.string.blur, R.drawable.np_blur, 4),
BLUR_CARD(R.string.blur_card, R.drawable.np_blur_card, 9),
CARD(R.string.card, R.drawable.np_card, 6),

View file

@ -18,21 +18,31 @@ import code.name.monkey.appthemehelper.util.ATHUtil
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.activities.tageditor.AbsTagEditorActivity
import code.name.monkey.retromusic.activities.tageditor.SongTagEditorActivity
import code.name.monkey.retromusic.dialogs.*
import code.name.monkey.retromusic.dialogs.AddToPlaylistDialog
import code.name.monkey.retromusic.dialogs.CreatePlaylistDialog
import code.name.monkey.retromusic.dialogs.DeleteSongsDialog
import code.name.monkey.retromusic.dialogs.SleepTimerDialog
import code.name.monkey.retromusic.dialogs.SongDetailDialog
import code.name.monkey.retromusic.dialogs.SongShareDialog
import code.name.monkey.retromusic.extensions.hide
import code.name.monkey.retromusic.fragments.player.PlayerAlbumCoverFragment
import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.interfaces.PaletteColorHolder
import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.model.lyrics.Lyrics
import code.name.monkey.retromusic.util.*
import kotlinx.android.synthetic.main.shadow_statusbar_toolbar.*
import code.name.monkey.retromusic.util.LyricUtil
import code.name.monkey.retromusic.util.MusicUtil
import code.name.monkey.retromusic.util.NavigationUtil
import code.name.monkey.retromusic.util.PreferenceUtil
import code.name.monkey.retromusic.util.RetroUtil
import code.name.monkey.retromusic.util.RingtoneManager
import kotlinx.android.synthetic.main.shadow_statusbar_toolbar.statusBarShadow
import java.io.FileNotFoundException
abstract class AbsPlayerFragment : AbsMusicServiceFragment(),
Toolbar.OnMenuItemClickListener,
PaletteColorHolder,
PlayerAlbumCoverFragment.Callbacks {
Toolbar.OnMenuItemClickListener,
PaletteColorHolder,
PlayerAlbumCoverFragment.Callbacks {
var callbacks: Callbacks? = null
private set
@ -41,7 +51,7 @@ abstract class AbsPlayerFragment : AbsMusicServiceFragment(),
private var playerAlbumCoverFragment: PlayerAlbumCoverFragment? = null
override fun onAttach(
context: Context
context: Context
) {
super.onAttach(context)
try {
@ -57,7 +67,7 @@ abstract class AbsPlayerFragment : AbsMusicServiceFragment(),
}
override fun onMenuItemClick(
item: MenuItem
item: MenuItem
): Boolean {
val song = MusicPlayerRemote.currentSong
when (item.itemId) {
@ -83,7 +93,7 @@ abstract class AbsPlayerFragment : AbsMusicServiceFragment(),
}
R.id.action_save_playing_queue -> {
CreatePlaylistDialog.create(MusicPlayerRemote.playingQueue)
.show(requireFragmentManager(), "ADD_TO_PLAYLIST")
.show(requireFragmentManager(), "ADD_TO_PLAYLIST")
return true
}
R.id.action_tag_editor -> {
@ -130,7 +140,8 @@ abstract class AbsPlayerFragment : AbsMusicServiceFragment(),
}
R.id.action_go_to_genre -> {
val retriever = MediaMetadataRetriever()
val trackUri = ContentUris.withAppendedId(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, song.id.toLong())
val trackUri =
ContentUris.withAppendedId(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, song.id.toLong())
retriever.setDataSource(activity, trackUri)
var genre: String? = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_GENRE)
if (genre == null) {
@ -147,7 +158,7 @@ abstract class AbsPlayerFragment : AbsMusicServiceFragment(),
MusicUtil.toggleFavorite(requireActivity(), song)
}
abstract fun playerToolbar(): Toolbar
abstract fun playerToolbar(): Toolbar?
abstract fun onShow()
@ -194,9 +205,9 @@ abstract class AbsPlayerFragment : AbsMusicServiceFragment(),
R.drawable.ic_favorite_border_white_24dp
val drawable = RetroUtil.getTintedVectorDrawable(requireContext(), res, toolbarIconColor())
if (playerToolbar().menu.findItem(R.id.action_toggle_favorite) != null)
playerToolbar().menu.findItem(R.id.action_toggle_favorite).setIcon(drawable).title = if (isFavorite) getString(R.string.action_remove_from_favorites) else getString(R.string.action_add_to_favorites)
if (playerToolbar() != null && playerToolbar()!!.menu.findItem(R.id.action_toggle_favorite) != null)
playerToolbar()!!.menu.findItem(R.id.action_toggle_favorite).setIcon(drawable).title =
if (isFavorite) getString(R.string.action_remove_from_favorites) else getString(R.string.action_add_to_favorites)
}
}.execute(MusicPlayerRemote.currentSong)
}
@ -238,17 +249,18 @@ abstract class AbsPlayerFragment : AbsMusicServiceFragment(),
}
open fun setLyrics(l: Lyrics?) {
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
view.setBackgroundColor(ATHUtil.resolveColor(requireContext(), R.attr.colorSecondary))
if (PreferenceUtil.getInstance(requireContext()).fullScreenMode &&
view.findViewById<View>(R.id.status_bar) != null) {
view.findViewById<View>(R.id.status_bar) != null
) {
view.findViewById<View>(R.id.status_bar).visibility = View.GONE
}
playerAlbumCoverFragment = childFragmentManager.findFragmentById(R.id.playerAlbumCoverFragment) as PlayerAlbumCoverFragment?
playerAlbumCoverFragment =
childFragmentManager.findFragmentById(R.id.playerAlbumCoverFragment) as PlayerAlbumCoverFragment?
playerAlbumCoverFragment?.setCallbacks(this)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
@ -269,8 +281,8 @@ abstract class AbsPlayerFragment : AbsMusicServiceFragment(),
val duration = MusicPlayerRemote.getQueueDurationMillis(MusicPlayerRemote.position)
return MusicUtil.buildInfoString(
resources.getString(R.string.up_next),
MusicUtil.getReadableDurationString(duration)
resources.getString(R.string.up_next),
MusicUtil.getReadableDurationString(duration)
)
}
}

View file

@ -0,0 +1,58 @@
/*
* 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.fragments.player.circle
import android.graphics.Color
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.widget.Toolbar
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.fragments.base.AbsPlayerFragment
/**
* Created by hemanths on 2020-01-06.
*/
class CirclePlayerFragment : AbsPlayerFragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_circle_player, container, false)
}
override fun playerToolbar(): Toolbar? {
return null
}
override fun onShow() {
}
override fun onHide() {
}
override fun onBackPressed(): Boolean = false
override fun toolbarIconColor(): Int = Color.RED
override val paletteColor: Int
get() = Color.BLACK
override fun onColorChanged(color: Int) {
}
override fun onFavoriteToggled() {
}
}

View file

@ -1,5 +1,6 @@
package code.name.monkey.retromusic.fragments.player.full
import android.app.ActivityOptions
import android.graphics.Color
import android.os.Bundle
import android.view.LayoutInflater
@ -155,7 +156,15 @@ class FullPlayerFragment : AbsPlayerFragment(), MusicProgressViewUpdateHelper.Ca
private fun setupArtist() {
artistImage.setOnClickListener {
NavigationUtil.goToArtist(requireActivity(), MusicPlayerRemote.currentSong.artistId)
val transitionName =
"${getString(R.string.transition_artist_image)}_${MusicPlayerRemote.currentSong.artistId}"
val activityOptions =
ActivityOptions.makeSceneTransitionAnimation(requireActivity(), artistImage, transitionName)
NavigationUtil.goToArtistOptions(
requireActivity(),
MusicPlayerRemote.currentSong.artistId,
activityOptions
)
}
}

View file

@ -25,7 +25,6 @@ import android.content.Intent;
import android.media.audiofx.AudioEffect;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.activities.AboutActivity;
@ -79,7 +78,7 @@ public class NavigationUtil {
ActivityCompat.startActivity(activity, intent, null);
}
public static void goToArtistOptions(@NotNull AppCompatActivity activity,
public static void goToArtistOptions(@NotNull Activity activity,
int artistId,
@NonNull ActivityOptions options) {

View file

@ -0,0 +1,577 @@
/*
* 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
*
* 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 {
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);
}
private static final String TAG = SeekArc.class.getSimpleName();
private static int INVALID_PROGRESS_VALUE = -1;
// The initial rotational offset -90 means we start at 12 o'clock
private final int mAngleOffset = -90;
private Paint mArcPaint;
// Internal variables
private int mArcRadius = 0;
private 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 double mTouchAngle;
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:
onStopTrackingTouch();
setPressed(false);
this.getParent().requestDisallowInterceptTouchEvent(false);
break;
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.OnSeekBarChangeListener
*/
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 = (int) mThumb.getIntrinsicHeight() / 2;
int thumbHalfWidth = (int) 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
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 = (int) mThumb.getIntrinsicHeight() / 2;
thumbHalfWidth = (int) mThumb.getIntrinsicWidth() / 2;
mThumb.setBounds(-thumbHalfWidth, -thumbHalfheight, thumbHalfWidth,
thumbHalfheight);
mMax = a.getInteger(R.styleable.SeekArc_max, mMax);
mProgress = a.getInteger(R.styleable.SeekArc_progress, 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 = (mProgress > mMax) ? mMax : mProgress;
mProgress = (mProgress < 0) ? 0 : mProgress;
mSweepAngle = (mSweepAngle > 360) ? 360 : mSweepAngle;
mSweepAngle = (mSweepAngle < 0) ? 0 : mSweepAngle;
mProgressSweep = (float) mProgress / mMax * mSweepAngle;
mStartAngle = (mStartAngle > 360) ? 0 : mStartAngle;
mStartAngle = (mStartAngle < 0) ? 0 : mStartAngle;
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);
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 = (progress > mMax) ? mMax : progress;
progress = (progress < 0) ? 0 : progress;
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;
}
}