我创建了一个带有表格的PDF。该表不会继续到下一页,而是在下一页中创建一个新表,其y位置与第一页的位置相同。如何在下一页继续绘制表格?
- (IBAction)pdfPressed:(id)sender {
// create some sample data. In a real application, this would come from the database or an API.
NSString* path = [[NSBundle mainBundle] pathForResource:@"sampleData" ofType:@"plist"];
NSDictionary* data = [NSDictionary dictionaryWithContentsOfFile:path];
NSArray* students = [data objectForKey:@"Students"];
// get a temprorary filename for this PDF
path = NSTemporaryDirectory();
self.pdfFilePath = [path stringByAppendingPathComponent:[NSString stringWithFormat:@"%d.pdf", [[NSDate date] timeIntervalSince1970] ]];
// Create the PDF context using the default page size of 612 x 792.
// This default is spelled out in the iOS documentation for UIGraphicsBeginPDFContextToFile
UIGraphicsBeginPDFContextToFile(self.pdfFilePath, CGRectZero, nil);
// get the context reference so we can render to it.
CGContextRef context = UIGraphicsGetCurrentContext();
int currentPage = 0;
// maximum height and width of the content on the page, byt taking margins into account.
CGFloat maxWidth = kDefaultPageWidth - kMargin * 2;
CGFloat maxHeight = kDefaultPageHeight - kMargin * 2;
// we're going to cap the name of the class to using half of the horizontal page, which is why we're dividing by 2
CGFloat classNameMaxWidth = maxWidth / 2;
// the max width of the grade is also half, minus the margin
CGFloat gradeMaxWidth = (maxWidth / 2) - kColumnMargin;
// only create the fonts once since it is a somewhat expensive operation
UIFont* studentNameFont = [UIFont boldSystemFontOfSize:17];
UIFont* classFont = [UIFont systemFontOfSize:15];
CGFloat currentPageY = 0;
// iterate through out students, adding to the pdf each time.
for (NSDictionary* student in students)
{
// every student gets their own page
// Mark the beginning of a new page.
UIGraphicsBeginPDFPageWithInfo(CGRectMake(0, 0, kDefaultPageWidth, kDefaultPageHeight), nil);
currentPageY = kMargin;
// draw the student's name at the top of the page.
NSString* name = [NSString stringWithFormat:@"%@ %@",
[student objectForKey:@"FirstName"],
[student objectForKey:@"LastName"]];
CGSize size = [name sizeWithFont:studentNameFont forWidth:maxWidth lineBreakMode:UILineBreakModeWordWrap];
[name drawAtPoint:CGPointMake(kMargin, currentPageY) forWidth:maxWidth withFont:studentNameFont lineBreakMode:UILineBreakModeWordWrap];
currentPageY += size.height;
// draw a one pixel line under the student's name
CGContextSetStrokeColorWithColor(context, [[UIColor blueColor] CGColor]);
CGContextMoveToPoint(context, kMargin, currentPageY);
CGContextAddLineToPoint(context, kDefaultPageWidth - kMargin, currentPageY);
CGContextStrokePath(context);
int xOrigin = 50;
int yOrigin = 300;
int rowHeight = 50;
int columnWidth = 120;
int numberOfRows = 3;
int numberOfColumns = 4;
// iterate through the list of classes and add these to the PDF.
NSArray* classes = [student objectForKey:@"Classes"];
for (NSDictionary* class in classes)
{
NSString* className = [class objectForKey:@"Name"];
NSString* grade = [class objectForKey:@"Grade"];
// before we render any text to the PDF, we need to measure it, so we'll know where to render the
// next line.
size = [className sizeWithFont:classFont constrainedToSize:CGSizeMake(classNameMaxWidth, MAXFLOAT) lineBreakMode:UILineBreakModeWordWrap];
// if the current text would render beyond the bounds of the page,
// start a new page and render it there instead
if (size.height + currentPageY > maxHeight) {
// create a new page and reset the current page's Y value
UIGraphicsBeginPDFPageWithInfo(CGRectMake(0, 0, kDefaultPageWidth, kDefaultPageHeight), nil);
currentPageY = kMargin;
}
// render the text
[className drawInRect:CGRectMake(kMargin, currentPageY, classNameMaxWidth, maxHeight) withFont:classFont lineBreakMode:UILineBreakModeWordWrap alignment:UITextAlignmentLeft];
// print the grade to the right of the class name
[grade drawInRect:CGRectMake(kMargin + classNameMaxWidth + kColumnMargin, currentPageY, gradeMaxWidth, maxHeight) withFont:classFont lineBreakMode:UILineBreakModeWordWrap alignment:UITextAlignmentLeft];
currentPageY += size.height;
[self drawTableAt:CGPointMake(xOrigin, yOrigin) withRowHeight:rowHeight andColumnWidth:columnWidth andRowCount:numberOfRows andColumnCount:numberOfColumns];
}
// increment the page number.
currentPage++;
}
// end and save the PDF.
UIGraphicsEndPDFContext();
// Ask the user if they'd like to see the file or email it.
UIActionSheet* actionSheet = [[[UIActionSheet alloc] initWithTitle:@"Would you like to preview or email this PDF?"
delegate:self
cancelButtonTitle:@"Cancel"
destructiveButtonTitle:nil
otherButtonTitles:@"Preview", @"Email", nil] autorelease];
[actionSheet showInView:self.view];
}
-(void)drawTableAt:(CGPoint)origin
withRowHeight:(int)rowHeight
andColumnWidth:(int)columnWidth
andRowCount:(int)numberOfRows
andColumnCount:(int)numberOfColumns
{
for (int i = 0; i <= numberOfRows; i++) {
int newOrigin = origin.y + (rowHeight*i);
CGPoint from = CGPointMake(origin.x, newOrigin);
CGPoint to = CGPointMake(origin.x + (numberOfColumns*columnWidth), newOrigin);
[self drawLineFromPoint:from toPoint:to];
}
for (int i = 0; i <= numberOfColumns; i++) {
int newOrigin = origin.x + (columnWidth*i);
CGPoint from = CGPointMake(newOrigin, origin.y);
CGPoint to = CGPointMake(newOrigin, origin.y +(numberOfRows*rowHeight));
[self drawLineFromPoint:from toPoint:to];
}
}
-(void)drawLineFromPoint:(CGPoint)from toPoint:(CGPoint)to
{
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetLineWidth(context, 2.0);
CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();
CGFloat components[] = {0.2, 0.2, 0.2, 0.3};
CGColorRef color = CGColorCreate(colorspace, components);
CGContextSetStrokeColorWithColor(context, color);
CGContextMoveToPoint(context, from.x, from.y);
CGContextAddLineToPoint(context, to.x, to.y);
CGContextStrokePath(context);
CGColorSpaceRelease(colorspace);
CGColorRelease(color);
}
答案 0 :(得分:0)
PDF绘图是“以页面为中心的”。当你开始绘制第二页时,你已经有效地获得了一个全新的上下文等等。除非你专门编写代码,否则不会有任何从一个页面到另一个页面的流血的概念。
我看到你已经通过检查className
的大小是否会将其放在maxHeight
之上,已经在“类”循环中解决了这个分页问题。你需要为表做同样的事情。
在较高级别,您可以一次一行地渲染您的表格,在每行之后以相同的方式检查,以查看下一行是否将表格放在maxHeight
上,然后是否会,做你在类循环中已经做过的事情 - 开始一个新页面,重置currentPageY
并继续绘制行直到表完成等等。
简而言之:没有办法让这个“免费”。