Track which selection handle is being dragged, and where.
This will be used to show the magnifier in a subsequent CL.
Test: ./gradlew :compose:f:f:cAT
Change-Id: I7cde74e5cd8665a3e092eda0773d84a78e738fc1
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/selection/SelectionManager.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/selection/SelectionManager.kt
index 09c3e37..1a2ec05 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/selection/SelectionManager.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/selection/SelectionManager.kt
@@ -186,11 +186,19 @@
private set
/**
- * The handle that is currently being dragged, or null when no handle is being dragged.
+ * The handle that is currently being dragged, or null when no handle is being dragged. To get
+ * the position of the last drag event, use [currentDragPosition].
*/
var draggingHandle: Handle? by mutableStateOf(null)
private set
+ /**
+ * When a handle is being dragged (i.e. [draggingHandle] is non-null), this is the last position
+ * of the actual drag event. It is not clamped to handle positions. Null when not being dragged.
+ */
+ var currentDragPosition: Offset? by mutableStateOf(null)
+ private set
+
private val shouldShowMagnifier get() = draggingHandle != null
init {
@@ -258,6 +266,7 @@
// This property is set by updateSelection while dragging, so we need to clear it after
// the original selection drag.
draggingHandle = null
+ currentDragPosition = null
}
selectionRegistrar. selectableKey ->
@@ -501,11 +510,34 @@
fun handleDragObserver(isStartHandle: Boolean): TextDragObserver = object : TextDragObserver {
override fun onDown(point: Offset) {
- // TODO(b/206833278) Show magnifier on down.
+ val selection = selection ?: return
+ val anchor = if (isStartHandle) selection.start else selection.end
+ val selectable = getAnchorSelectable(anchor) ?: return
+ // The LayoutCoordinates of the composable where the drag gesture should begin. This
+ // is used to convert the position of the beginning of the drag gesture from the
+ // composable coordinates to selection container coordinates.
+ val beginLayoutCoordinates = selectable.getLayoutCoordinates() ?: return
+
+ // The position of the character where the drag gesture should begin. This is in
+ // the composable coordinates.
+ val beginCoordinates = getAdjustedCoordinates(
+ selectable.getHandlePosition(
+ selection = selection, isStartHandle = isStartHandle
+ )
+ )
+
+ // Convert the position where drag gesture begins from composable coordinates to
+ // selection container coordinates.
+ currentDragPosition = requireContainerCoordinates().localPositionOf(
+ beginLayoutCoordinates,
+ beginCoordinates
+ )
+ draggingHandle = if (isStartHandle) Handle.SelectionStart else Handle.SelectionEnd
}
override fun onUp() {
- // TODO(b/206833278) Show magnifier on down.
+ draggingHandle = null
+ currentDragPosition = null
}
override fun onStart(startPoint: Offset) {
@@ -567,11 +599,13 @@
override fun onStop() {
showSelectionToolbar()
draggingHandle = null
+ currentDragPosition = null
}
override fun onCancel() {
showSelectionToolbar()
draggingHandle = null
+ currentDragPosition = null
}
}
@@ -704,8 +738,8 @@
isStartHandle: Boolean,
adjustment: SelectionAdjustment,
): Boolean {
- // TODO(b/206833278) This should be set as soon as down event happens, not wait for drag.
draggingHandle = if (isStartHandle) Handle.SelectionStart else Handle.SelectionEnd
+ currentDragPosition = if (isStartHandle) startHandlePosition else endHandlePosition
val newSubselections = mutableMapOf<Long, Selection>()
var moveConsumed = false
val newSelection = selectionRegistrar.sort(requireContainerCoordinates())