3

I want my UITextView to work and look similar to a crop utility (see image example below) but I cannot find the right approach how to use view's edges to move, rotate, resize my view:



I successfully applied UIGestureRecognizers to my entire UITextView to move (or pan) and rotate it, but when business comes to the edges functionality where all 4 nodes would either move, rotate or resize the view, I get stuck because nodes are hard to make fully functional. I tried 2 approaches:

1. Added all 4 nodes as UIImageView's as subviews of UITextView. When nodes were half outside UITextView edges I used clipsToBound = NO; to make them displayed right. However, nodes outside the view are not responding for touch. Then I tried solution 2...

2. Wrapped UITextView within container UIView and added 4 nodes for each edge and UITextView properly positioned inside. With this I achieved good UI but gesture recognizers still did not function because they were probably nested too deeply within a view which is a subview of another view that already had gesture recognizer. This needs more investigation but I feel like this approach a bit too complicated.

Am I on the right way? Perhaps, UIGestureRecognizer is not the right solution for this goal I am trying to achieve. If someone had experience working with anything similar please point me in the right direction. I am not looking for code rather ideas...

Community
  • 1
  • 1
Vad
  • 3,658
  • 8
  • 46
  • 81

2 Answers2

0

Approach 1 won't work (without some hacking) because a UIView's hit test does not respond to touches outside of its bounds. (For the hack see interaction beyond bounds of uiview)

Approach #3 is correct, and you should continue pursuing it. However, you could try using touchesBegan:withEvent: on your custom UIView subclass.

My ideas:

  1. I have implemented a similar resizing control using the technique below. You have a little bit more control than a gesture recognizers, because normal UIGestureRecognizers tend to have some minimum distance at which they begin responding, which in not ideal in this case, since you want near instant response. In addition, you are less likely to have conflicts, knowing that you already have some gesture recognizers.

  2. Many would probably recommend that you design your own UIGestureRecognizer to encapsulate and solve some of the issues I outlined above. This is probably a cleaner approach, but you will just need to be implement several UIGestureRecognizer delegate methods such as

    • gestureRecognizerShouldBegin: and gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer: to prevent simultaneous interaction with other gesture recognizers. You may also need to require some gesture recognizers only activate when others fail, using requireGestureRecognizerToFail:.

Maybe you could start with #1, get it working, and then, ideally, refactor it into #2.

Sample code for idea 1

typedef enum  {
     HandleTopLeft,
     HandleTopRight,
     HandleBottomLeft,
     HandleBottomRight
}
HandlePosition; //you will need fewer

@protocol SizingHandleDelegate;

@interface SizingHandle : UIView
@property (nonatomic, assign) id<SizingHandleDelegate> delegate;
@property (nonatomic, assign) HandlePosition position;
@end


@protocol SizingHandleDelegate <NSObject>

- (void)touchesBeganForSizingHandle:(SizingHandle*)sizingHandle;
- (void)touchesEndedForSizingHandle:(SizingHandle*)sizingHandle;

@end

Your SizingHandle class should override touchesBegan:withEvent: and touchesEnded:withEvent:: and forward those messages to their delegate. The delegate should then be able to apply the correct logic.

Also, you might want to handle the use case of the user touching more than one SizingHandle at a time.

Community
  • 1
  • 1
Arie Litovsky
  • 4,893
  • 2
  • 35
  • 40
0

When I had such a requirement, I tried to implement this using one of the sample codes from the below link, It really helped.

CropImageSampleCodes

Geekoder
  • 1,531
  • 10
  • 21