Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import android.view.ContextThemeWrapper
import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
import android.widget.OverScroller
import androidx.appcompat.widget.AppCompatTextView
import androidx.core.content.withStyledAttributes
import androidx.core.graphics.drawable.toDrawable
Expand Down Expand Up @@ -80,6 +81,8 @@ class RecordsCalendarView @JvmOverloads constructor(
private var swipeStartOffset: Float = 0f
private var swipeStartPanFactor: Float = 0f
private var shouldRebaseSwipeAfterScaleStop: Boolean = false
private var isFlingStoppedOnTouch: Boolean = false
private var isScaledDuringTouch: Boolean = false
private var legendTextWidth: Float = 0f
private var legendTextHeight: Float = 0f
private var legendTopTextHeight: Float = 0f
Expand Down Expand Up @@ -185,7 +188,9 @@ class RecordsCalendarView @JvmOverloads constructor(
onSlideStart = ::onEventSwipeStart,
onSlide = ::onEventSwipe,
onSlideStop = ::onEventSwipeStop,
onFling = ::onEventFling,
)
private val flingScroller = OverScroller(context)

init {
initArgs(context, attrs, defStyleAttr)
Expand Down Expand Up @@ -243,7 +248,13 @@ class RecordsCalendarView @JvmOverloads constructor(
var handled = false

when (event.action) {
MotionEvent.ACTION_DOWN -> handled = true
MotionEvent.ACTION_DOWN -> {
// Touch during fling only stops it, same as in regular lists.
isFlingStoppedOnTouch = !flingScroller.isFinished
isScaledDuringTouch = false
flingScroller.forceFinished(true)
handled = true
}
}

return handled or
Expand All @@ -252,6 +263,15 @@ class RecordsCalendarView @JvmOverloads constructor(
scaleDetector.onTouchEvent(event)
}

override fun computeScroll() {
if (flingScroller.computeScrollOffset()) {
panFactor = flingScroller.currY.toFloat()
coercePan()
lastPanFactor = panFactor
postInvalidateOnAnimation()
}
}

fun setClickListener(listener: (ViewHolderType) -> Unit) {
this.clickListener = listener
}
Expand All @@ -274,6 +294,7 @@ class RecordsCalendarView @JvmOverloads constructor(
}

fun reset() {
flingScroller.forceFinished(true)
scaleFactor = 1f
lastScaleFactor = 1f
panFactor = 0f
Expand Down Expand Up @@ -925,6 +946,7 @@ class RecordsCalendarView @JvmOverloads constructor(
}

private fun onEventClick(event: MotionEvent) {
if (isFlingStoppedOnTouch) return
val selected = findDataPoint(x = event.x, y = event.y)
?.point?.data ?: return
resetSelectedRecordRunnable?.let(::removeCallbacks)
Expand All @@ -942,6 +964,7 @@ class RecordsCalendarView @JvmOverloads constructor(
}

private fun onEventLongClick(event: MotionEvent) {
if (isFlingStoppedOnTouch) return
val selected = findDataPoint(x = event.x, y = event.y)
?.point?.data ?: return
resetSelectedRecordRunnable?.let(::removeCallbacks)
Expand All @@ -952,6 +975,8 @@ class RecordsCalendarView @JvmOverloads constructor(
}

private fun onEventScaleStart() {
flingScroller.forceFinished(true)
isScaledDuringTouch = true
isScaling = true
if (isSwiping) lastPanFactor = panFactor
}
Expand Down Expand Up @@ -1009,9 +1034,27 @@ class RecordsCalendarView @JvmOverloads constructor(
lastPanFactor = panFactor
}

private fun onEventFling(
velocity: Float,
direction: SwipeDetector.Direction,
) {
// After a pinch, finger speed comes from zooming, not scrolling.
if (direction.isHorizontal() || isScaledDuringTouch) return
flingScroller.fling(
0, panFactor.toInt(), // Start x, y.
0, velocity.toInt(), // Velocity x, y.
0, 0, // Min, max x.
-getMaxPanAvailable().toInt(), 0, // Min, max y.
)
postInvalidateOnAnimation()
}

private fun coercePan() {
val maxPanAvailable = chartHeight * scaleFactor - chartHeight
panFactor = panFactor.coerceIn(-maxPanAvailable, 0f)
panFactor = panFactor.coerceIn(-getMaxPanAvailable(), 0f)
}

private fun getMaxPanAvailable(): Float {
return chartHeight * scaleFactor - chartHeight
}

private fun findDataPoint(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ class SwipeDetector(
private val onSlideStart: () -> Unit = {},
onSlide: (offset: Float, initialDirection: Direction, event: MotionEvent) -> Unit = { _, _, _ -> },
private val onSlideStop: () -> Unit = {},
onFling: (velocity: Float, initialDirection: Direction) -> Unit = { _, _ -> },
) {

enum class Direction {
Expand Down Expand Up @@ -165,6 +166,20 @@ class SwipeDetector(
return false
}

override fun onFling(e1: MotionEvent?, e2: MotionEvent, velocityX: Float, velocityY: Float): Boolean {
val velocity = when (initialDirection) {
Direction.LEFT,
Direction.RIGHT,
-> velocityX

Direction.UP,
Direction.DOWN,
-> velocityY
}
onFling(velocity, initialDirection)
return super.onFling(e1, e2, velocityX, velocityY)
}

private fun doSlide(e1: MotionEvent, e2: MotionEvent) {
val offset = when (initialDirection) {
Direction.LEFT,
Expand Down
Loading