fix: посимвольное выделение + magnifier на позиции handle + haptic на каждый символ
Было: word snap при drag handle → нельзя выделить часть слова Стало: посимвольно при drag (word snap только при первом long press) Magnifier: показывается на позиции handle (текущий символ), а не на позиции пальца. По Y — центр строки текста. Haptic: TEXT_HANDLE_MOVE на каждый символ (не на каждое слово). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -124,8 +124,7 @@ class TextSelectionHelper {
|
|||||||
fun updateSelectionStart(charOffset: Int) {
|
fun updateSelectionStart(charOffset: Int) {
|
||||||
if (!isActive) return
|
if (!isActive) return
|
||||||
val text = layoutInfo?.text ?: return
|
val text = layoutInfo?.text ?: return
|
||||||
var newStart = charOffset.coerceIn(0, text.length)
|
val newStart = charOffset.coerceIn(0, text.length)
|
||||||
while (newStart > 0 && Character.isLetterOrDigit(text[newStart - 1])) newStart--
|
|
||||||
if (newStart >= selectionEnd) return
|
if (newStart >= selectionEnd) return
|
||||||
val changed = newStart != selectionStart
|
val changed = newStart != selectionStart
|
||||||
selectionStart = newStart
|
selectionStart = newStart
|
||||||
@@ -135,8 +134,7 @@ class TextSelectionHelper {
|
|||||||
fun updateSelectionEnd(charOffset: Int) {
|
fun updateSelectionEnd(charOffset: Int) {
|
||||||
if (!isActive) return
|
if (!isActive) return
|
||||||
val text = layoutInfo?.text ?: return
|
val text = layoutInfo?.text ?: return
|
||||||
var newEnd = charOffset.coerceIn(0, text.length)
|
val newEnd = charOffset.coerceIn(0, text.length)
|
||||||
while (newEnd < text.length && Character.isLetterOrDigit(text[newEnd])) newEnd++
|
|
||||||
if (newEnd <= selectionStart) return
|
if (newEnd <= selectionStart) return
|
||||||
val changed = newEnd != selectionEnd
|
val changed = newEnd != selectionEnd
|
||||||
selectionEnd = newEnd
|
selectionEnd = newEnd
|
||||||
@@ -201,7 +199,7 @@ class TextSelectionHelper {
|
|||||||
.setSize(240, 64)
|
.setSize(240, 64)
|
||||||
.setCornerRadius(12f)
|
.setCornerRadius(12f)
|
||||||
.setElevation(4f)
|
.setElevation(4f)
|
||||||
.setDefaultSourceToMagnifierOffset(0, -80)
|
.setDefaultSourceToMagnifierOffset(0, -96)
|
||||||
.build()
|
.build()
|
||||||
} else {
|
} else {
|
||||||
@Suppress("DEPRECATION")
|
@Suppress("DEPRECATION")
|
||||||
@@ -209,11 +207,21 @@ class TextSelectionHelper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
val info = layoutInfo ?: return
|
val info = layoutInfo ?: return
|
||||||
// Convert overlay-local → view-local (magnifierView coords)
|
|
||||||
|
// Magnifier should show at the HANDLE position (current char), not finger
|
||||||
|
// Use handle X for horizontal, and line center for vertical
|
||||||
|
val handleX = if (movingHandleStart) startHandleX else endHandleX
|
||||||
|
val handleY = if (movingHandleStart) startHandleY else endHandleY
|
||||||
|
val activeOffset = if (movingHandleStart) selectionStart else selectionEnd
|
||||||
|
val layout = info.layout
|
||||||
|
val line = layout.getLineForOffset(activeOffset.coerceIn(0, info.text.length))
|
||||||
|
val lineCenter = (layout.getLineTop(line) + layout.getLineBottom(line)) / 2f
|
||||||
|
|
||||||
|
// Convert to view-local coordinates
|
||||||
val viewLoc = IntArray(2)
|
val viewLoc = IntArray(2)
|
||||||
view.getLocationInWindow(viewLoc)
|
view.getLocationInWindow(viewLoc)
|
||||||
val sourceX = (overlayLocalX + overlayWindowX - viewLoc[0]).coerceIn(0f, view.width.toFloat())
|
val sourceX = (handleX + overlayWindowX - viewLoc[0]).coerceIn(0f, view.width.toFloat())
|
||||||
val sourceY = (overlayLocalY + overlayWindowY - viewLoc[1]).coerceIn(0f, view.height.toFloat())
|
val sourceY = (lineCenter + info.windowY - viewLoc[1]).coerceIn(0f, view.height.toFloat())
|
||||||
magnifier?.show(sourceX, sourceY)
|
magnifier?.show(sourceX, sourceY)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user