Switch tracks by swipe on cover
This commit is contained in:
parent
fcbce0fb98
commit
56a4102023
6 changed files with 123 additions and 6 deletions
|
@ -73,7 +73,7 @@ import org.oxycblt.auxio.util.getInteger
|
|||
* @author Alexander Capehart (OxygenCobalt)
|
||||
*/
|
||||
@AndroidEntryPoint
|
||||
class CoverView
|
||||
open class CoverView
|
||||
@JvmOverloads
|
||||
constructor(context: Context, attrs: AttributeSet? = null, @AttrRes defStyleAttr: Int = 0) :
|
||||
FrameLayout(context, attrs, defStyleAttr) {
|
||||
|
|
|
@ -39,6 +39,7 @@ import org.oxycblt.auxio.music.Song
|
|||
import org.oxycblt.auxio.music.resolveNames
|
||||
import org.oxycblt.auxio.playback.state.RepeatMode
|
||||
import org.oxycblt.auxio.playback.ui.StyledSeekBar
|
||||
import org.oxycblt.auxio.playback.ui.SwipeCoverView
|
||||
import org.oxycblt.auxio.ui.ViewBindingFragment
|
||||
import org.oxycblt.auxio.util.collectImmediately
|
||||
import org.oxycblt.auxio.util.logD
|
||||
|
@ -58,7 +59,8 @@ import org.oxycblt.auxio.util.systemBarInsetsCompat
|
|||
class PlaybackPanelFragment :
|
||||
ViewBindingFragment<FragmentPlaybackPanelBinding>(),
|
||||
Toolbar.OnMenuItemClickListener,
|
||||
StyledSeekBar.Listener {
|
||||
StyledSeekBar.Listener,
|
||||
SwipeCoverView.OnSwipeListener {
|
||||
private val playbackModel: PlaybackViewModel by activityViewModels()
|
||||
private val musicModel: MusicViewModel by activityViewModels()
|
||||
private val detailModel: DetailViewModel by activityViewModels()
|
||||
|
@ -111,7 +113,7 @@ class PlaybackPanelFragment :
|
|||
isSelected = true
|
||||
setOnClickListener { navigateToCurrentAlbum() }
|
||||
}
|
||||
|
||||
binding.playbackCover.onSwipeListener = this
|
||||
binding.playbackSeekBar.listener = this
|
||||
|
||||
// Set up actions
|
||||
|
@ -191,6 +193,14 @@ class PlaybackPanelFragment :
|
|||
playbackModel.seekTo(positionDs)
|
||||
}
|
||||
|
||||
override fun onSwipePrevious() {
|
||||
playbackModel.prev()
|
||||
}
|
||||
|
||||
override fun onSwipeNext() {
|
||||
playbackModel.next()
|
||||
}
|
||||
|
||||
private fun updateSong(song: Song?) {
|
||||
if (song == null) {
|
||||
// Nothing to do.
|
||||
|
|
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
* Copyright (c) 2023 Auxio Project
|
||||
* SwipeCoverView.kt is part of Auxio.
|
||||
*
|
||||
* This program 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 program 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.oxycblt.auxio.playback.ui
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import android.view.GestureDetector
|
||||
import android.view.GestureDetector.OnGestureListener
|
||||
import android.view.MotionEvent
|
||||
import android.view.ViewConfiguration
|
||||
import androidx.annotation.AttrRes
|
||||
import kotlin.math.abs
|
||||
import org.oxycblt.auxio.image.CoverView
|
||||
import org.oxycblt.auxio.util.isRtl
|
||||
|
||||
class SwipeCoverView
|
||||
@JvmOverloads
|
||||
constructor(context: Context, attrs: AttributeSet? = null, @AttrRes defStyleAttr: Int = 0) :
|
||||
CoverView(context, attrs, defStyleAttr), OnGestureListener {
|
||||
|
||||
private val gestureDetector = GestureDetector(context, this)
|
||||
private val viewConfig = ViewConfiguration.get(context)
|
||||
|
||||
var onSwipeListener: OnSwipeListener? = null
|
||||
|
||||
override fun onInterceptTouchEvent(event: MotionEvent): Boolean {
|
||||
return gestureDetector.onTouchEvent(event)
|
||||
}
|
||||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
override fun onTouchEvent(event: MotionEvent): Boolean {
|
||||
return gestureDetector.onTouchEvent(event) || super.onTouchEvent(event)
|
||||
}
|
||||
|
||||
override fun onGenericMotionEvent(event: MotionEvent): Boolean {
|
||||
return gestureDetector.onGenericMotionEvent(event) || super.onGenericMotionEvent(event)
|
||||
}
|
||||
|
||||
override fun onDown(e: MotionEvent): Boolean = true
|
||||
|
||||
override fun onShowPress(e: MotionEvent) = Unit
|
||||
|
||||
override fun onSingleTapUp(e: MotionEvent): Boolean = false
|
||||
|
||||
override fun onScroll(
|
||||
e1: MotionEvent?,
|
||||
e2: MotionEvent,
|
||||
velocityX: Float,
|
||||
velocityY: Float
|
||||
): Boolean = false
|
||||
|
||||
override fun onFling(
|
||||
e1: MotionEvent?,
|
||||
e2: MotionEvent,
|
||||
velocityX: Float,
|
||||
velocityY: Float
|
||||
): Boolean {
|
||||
e1 ?: return false
|
||||
val diffY = e2.y - e1.y
|
||||
val diffX = e2.x - e1.x
|
||||
if (abs(diffX) > abs(diffY) &&
|
||||
abs(diffX) > viewConfig.scaledTouchSlop &&
|
||||
abs(velocityX) > viewConfig.scaledMinimumFlingVelocity
|
||||
) {
|
||||
if (diffX > 0) {
|
||||
onSwipeRight()
|
||||
} else {
|
||||
onSwipeLeft()
|
||||
}
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
override fun onLongPress(e: MotionEvent) = Unit
|
||||
|
||||
private fun onSwipeRight() {
|
||||
onSwipeListener?.run { if (isRtl) onSwipeNext() else onSwipePrevious() }
|
||||
}
|
||||
|
||||
private fun onSwipeLeft() {
|
||||
onSwipeListener?.run { if (isRtl) onSwipePrevious() else onSwipeNext() }
|
||||
}
|
||||
|
||||
interface OnSwipeListener {
|
||||
|
||||
fun onSwipePrevious()
|
||||
fun onSwipeNext()
|
||||
}
|
||||
}
|
|
@ -16,7 +16,7 @@
|
|||
app:title="@string/lbl_playback"
|
||||
tools:subtitle="@string/lbl_all_songs" />
|
||||
|
||||
<org.oxycblt.auxio.image.CoverView
|
||||
<org.oxycblt.auxio.playback.ui.SwipeCoverView
|
||||
android:id="@+id/playback_cover"
|
||||
style="@style/Widget.Auxio.Image.Full"
|
||||
android:layout_margin="@dimen/spacing_medium"
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
app:title="@string/lbl_playback"
|
||||
tools:subtitle="@string/lbl_all_songs" />
|
||||
|
||||
<org.oxycblt.auxio.image.CoverView
|
||||
<org.oxycblt.auxio.playback.ui.SwipeCoverView
|
||||
android:id="@+id/playback_cover"
|
||||
style="@style/Widget.Auxio.Image.Full"
|
||||
android:layout_margin="@dimen/spacing_medium"
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
app:title="@string/lbl_playback"
|
||||
tools:subtitle="@string/lbl_all_songs" />
|
||||
|
||||
<org.oxycblt.auxio.image.CoverView
|
||||
<org.oxycblt.auxio.playback.ui.SwipeCoverView
|
||||
android:id="@+id/playback_cover"
|
||||
style="@style/Widget.Auxio.Image.Full"
|
||||
android:layout_marginStart="@dimen/spacing_medium"
|
||||
|
|
Loading…
Reference in a new issue