diff --git a/app/src/main/java/org/fcitx/fcitx5/android/input/bar/KawaiiBarComponent.kt b/app/src/main/java/org/fcitx/fcitx5/android/input/bar/KawaiiBarComponent.kt index eb963d1d..fe90eda6 100644 --- a/app/src/main/java/org/fcitx/fcitx5/android/input/bar/KawaiiBarComponent.kt +++ b/app/src/main/java/org/fcitx/fcitx5/android/input/bar/KawaiiBarComponent.kt @@ -47,6 +47,7 @@ import org.fcitx.fcitx5.android.input.bar.KawaiiBarStateMachine.TransitionEvent. import org.fcitx.fcitx5.android.input.bar.ui.CandidateUi import org.fcitx.fcitx5.android.input.bar.ui.IdleUi import org.fcitx.fcitx5.android.input.bar.ui.TitleUi +import org.fcitx.fcitx5.android.input.bar.ui.ToolButton import org.fcitx.fcitx5.android.input.broadcast.InputBroadcastReceiver import org.fcitx.fcitx5.android.input.candidates.expanded.ExpandedCandidateStyle import org.fcitx.fcitx5.android.input.candidates.expanded.window.FlexboxExpandedCandidateWindow @@ -80,10 +81,8 @@ import kotlin.coroutines.resume import kotlin.math.PI import kotlin.math.abs import kotlin.math.atan2 -import kotlin.math.cos import kotlin.math.hypot import kotlin.math.min -import kotlin.math.sin class KawaiiBarComponent : UniqueViewComponent(), InputBroadcastReceiver { @@ -209,49 +208,40 @@ class KawaiiBarComponent : UniqueViewComponent( // - If horizontal is dominant and left, show number row (when allowed). // - If vertical is dominant and down, hide keyboard. private val swipeHideKeyboardCallback = CustomGestureView.OnGestureListener { v, e -> + require(v is ToolButton) val numberRowAvailable = isCapabilityFlagsPassword && !isKeyboardLayoutNumber if (numberRowAvailable) { val dir = if (context.resources.configuration.layoutDirection == View.LAYOUT_DIRECTION_LTR) 1 else -1 - // We can't access the rawX and rawY of the MotionEvent, so we need to do some math. - // `e.x` and `e.y` are relative to the view's top-left corner, we want to rotate - // around the center of the view, so we translate them to be relative to the center - val relX = e.x - v.width / 2f - val relY = e.y - v.height / 2f + // `e.x` and `e.y` are relative to the view's top-left corner + val centerX = e.x - v.width / 2f + val centerY = e.y - v.height / 2f - // rotate the relative coordinates by current rotation to get absolute coordinates + val distance = hypot(centerX, centerY) // the button is ↓, so apply -90 degrees offset - val theta = Math.toRadians(v.rotation.toDouble()) - PI / 2 - val c = cos(theta) - val s = sin(theta) - val screenX = c * relX - s * relY - val screenY = s * relX + c * relY - val distance = hypot(screenX, screenY) - var angle = Math.toDegrees(atan2(screenY, screenX)).toFloat() + var angle = atan2(-centerX, centerY) * (180f / PI.toFloat()) when (e.type) { CustomGestureView.GestureType.Move -> { angle = if (angle in -45f..45f) { angle.coerceIn(-10f, 10f) } else abs(angle).coerceIn(90f - 10f, 90f + 10f) * dir - v.rotation = angle + v.iconRotation = angle } CustomGestureView.GestureType.Up -> { - val thresholdX = (v as CustomGestureView).swipeThresholdX - val thresholdY = v.swipeThresholdY val handled = when (angle) { - in -45f..45f if distance > thresholdY -> { + in -45f..45f if distance > v.swipeThresholdX -> { service.requestHideSelf(0) true } - !in -45f..45f if distance > thresholdX -> { - v.rotation = 90f * dir + !in -45f..45f if distance > v.swipeThresholdY -> { + v.iconRotation = 90f * dir numberRowState = NumberRowState.ForceShow evalIdleUiState(fromUser = true) true } else -> false } - v.rotation = 0f + v.iconRotation = 0f return@OnGestureListener handled } else -> {} diff --git a/app/src/main/java/org/fcitx/fcitx5/android/input/bar/ui/IdleUi.kt b/app/src/main/java/org/fcitx/fcitx5/android/input/bar/ui/IdleUi.kt index e15bbe76..14c09e6e 100644 --- a/app/src/main/java/org/fcitx/fcitx5/android/input/bar/ui/IdleUi.kt +++ b/app/src/main/java/org/fcitx/fcitx5/android/input/bar/ui/IdleUi.kt @@ -72,7 +72,7 @@ class IdleUi( } val menuButton = ToolButton(ctx, R.drawable.ic_baseline_expand_more_24, theme).apply { - rotation = menuButtonRotation + iconRotation = menuButtonRotation } val hideKeyboardButton = ToolButton(ctx, R.drawable.ic_baseline_arrow_drop_down_24, theme) @@ -144,9 +144,10 @@ class IdleUi( } private fun updateMenuButtonIcon() { - menuButton.image.imageResource = + menuButton.setIcon( if (inPrivate) R.drawable.ic_view_private else R.drawable.ic_baseline_expand_more_24 + ) } private fun updateMenuButtonContentDescription() { @@ -160,12 +161,12 @@ class IdleUi( private fun updateMenuButtonRotation(instant: Boolean = false) { val targetRotation = menuButtonRotation menuButton.apply { - if (targetRotation == rotation) return - animate().cancel() + if (targetRotation == iconRotation) return + iconAnimate().cancel() if (!instant && !disableAnimation) { - animate().setDuration(200L).rotation(targetRotation) + iconAnimate().setDuration(200L).rotation(targetRotation) } else { - rotation = targetRotation + iconRotation = targetRotation } } } diff --git a/app/src/main/java/org/fcitx/fcitx5/android/input/bar/ui/ToolButton.kt b/app/src/main/java/org/fcitx/fcitx5/android/input/bar/ui/ToolButton.kt index be8e2ae4..1f15196e 100644 --- a/app/src/main/java/org/fcitx/fcitx5/android/input/bar/ui/ToolButton.kt +++ b/app/src/main/java/org/fcitx/fcitx5/android/input/bar/ui/ToolButton.kt @@ -6,6 +6,7 @@ package org.fcitx.fcitx5.android.input.bar.ui import android.content.Context import android.content.res.ColorStateList +import android.view.ViewPropertyAnimator import android.widget.ImageView import androidx.annotation.ColorInt import androidx.annotation.DrawableRes @@ -29,13 +30,19 @@ class ToolButton(context: Context) : CustomGestureView(context) { val disableAnimation by AppPrefs.getInstance().advanced.disableAnimation } - val image = imageView { + private val image = imageView { isClickable = false isFocusable = false padding = dp(10) scaleType = ImageView.ScaleType.CENTER_INSIDE } + var iconRotation: Float + get() = image.rotation + set(value) { + image.rotation = value + } + constructor(context: Context, @DrawableRes icon: Int, theme: Theme) : this(context) { image.imageTintList = ColorStateList.valueOf(theme.altKeyTextColor) setIcon(icon) @@ -43,6 +50,8 @@ class ToolButton(context: Context) : CustomGestureView(context) { add(image, lParams(wrapContent, wrapContent, gravityCenter)) } + fun iconAnimate(): ViewPropertyAnimator = image.animate() + fun setIcon(@DrawableRes icon: Int) { image.imageResource = icon }