2

i'm trying draw background line of UITextView, here is the code i used to draw those lines

    CGContextBeginPath(context);
    CGContextSetStrokeColorWithColor(context, self.horizontalLineColor.CGColor);
    CGContextSetLineWidth(context, kDashedBorderWidth);
    CGContextSetLineDash(context, 0, kDashedLinesLength, kDashedCount) ;

    CGFloat baseOffset = 9.0f + self.font.descender;
    CGFloat boundsX = self.bounds.origin.x;
    CGFloat boundsWidth = self.bounds.size.width;

    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 * (float)line));            
        CGContextMoveToPoint(context, boundsX, linePointY);
        CGContextAddLineToPoint(context, boundsWidth, linePointY);
    }
    CGContextClosePath(context);
    CGContextStrokePath(context);

And the result is shown in the picture enter image description here

It seem like the it get the first line correctly but the following lines are not aligned with the text.

What did i probably miss here? Is there anything to do with localization setting?

jAckOdE
  • 2,402
  • 8
  • 37
  • 67
  • 2
    Looks like your line height calculation is off. It lines up initially because the first line is aligned correctly, but since the line height of the text is greater than that of the dashed lines, it eventually gets more and more out of line. I'd start by looking at your calculation for the line height and adjust it. – garrettmurray Aug 06 '13 at 05:10
  • i agree, `self.font.lineHeight` doesnt seem to provide a precise height value. – jAckOdE Aug 06 '13 at 05:20
  • Obviously the internal rendering of UITextView didn't use `lineHeight` property for laying out the lines. It's impossible to draw the lines accurately without knowing how it works internally. – Khanh Nguyen Aug 06 '13 at 05:30
  • Hi, may I know, how do you derive `9.0f` from, for the `baseOffset`? Thanks. – Cheok Yan Cheng Aug 06 '21 at 08:54

3 Answers3

4

You may want to check this out.

Khanh Nguyen
  • 11,112
  • 10
  • 52
  • 65
  • i use this project as the start point for my drawing code. it has the same problem. – jAckOdE Aug 06 '13 at 05:17
  • this project is good but the problem is that it draws every time line.. when i just put a cursor on textview and chane the frame of textview it will again drawing lines and text of uitextview is it will same as it is. – kalpesh May 31 '16 at 06:44
2

after few experiments, i figured out that the lineHeight in fact is a bit smaller than the real height, about 1points size.

Here is working version

CGFloat baseOffset = 7.0f + self.font.descender;

// ....

for (NSInteger line = firstVisibleLine; line <= lastVisibleLine; ++line)
{
    CGFloat linePointY = (baseOffset + ((self.font.lineHeight + 1.0f) * (float)line));            
    CGContextMoveToPoint(context, boundsX, linePointY);
    CGContextAddLineToPoint(context, boundsWidth, linePointY);
}

There are two magic numbers i think you need to find out if you implement your own version : the 7.0f and 1.0f

it is just a work around, i would love to know a better way to achieve this.

jAckOdE
  • 2,402
  • 8
  • 37
  • 67
1

This is not the exact solution, but the way around for this UI. This UI gives a feel of underlined text.

But I guess using this, we can achieve the same kind of functionality as you required.

Hope this helps.

Community
  • 1
  • 1
Mrunal
  • 13,982
  • 6
  • 52
  • 96
  • thanks, it definitely helps, but before heading down this road, i want to try a easier solution. – jAckOdE Aug 06 '13 at 05:35
  • Once you get any proper solution, please upload it here as well. So that it would be helpful for all. – Mrunal Aug 07 '13 at 13:59
  • Check out my answer, i couldnt accept my own answer, SO only allow to do it after 2 days. – jAckOdE Aug 07 '13 at 15:13