fix: magnifier правильные координаты + haptic при изменении выделения
Magnifier: - Конвертация overlay-local → view-local координаты для Magnifier.show() - Builder: 240×64px, cornerRadius 12, elevation 4, offset -80 (над текстом) Haptic: - TEXT_HANDLE_MOVE при каждом изменении selectionStart/selectionEnd - Как в Telegram: вибрация при перемещении handle по словам Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -127,7 +127,9 @@ class TextSelectionHelper {
|
|||||||
var newStart = charOffset.coerceIn(0, text.length)
|
var newStart = charOffset.coerceIn(0, text.length)
|
||||||
while (newStart > 0 && Character.isLetterOrDigit(text[newStart - 1])) newStart--
|
while (newStart > 0 && Character.isLetterOrDigit(text[newStart - 1])) newStart--
|
||||||
if (newStart >= selectionEnd) return
|
if (newStart >= selectionEnd) return
|
||||||
|
val changed = newStart != selectionStart
|
||||||
selectionStart = newStart
|
selectionStart = newStart
|
||||||
|
if (changed) hapticOnSelectionChange()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updateSelectionEnd(charOffset: Int) {
|
fun updateSelectionEnd(charOffset: Int) {
|
||||||
@@ -136,7 +138,16 @@ class TextSelectionHelper {
|
|||||||
var newEnd = charOffset.coerceIn(0, text.length)
|
var newEnd = charOffset.coerceIn(0, text.length)
|
||||||
while (newEnd < text.length && Character.isLetterOrDigit(text[newEnd])) newEnd++
|
while (newEnd < text.length && Character.isLetterOrDigit(text[newEnd])) newEnd++
|
||||||
if (newEnd <= selectionStart) return
|
if (newEnd <= selectionStart) return
|
||||||
|
val changed = newEnd != selectionEnd
|
||||||
selectionEnd = newEnd
|
selectionEnd = newEnd
|
||||||
|
if (changed) hapticOnSelectionChange()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun hapticOnSelectionChange() {
|
||||||
|
magnifierView?.performHapticFeedback(
|
||||||
|
HapticFeedbackConstants.TEXT_HANDLE_MOVE,
|
||||||
|
HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun beginHandleDrag(isStart: Boolean, touchX: Float, touchY: Float) {
|
fun beginHandleDrag(isStart: Boolean, touchX: Float, touchY: Float) {
|
||||||
@@ -180,24 +191,30 @@ class TextSelectionHelper {
|
|||||||
magnifierView = view
|
magnifierView = view
|
||||||
}
|
}
|
||||||
|
|
||||||
fun showMagnifier(x: Float, y: Float) {
|
fun showMagnifier(overlayLocalX: Float, overlayLocalY: Float) {
|
||||||
if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.P) return
|
if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.P) return
|
||||||
val view = magnifierView ?: return
|
val view = magnifierView ?: return
|
||||||
if (!movingHandle) return
|
if (!movingHandle) return
|
||||||
if (magnifier == null) {
|
if (magnifier == null) {
|
||||||
magnifier = if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q) {
|
magnifier = if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q) {
|
||||||
android.widget.Magnifier.Builder(view)
|
android.widget.Magnifier.Builder(view)
|
||||||
.setSize(200, 80)
|
.setSize(240, 64)
|
||||||
.setCornerRadius(16f)
|
.setCornerRadius(12f)
|
||||||
|
.setElevation(4f)
|
||||||
|
.setDefaultSourceToMagnifierOffset(0, -80)
|
||||||
.build()
|
.build()
|
||||||
} else {
|
} else {
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
android.widget.Magnifier(view)
|
android.widget.Magnifier(view)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val info = layoutInfo ?: return
|
val info = layoutInfo ?: return
|
||||||
val localX = (x - info.windowX).coerceIn(0f, view.width.toFloat())
|
// Convert overlay-local → view-local (magnifierView coords)
|
||||||
val localY = (y - info.windowY).coerceIn(0f, view.height.toFloat())
|
val viewLoc = IntArray(2)
|
||||||
magnifier?.show(localX, localY)
|
view.getLocationInWindow(viewLoc)
|
||||||
|
val sourceX = (overlayLocalX + overlayWindowX - viewLoc[0]).coerceIn(0f, view.width.toFloat())
|
||||||
|
val sourceY = (overlayLocalY + overlayWindowY - viewLoc[1]).coerceIn(0f, view.height.toFloat())
|
||||||
|
magnifier?.show(sourceX, sourceY)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun hideMagnifier() {
|
fun hideMagnifier() {
|
||||||
|
|||||||
Reference in New Issue
Block a user