iOS: Scaling UITextView with pinching?
To elaborate on @Cocoanetics answer above. I implemented the gesture handling idea for attributed strings on iOS 7 but it is prohibitively slow when you have too many font changes in your string. There is also a ridiculous buffering bug in iOS 7 where Change notifications keep firing long after you've stopped pinching - reminds me of the stupid keyboard buffer in early versions of PC-DOS. Anyway, I have put the code below that got this working for me - although it has only resulted in informing me that this is a waste of time and that I need to give my users some other way of scaling their fonts.
- (void)scaleTextView:(UIPinchGestureRecognizer *)pinchGestureRecognizer
{
CGFloat scale = 0;
NSMutableAttributedString *string;
switch (pinchGestureRecognizer.state) {
case UIGestureRecognizerStateBegan:
self.old_scale = 1.0;
self.last_time = [NSDate date];
break;
case UIGestureRecognizerStateChanged:
scale = pinchGestureRecognizer.scale - self.old_scale;
if( [self.last_time timeIntervalSinceNow] < -0.2 ) { // updating 5 times a second is best I can do - faster than this and we get buffered changes going on for ages!
self.last_time = [NSDate date];
string = [self getScaledStringFrom:[self.textview.attributedText mutableCopy] withScale:1.0 + scale];
if( string ) {
self.textview.attributedText = string;
self.old_scale = pinchGestureRecognizer.scale;
}
}
break;
case UIGestureRecognizerStateEnded:
case UIGestureRecognizerStateCancelled:
case UIGestureRecognizerStateFailed:
break;
default:
break;
}
}
- (NSMutableAttributedString*) getScaledStringFrom:(NSMutableAttributedString*)string withScale:(CGFloat)scale
{
[string beginEditing];
[string enumerateAttribute:NSFontAttributeName inRange:NSMakeRange(0, string.length) options:0 usingBlock:^(id value, NSRange range, BOOL *stop) {
if (value) {
UIFont *oldFont = (UIFont *)value;
UIFont *newFont = [oldFont fontWithSize:oldFont.pointSize * scale];
[string removeAttribute:NSFontAttributeName range:range];
[string addAttribute:NSFontAttributeName value:newFont range:range];
}
}];
[string endEditing];
return string;
}
Try:
- (void)scaleTextView:(UIPinchGestureRecognizer *)pinchGestRecognizer{
CGFloat scale = pinchGestRecognizer.scale;
createTextView.font = [UIFont fontWithName:createTextView.font.fontName size:createTextView.font.pointSize*scale];
[self textViewDidChange:createTextView];
}
It basically scales the font size and then recalculates the content size using your code in textViewDidChange.
First of all add UIPinchGestureRecognizer
in viewDidLoad
method:
UIPinchGestureRecognizer *pinchOnTextfield = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(handleTextFieldFontOnAddMusicVc:)];
[self.myTextField addGestureRecognizer:pinchOnTextfield];
then put this method in your viewController
to scale textField
font:
- (void)handleTextFieldFontOnAddMusicVc:(UIPinchGestureRecognizer *)pinchGestRecognizer {
if (pinchGestRecognizer.state == UIGestureRecognizerStateEnded || pinchGestRecognizer.state == UIGestureRecognizerStateChanged) {
CGFloat currentFontSize = self.myTextField.font.pointSize;
CGFloat newScale = currentFontSize * pinchGestRecognizer.scale;
if (newScale < 20.0) {
newScale = 20.0;
}
if (newScale > 60.0) {
newScale = 60.0;
}
self.myTextField.font = [UIFont fontWithName:self.myTextField.font.fontName size:newScale];
pinchGestRecognizer.scale = 1;
}
}