在iPhone上为UITextView绘制规则线

4

我想创建一个类似于iPhone上的笔记应用程序的视图,因此需要该视图具有笔记应用程序中的横线。 我已经在Windows中完成了这个工作,您需要获取字体度量值,然后将线条绘制到设备上下文中。如果在UITextView中完成过此操作,则需要一些帮助。

4个回答

8

继承UITextView类。重写-drawRect:方法。

- (void)drawRect:(CGRect)rect
{    
    CGContextRef context = UIGraphicsGetCurrentContext();

    CGContextSetStrokeColorWithColor(context, self.lineColor.CGColor);
    CGContextSetLineWidth(context, self.lineWidth);
    CGFloat strokeOffset = (self.lineWidth / 2);

    CGFloat rowHeight = self.font.lineHeight;
    if (rowHeight > 0) {
        CGRect rowRect = CGRectMake(self.contentOffset.x, - self.bounds.size.height, self.contentSize.width, rowHeight);
        while (rowRect.origin.y < (self.bounds.size.height + self.contentSize.height)) {
            CGContextMoveToPoint(context, rowRect.origin.x + strokeOffset, rowRect.origin.y + strokeOffset);
            CGContextAddLineToPoint(context, rowRect.origin.x + rowRect.size.width + strokeOffset, rowRect.origin.y + strokeOffset);
            CGContextDrawPath(context, kCGPathStroke);
            rowRect.origin.y += rowHeight;
        }
    }
}

当您初始化文本视图时,请确保将contentMode设置为UIViewContentModeRedraw。否则,行不会随着文本滚动。

self.contentMode = UIViewContentModeRedraw;

这不是最完美的。理想情况下,你应该只需绘制传递的矩形。但我懒惰了,这对我的需求起作用。


你能详细说明一下吗?例如,rowNumber是什么? - Stian Høiland
抱歉,当我复制和粘贴时,代码被留在那里了。我不认为它与这段代码相关。我已经将其删除。 - Dave Batton
@DaveBatton self.lineWidth是什么?它是静态的还是动态的? - Hitarth
self.lineWidth是一个公共的CGFloat属性。 - Dave Batton

5
我认为这个代码可以工作,但我感觉它被黑客攻击了,而且我并不完全理解UITextView类的机制;
首先,您必须将以下内容添加到委托中以强制在滚动时重新绘制。
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{   
    // NSLog(@"scrollViewDidScroll The scroll offset is ---%f",scrollView.contentOffset.y);
    [noteText setNeedsDisplay];
}

然后在子类中实现drawRect,代码如下:
- (void)drawRect:(CGRect)rect {
    // Drawing code
    // Get the graphics context
    CGContextRef ctx = UIGraphicsGetCurrentContext();

    [super drawRect:rect];

    // Get the height of a single text line
    NSString *alpha = @"ABCD";
    CGSize textSize = [alpha sizeWithFont:self.font constrainedToSize:self.contentSize lineBreakMode:UILineBreakModeWordWrap];
    NSUInteger height = textSize.height;

    // Get the height of the view or contents of the view whichever is bigger
    textSize = [self.text sizeWithFont:self.font constrainedToSize:self.contentSize lineBreakMode:UILineBreakModeWordWrap];
    NSUInteger contentHeight = (rect.size.height > textSize.height) ? (NSUInteger)rect.size.height : textSize.height;

    NSUInteger offset = 6 + height; // MAGIC Number 6 to offset from 0 to get first line OK ???
    contentHeight += offset;
    // Draw ruled lines
    CGContextSetRGBStrokeColor(ctx, .8, .8, .8, 1);
    for(int i=offset;i < contentHeight;i+=height) {
        CGPoint lpoints[2] = { CGPointMake(0, i), CGPointMake(rect.size.width, i) };
        CGContextStrokeLineSegments(ctx, lpoints, 2);
    }
}

仍然担心这个神奇数字6

Bob


很棒的解决方案。但是我已经将@Dave的self.contentMode = UIViewContentModeRedraw;添加到子类的init方法中,而不是你的setNeedsDisplay方法。 - reggian

1
你可以尝试使用有规则线条的图像设置textView的backgroundColor。
textView.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"RuledLinesPage.png"]];

如果要填充颜色的区域大于图像,则使用带有图案的颜色会创建平铺图像。因此,您必须确保图像大小是正确的/可平铺的(我不认为“可平铺”是一个真正的词,但我希望您明白我的意思)。此外,您还需要创建具有规则线条的图像,以最好地匹配您的textView字体。

祝你好运。


1
聪明的话,它就能够运行。图像可以通过编程生成以适应字体。 - Justin

0
@lukya, 你的解决方案有点混乱,因为当我们滚动UITextView时,文本只会滚动,而图像中的线条则保持在原地。
更好的解决方案是在你的文本视图中添加子视图,其中包含你绘制的线条。你需要向文本视图添加观察者,以便跟踪其内容大小的变化,因为文本增加/减少。

这应该是对答案的评论,而不是“答案”本身。 - Santa

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接