DALinedTextView
DALinedTextView copied to clipboard
iOS7 lineHeight issue
Does not work on iOS with uifont besides systemfont
With self.textView.font = [UIFont fontWithName:@"HelveticaNeue" size:20]; lines does not match the letters...
I'm checking but not resolve yet
You can check and change "CGFloat baseOffset = 7.0f + self.font.descender;" value. Hope this help!
It's strange. because systemfont works and if you use a custom font (.ttf file) it works also.
any updates?
We need to use TextKit to resolve this issue.
Unfortunately, the bugs in TextKit affecting this issue were not fixed in iOS 7.1 As JohnSD said, systemFont works, but the named font which is the system font does not work. I did some poking around, printing out line and descender height for a variety of fonts under iOS 6 vs 7, and the results are inconsistent, supporting the idea of bugs in TextKit.
I discovered that the error in line height is proportional to the font size. If a factor is introduced to allow for the error, it is proportional to font size. In playing with this idea, I discovered a factor can be used, but unfortunately, it is different for each named font.
This kFactor is multiplied by the pointSize of the font to adjust the lineHeight. This adjustment must be compensated for in the offsetY or else the lines will not be drawn in the entire visible region. I have pasted in a portion of DrawRect() with my comments denoted by "RAH".
So, here's the DrawRect code that allows me to compensate fairly successfully for the bugs in iOS 7:
// Create un-mutated floats outside of the for loop.
// Reduces memory access.
CGFloat baseOffset = 7.0f + self.font.descender; // original constant is 7.0f
CGFloat screenScale = [UIScreen mainScreen].scale;
CGFloat boundsX = self.bounds.origin.x;
CGFloat boundsWidth = self.bounds.size.width;
//RAH xcode5 introduced k factor due to programming bugs by Apple
// in iOS 7 of UITextView.
CGFloat kFactor = 0.0;
BOOL isAtLeast7 = [[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0;
if(isAtLeast7) {
kFactor = self.font.pointSize * 0.03268; // ArialMT 0.03267857143
//kFactor = self.font.pointSize * 0.0; // Helvetica
//kFactor = self.font.pointSize * 0.028; // Helvetica Neue (Regular)
//kFactor = self.font.pointSize * 0.029; // Helvetica Neue Thin
//kFactor = self.font.pointSize * 0.029; // Helvetica Neue Light
//kFactor = self.font.pointSize * 0.0424; // Times New Roman
}
// Only draw lines that are visible on the screen.
// (As opposed to throughout the entire view's contents)
//RAH have to compute the "real" contentOffset to compensate for the kfactor
// or else as you scroll down a long page, the lines nearest the top won't be drawn.
float realContentOffsetY = self.contentOffset.y - (self.contentOffset.y/self.font.lineHeight) * kFactor;
NSInteger firstVisibleLine = MAX(1, (realContentOffsetY / self.font.lineHeight));
//RAH original code -- NSInteger firstVisibleLine = MAX(1, (self.contentOffset.y / self.font.lineHeight));
NSInteger lastVisibleLine = ceilf((self.contentOffset.y + self.bounds.size.height) / self.font.lineHeight);
for (NSInteger line = firstVisibleLine; line <= lastVisibleLine; ++line)
{
CGFloat linePointY = (baseOffset + ((self.font.lineHeight + kFactor) * line));
// Rounding the point to the nearest pixel.
// Greatly reduces drawing time.
CGFloat roundedLinePointY = roundf(linePointY * screenScale) / screenScale;
CGContextMoveToPoint(context, boundsX, roundedLinePointY);
CGContextAddLineToPoint(context, boundsWidth, roundedLinePointY);
}
CGContextClosePath(context);
CGContextStrokePath(context);
}