自定义 uiscrollview 不滚动(使用 coretext)
Posted
技术标签:
【中文标题】自定义 uiscrollview 不滚动(使用 coretext)【英文标题】:custom uiscrollview doesn't scroll (using coretext) 【发布时间】:2012-05-22 15:52:20 【问题描述】:我正在使用 CoreText 在多列中绘制文本(取决于 iPad 的方向)。
为了测试,我创建了一个由数字 100 - 999 组成的 NSMutableString。此文本跨越 5 列,其中 1 或 2 列在屏幕上(取决于方向)。
在我的主 ViewController 中,我添加了一个自定义 UIScrollView 来保存此文本,并且我希望它可以滚动。
我注意到滚动视图在我设置之前不会滚动:
[myScrollView setContentMode:UIViewContentModeRedraw];
我确实希望滚动视图在 iPad 旋转时调用 drawRect(以调整列数)!
我对此的问题是它似乎一遍又一遍地调用 drawRect ...在滚动时(因此分配越来越多的内存,也导致一些滞后)。
我将 UIScrollView 添加到我的主 viewController 中,如下所示:
myScrollView = [[CoreTextTestUIView alloc] init];
myScrollView.parentView = self;
if(FACING == @"PU" || FACING == @"PD")
myScrollView.frame = CGRectMake(0,50,768,974);
else
myScrollView.frame = CGRectMake(0,50,1024,718);
[myScrollView setContentMode:UIViewContentModeRedraw];
[container addSubview:myScrollView];
再次,我希望在 iPad 旋转时调用 drawRect,因此列数可以改变......但我不希望它在我只是尝试滚动 UIScrollView 时调用 drawRect。
有人可以帮帮我吗?
...
下面是我的 UIScrollView 的 .m:
#import "CoreTextTestUIView.h"
#import <CoreText/CoreText.h>
@implementation CoreTextTestUIView
@synthesize parentView;
NSMutableString *testText;
-(id)initWithFrame:(CGRect)frame
self = [super initWithFrame:frame];
if(self)
// Initialization code
//set BG color
self.backgroundColor = [[UIColor alloc] initWithRed:134 green:166 blue:228 alpha:1.0];
//UIScrollView Stuff
//self.delegate = self;
self.scrollEnabled = YES;
self.pagingEnabled = YES;
self.userInteractionEnabled = YES;
[self becomeFirstResponder];
self.showsVerticalScrollIndicator = NO;
self.showsHorizontalScrollIndicator = NO;
self.bounces = NO;
self.alwaysBounceHorizontal = YES;
self.alwaysBounceVertical = NO;
//generate long text
testText = [[NSMutableString alloc] initWithString:@""];
for(int i = 100; i < 1000; i++)
[testText appendString:[NSString stringWithFormat:@"%i ",i]];
self.alpha = 0.0;
[self fadeIn];
return self;
-(void)fadeIn
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:1.0];
[UIView setAnimationDelegate:self];
//[UIView setAnimationDidStopSelector:@selector(animationFinished:finished:context:)];
self.alpha = 1.0;
[UIView commitAnimations];
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
-(void)drawRect:(CGRect)rect
NSMutableAttributedString *string = [[NSMutableAttributedString alloc] initWithString:[NSString stringWithFormat:@"%@",testText]];
//set font
CTFontRef helvetica = CTFontCreateWithName(CFSTR("Helvetica"), 40.0, NULL);
[string addAttribute:(id)kCTFontAttributeName
value:(id)helvetica
range:NSMakeRange(0, [string length])];
//layout master
CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)string);
//flip the coordinate system
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetTextMatrix(context, CGAffineTransformIdentity);
CGContextTranslateCTM(context, 0, self.bounds.size.height);
CGContextScaleCTM(context, 1.0, -1.0);
int textPos = 0;
int columnIndex = 0;
//how many columns? (orientation dependent)
float howManyColumns;
if(parentView.FACING == @"PU" || parentView.FACING == @"PD")
howManyColumns = 1.0;
else
howManyColumns = 2.0;
//create columns in loop
while(textPos < [string length])
NSLog(@"column started");
//column form
CGMutablePathRef columnPath = CGPathCreateMutable();
CGPathAddRect(columnPath, NULL,
CGRectMake((self.bounds.size.width/howManyColumns*columnIndex), 0,
(self.bounds.size.width/howManyColumns),
self.bounds.size.height));
//column frame
CTFrameRef columnFrame = CTFramesetterCreateFrame(framesetter,
CFRangeMake(textPos, 0),
columnPath,
NULL);
//use the column path
CTFrameRef frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(textPos, 0), columnPath, NULL);
CFRange frameRange = CTFrameGetVisibleStringRange(frame);
//draw
CTFrameDraw(columnFrame, context);
//cleanup
CFRelease(columnFrame);
CGPathRelease(columnPath);
textPos += frameRange.length;
columnIndex++;
//set scrollView content size
int totalPages = (columnIndex+1)/howManyColumns;
self.contentSize = CGSizeMake(totalPages*self.bounds.size.width, self.frame.size.height);
//release
CFRelease(framesetter);
[string release];
-(void)dealloc
[super dealloc];
[parentView release];
[testText release];
@end
【问题讨论】:
【参考方案1】:看着这个,我看不出你在哪里设置你的滚动视图的contentSize
。如果你没有设置滚动视图的contentSize
,滚动将不会被启用,你只会看到滚动视图当前区域的内容。此外,如果您的文本在配置中是静态的,请考虑优化正在发生的一些重绘并将其添加到 scrollView 的子视图中。
【讨论】:
我在 drawRect 方法的深处包含了一个 setContentSize 调用......但解决方案是将所有文本绘制到 UIView 中,然后将整个视图包含在 UIScrollView 中(正如@heckman 建议的那样)! !!谢谢你!!! @Chris Allinson 如果您的 setContentSize 嵌入在此 drawRect 方法中,很可能这就是您在执行[myScrollView setContentMode:UIViewContentModeRedraw];
后能够滚动的原因
@ChrisAllinson 这解决了吗?你能接受某人的回答,这样我就可以不再回头看这个了。
成功!!!解决方案是在 UIView 中绘制文本,然后将该 UIView 添加到 UIScrollView ......这样drawRect 就不会被一遍又一遍地调用(就像我在 UIScrollView 本身中绘制时那样)......谢谢!!!
@ChrisAllinson 很高兴听到这个消息!【参考方案2】:
这就是 drawRect 的工作原理。每次视图移动或更改或与它重叠的东西时都会调用它。如果您正确管理内存,这应该不是问题。
【讨论】:
以上是关于自定义 uiscrollview 不滚动(使用 coretext)的主要内容,如果未能解决你的问题,请参考以下文章
UIScrollView 被裁剪并且不使用 Autolayout 滚动
当我无法使用 UIScrollView 时,如何在自定义 UIView 中模拟惯性滚动?
UIScrollView 在 customView 中不滚动