auto rotate wheel when tapping icon
This commit is contained in:
@@ -23,6 +23,8 @@ import kotlin.math.*
|
||||
|
||||
class CircularNavFragment : Fragment() {
|
||||
|
||||
private var wheelView: CircularWheelView? = null
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
@@ -47,9 +49,10 @@ class CircularNavFragment : Fragment() {
|
||||
android.widget.LinearLayout.LayoutParams.MATCH_PARENT, 0, 1f
|
||||
)
|
||||
}
|
||||
val wheelView = CircularWheelView(ctx).apply {
|
||||
val prefs = ctx.getSharedPreferences("prefs", Context.MODE_PRIVATE)
|
||||
wheelView = CircularWheelView(ctx).apply {
|
||||
layoutParams = FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT)
|
||||
val prefs = ctx.getSharedPreferences("prefs", Context.MODE_PRIVATE)
|
||||
wheelAngle = prefs.getFloat("circular_wheel_angle", 0f)
|
||||
val savedSlots = NavCustomization.getCircularSlots(prefs).map { id ->
|
||||
val def = NavCustomization.ALL_SWAPPABLE.find { it.id == id }!!
|
||||
CircularWheelView.WheelItem(def.id, def.iconRes, ctx.getString(def.titleRes))
|
||||
@@ -112,6 +115,10 @@ class CircularNavFragment : Fragment() {
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
wheelView?.let { wv ->
|
||||
requireContext().getSharedPreferences("prefs", Context.MODE_PRIVATE)
|
||||
.edit().putFloat("circular_wheel_angle", wv.wheelAngle).apply()
|
||||
}
|
||||
val toolbar = requireActivity().findViewById<com.google.android.material.appbar.MaterialToolbar>(R.id.toolbar)
|
||||
toolbar.findViewWithTag<android.view.View>("wheel_title")?.let { toolbar.removeView(it) }
|
||||
requireActivity().invalidateOptionsMenu()
|
||||
@@ -181,7 +188,7 @@ class CircularWheelView @JvmOverloads constructor(
|
||||
|
||||
// ---- touch & fling ----------------------------------------------------
|
||||
|
||||
private var wheelAngle = 0f
|
||||
var wheelAngle = 0f
|
||||
private var isDragging = false
|
||||
private var snapAnimator: ValueAnimator? = null
|
||||
|
||||
@@ -358,7 +365,7 @@ class CircularWheelView @JvmOverloads constructor(
|
||||
dist <= innerRadius -> onCenterClick?.invoke()
|
||||
dist <= outerRadius -> {
|
||||
val idx = segmentAt(event.x, event.y)
|
||||
if (idx in items.indices) onItemClick?.invoke(items[idx].navId)
|
||||
if (idx in items.indices) animateToSixOClock(idx) { onItemClick?.invoke(items[idx].navId) }
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -423,6 +430,30 @@ class CircularWheelView @JvmOverloads constructor(
|
||||
return (a / (360f / items.size)).toInt() % items.size
|
||||
}
|
||||
|
||||
private fun animateToSixOClock(index: Int, onDone: () -> Unit) {
|
||||
val segDeg = 360f / items.size.coerceAtLeast(1)
|
||||
val midDeg = index * segDeg + segDeg / 2f
|
||||
// delta needed so this segment's midpoint lands at 90° (6 o'clock in math coords)
|
||||
var delta = (90f - midDeg) - wheelAngle
|
||||
// normalise to shortest path [-180, 180]
|
||||
delta = ((delta % 360f) + 360f) % 360f
|
||||
if (delta > 180f) delta -= 360f
|
||||
val endAngle = wheelAngle + delta
|
||||
|
||||
snapAnimator?.cancel()
|
||||
snapAnimator = ValueAnimator.ofFloat(wheelAngle, endAngle).apply {
|
||||
duration = 350
|
||||
interpolator = DecelerateInterpolator()
|
||||
addUpdateListener { wheelAngle = it.animatedValue as Float; invalidate() }
|
||||
addListener(object : AnimatorListenerAdapter() {
|
||||
private var cancelled = false
|
||||
override fun onAnimationCancel(a: Animator) { cancelled = true }
|
||||
override fun onAnimationEnd(a: Animator) { if (!cancelled) onDone() }
|
||||
})
|
||||
start()
|
||||
}
|
||||
}
|
||||
|
||||
private fun snapToNearest() {
|
||||
val segDeg = 360f / items.size.coerceAtLeast(1)
|
||||
val target = (wheelAngle / segDeg).roundToInt() * segDeg
|
||||
|
||||
Reference in New Issue
Block a user