Skip to content

feat: improve crop mathematics and expand touch padding#12

Open
rubenalfon wants to merge 3 commits into
Tanish-Ranjan:developfrom
rubenalfon:fix/drag-gesture
Open

feat: improve crop mathematics and expand touch padding#12
rubenalfon wants to merge 3 commits into
Tanish-Ranjan:developfrom
rubenalfon:fix/drag-gesture

Conversation

@rubenalfon
Copy link
Copy Markdown

Description

This PR significantly improves the UX of the cropping tool by overhauling the gesture calculation logic. Previously, resizing with a locked aspect ratio could feel "jumpy" or unresponsive. I have implemented a vector projection approach that ensures the crop rectangle follows the user's finger naturally while respecting the aspect ratio constraints.

Additionally, this PR addresses touch handling issues at the edges of the image (related to PR #9) by adding content padding to the canvas, ensuring handles are always clickable.

Key Changes:

  • Implemented getNewRectMeasuresLocked using vector projection for precise, locked resizing.
  • Added calculateNewCropRect as a unified entry point to cleanly switch between free-form and locked logic.
  • Refactored CropStateManager to track dragOffset for smoother updates.
  • Increased touchPadding to 20.dp and updated canvas initialization to include content padding.

Fixes #9

Type of change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as
    expected)
  • This change requires a documentation update

How Has This Been Tested?

I have performed manual testing on an Android phone to verify the gesture behavior.

  • Locked Aspect Ratio Test: Verified that dragging corners with a fixed ratio (e.g., 16:9, 1:1) resizes smoothly without jumping, even when dragging far from the pivot point, and going out then inside the bounds of the image.
  • Free Crop Test: Verified that standard cropping (aspect ratio 0f) works robustly and respects the new clamping logic.
  • Edge Touch Test: Moved the crop selection to the absolute edges of the image and verified that corner handles remain fully interactive and easy to grab.

Checklist:

  • My code follows the style guidelines of this project
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes
  • Any dependent changes have been merged and published in downstream modules

This commit overhauls the gesture logic to allow precise resizing. It also improves UX by expanding touch areas.

Specific changes:
- Implemented `getNewRectMeasuresLocked` for aspect-ratio locked resizing.
- Added `calculateNewCropRect` as a unified entry point.
- Refactored `CropStateManager` to track `dragOffset`.
- Updated canvas to include `contentPadding` for better edge interaction.
- Increased default `touchPadding` to 20.dp.

This implementation effectively covers the goals of PR Tanish-Ranjan#9.

Closes Tanish-Ranjan#9
Specifically:
- Updated `getNewRectMeasuresLocked` to pre-calculate `minWidth` and `minHeight` based on the aspect ratio and `minCropSize`.
- Added logic to constrain the `handleOffset` before calculating distances, preventing the crop rectangle from shrinking below minimum dimensions.
- Refactored `directionX` and `directionY` calculation to rely on the `activeHandle` type rather than coordinate comparisons for more reliable growth direction tracking.
- Refined horizontal and vertical bounds checking to ensure the aspect ratio is maintained when scaling down to fit within the image boundaries.
@rubenalfon rubenalfon marked this pull request as ready for review February 7, 2026 16:25
This commit moves the `dragOffset` state from the `CropState` data class to a local variable within `CropStateManager`.

This change centralizes drag-related logic within the `CropStateManager` and simplifies the `CropState` data class, which no longer needs to track this transient UI state. The `dragOffset` is now managed directly where drag gestures are handled.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEAT] improve touch responsiveness for the drag handles

1 participant