UITextView 格线背景但线高错误

Posted

技术标签:

【中文标题】UITextView 格线背景但线高错误【英文标题】:UITextView ruled line background but wrong line height 【发布时间】:2011-03-21 08:36:20 【问题描述】:

我有一个 UITextView,用户可以在其中创建注释并保存到 plist 文件中。 我希望能够像普通笔记本一样显示线条。我遇到的问题是 文本将无法正确对齐。

下图很好地解释了这个问题。

这是我用来创建像 Notes.app 这样的线条的背景

这是我为UITextView 创建背景的代码:

textView.font            = [UIFont fontWithName:@"MarkerFelt-Thin" size:19.0]; 
textView.backgroundColor = [UIColor colorWithPatternImage: [UIImage imageNamed: @"Notes.png"]];

我知道UIFont.lineHeight 属性仅适用于 > ios 4.x。

所以我想知道我的问题是否有其他解决方案?

【问题讨论】:

【参考方案1】:

您应该尝试以编程方式绘制线条,而不是使用图像。下面是一些示例代码,说明如何实现这一点。您可以继承 UITextView 并覆盖它的 drawRect: 方法。

NoteView.h

#import <UIKit/UIKit.h>
@interface NoteView : UITextView <UITextViewDelegate> 

@end

NoteView.m

#import "NoteView.h"

@implementation NoteView

- (id)initWithFrame:(CGRect)frame 

    self = [super initWithFrame:frame];
    if (self) 
        self.backgroundColor = [UIColor colorWithRed:1.0f green:1.0f blue:0.6f alpha:1.0f];
        self.font = [UIFont fontWithName:@"MarkerFelt-Thin" size:19];
    
    return self;


- (void)drawRect:(CGRect)rect 

    //Get the current drawing context   
    CGContextRef context = UIGraphicsGetCurrentContext(); 
    //Set the line color and width
    CGContextSetStrokeColorWithColor(context, [UIColor colorWithRed:0.0f green:0.0f blue:0.0f alpha:0.2f].CGColor);
    CGContextSetLineWidth(context, 1.0f);
    //Start a new Path
    CGContextBeginPath(context);

    //Find the number of lines in our textView + add a bit more height to draw lines in the empty part of the view
    NSUInteger numberOfLines = (self.contentSize.height + self.bounds.size.height) / self.font.leading;

    //Set the line offset from the baseline. (I'm sure there's a concrete way to calculate this.)
    CGFloat baselineOffset = 6.0f;

    //iterate over numberOfLines and draw each line
    for (int x = 0; x < numberOfLines; x++) 
        //0.5f offset lines up line with pixel boundary
        CGContextMoveToPoint(context, self.bounds.origin.x, self.font.leading*x + 0.5f + baselineOffset);
        CGContextAddLineToPoint(context, self.bounds.size.width, self.font.leading*x + 0.5f + baselineOffset);
    

    //Close our Path and Stroke (draw) it
    CGContextClosePath(context);
    CGContextStrokePath(context);


@end

MyViewController.h

#import <UIKit/UIKit.h>
#import "NoteView.h"
@interface MyViewController : UIViewController <UITextViewDelegate> 

    NoteView *note;


@property (nonatomic, retain) NoteView *note;

@end

MyViewController.m

#import "MyViewController.h"
#import "NoteView.h"

#define KEYBOARD_HEIGHT 216

@implementation MyViewController
@synthesize note;

- (void)loadView 
    [super loadView];
    self.note = [[[NoteView alloc] initWithFrame:self.view.bounds] autorelease];
    [self.view addSubview:note];
    note.delegate = self;
    note.text = @"This is the first line.\nThis is the second line.\nThis is the ... line.\nThis is the ... line.\nThis is the ... line.\nThis is the ... line.\nThis is the ... line.\n";


- (void)scrollViewDidScroll:(UIScrollView *)scrollView 
    [note setNeedsDisplay];


- (void)textViewDidBeginEditing:(UITextView *)textView 
    CGRect frame = self.view.bounds;
    frame.size.height -= KEYBOARD_HEIGHT;
    note.frame = frame;


- (void)textViewDidEndEditing:(UITextView *)textView 
    note.frame = self.view.bounds;


- (void)dealloc 
    [note release];
    [super dealloc];

查看 Apple 的 Managing the Keyboard 文档,特别是“移动位于键盘下方的内容”。它解释了如何监听 NSNotifcations 并正确调整你的视图。

【讨论】:

好的,我想我现在关注您添加更多文本时出现的行。我将编辑答案,将视图的高度添加到内容大小的高度,并且应该用线条覆盖整个视图。 好的,我明白了,谢谢。如果您单击 Enter 并创建带有文本的新行,如果您的解决方案没有阻止这种情况的发生,文本在键盘下将不可见,那么您是否可以看到这些行不再正确对齐?如果您只键入三行,那么一切都是完美的,但是一旦它变得更多 NoteView.frame.size.height 线条被错误地绘制。你遇到过这种情况吗? 好吧,这真是太棒了。我将它与从 XIB 加载的文本视图一起使用 - 只需制作一个 UITextView 并将其类设置为 NoteView,就完成了。工作出色。我做了一个更改,我从 1 开始 for 循环,这样它就不会在第一行文本上方画一条线 - 看起来更漂亮,更像是一个真正的记事本。但实际上,这个答案超出了 *** 的预期。 不要忘记在initWithFrame: 中添加self.contentMode = UIViewContentModeRedraw;,这样文本和行会一起滚动。否则,绝对很棒的解决方案! 我不确定它什么时候坏了,但是 font.leading 属性总是为我返回 0。相反,您应该使用在 iOS 9 上完全可以正常工作的 font.lineHeight【参考方案2】:

我认为问题出在您的图像上,线上方的黄色空间造成了问题。

您应该编辑图像。

干得好。

【讨论】:

这似乎是两件事的结合:我删除的黄色空间使它看起来每行的行高都相同。当我解决这个问题时,问题变得非常清楚: UITextView 中的文本有一个顶部填充,可以阻止文本完美对齐。边距可以用 contentInset 解决,但不能用 padding 解决。有人知道如何修复顶部填充吗? CSS 中的等价物是:padding-top:0px 是的,你说得对。我自己检查一下。但仍然无法解决这个问题。 contentInset 属性不适用于我的解决方案,因为背景随着 contentInset 移动。这只是需要移动的内容。我不明白为什么 UITextView 默认有一个 15px 左右的填充。我不知道在我的研究之后这是否可以调整,我想我需要寻找一些替代方法来解决它。过去这里有人做过吗? 我想在我的上一个客户项目中这样做。然后由于许多困难,我离开了所有这些线。但如果你找到解决方案,那么你应该与我们分享。

以上是关于UITextView 格线背景但线高错误的主要内容,如果未能解决你的问题,请参考以下文章

在启用滚动的堆栈视图中扩展 UITextView

如何获得跨度的线高?

当通过点击背景关闭 UITextView 的键盘时,我在 didSelectRowAt 中得到错误的 indexPath

表格里下划线怎么去掉

调整表格视图单元格以显示 UITextView 和 UIWebView

iOS6 和 UITableView 中的屏幕外 UITextView