Question

I am currently writing up an app that reads in a file and puts the headings into a list. When each heading is clicked, it switches to a controller with a CATextLayer containing the text associated with that heading (generally a few paragraphs). Initially, I used a UITextView, however I found that I needed more formatting options (namely justified alignment) and switched to a CATextLayer.

I have read in other questions here that CATextLayer is innately scrollable, however I cannot find how to trigger that behaviour. When I've attempted to set contentsRect, my text disappears entirely from the view.

This is my set-up code, which works aside from the scrolling:

    CATextLayer *textLayer = [[CATextLayer alloc] init];
    textLayer.alignmentMode = kCAAlignmentJustified;
    textLayer.string = [_data objectForKey:@"Text"];
    textLayer.wrapped = YES;
    textLayer.frame = CGRectMake(27, 75, 267, 320);
    textLayer.font = [UIFont fontWithName:@"Helvetica" size:17.0f];
    textLayer.foregroundColor = [UIColor blackColor].CGColor;
    textLayer.backgroundColor = [UIColor whiteColor].CGColor;
    [textLayer setCornerRadius:8.0f];
    [textLayer setMasksToBounds:YES]; 
    [textLayer setBorderWidth:1.0f];
    [textLayer setBorderColor:[UIColor grayColor].CGColor];
    [self.view.layer addSublayer:textLayer];
    [textLayer release];

I have looked through the documentation for CATextLayer and numerous other SO questions, and haven't found what I was looking for.

EDIT: It is possible for this class to be scrolled, however it needs to be done so programmatically using the contentsRect's offsets. It can be sub-layered to a CAScrollLayer for some helper functions (scrollToPoint and scrollToRect) and slightly tidier set of calculations. CAScrollLayer also requires the programmer to handle touch events, so for the sake of simplicity, I will not be pursuing this route.

For those who would like to go this route with a CAScrollLayer, my set-up code changed to the following:

    CAScrollLayer  *scrollLayer = [[CAScrollLayer alloc] init];
    scrollLayer.frame = CGRectMake(27, 75, 267, 320);
    scrollLayer.backgroundColor = [UIColor whiteColor].CGColor;
    scrollLayer.scrollMode = kCAScrollVertically;    
    [scrollLayer setCornerRadius:8.0f];
    [scrollLayer setMasksToBounds:YES]; 
    [scrollLayer setBorderWidth:1.0f];
    [scrollLayer setBorderColor:[UIColor grayColor].CGColor];
    scrollLayer.contentsRect = CGRectMake(0, 0, 250, 350);
    scrollLayer.contentsGravity = kCAGravityCenter;

    if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)]) 
    { 
        scrollLayer.contentsScale = [[UIScreen mainScreen] scale];
    }

    CATextLayer *textLayer = [[CATextLayer alloc] init];
    textLayer.alignmentMode = kCAAlignmentJustified;
    textLayer.string = [_notice objectForKey:@"Text"];
    textLayer.wrapped = YES;
    textLayer.frame = CGRectMake(5, 5, 250, 500);
    textLayer.font = [UIFont fontWithName:@"Helvetica" size:17.0f];
    textLayer.foregroundColor = [UIColor blackColor].CGColor;
    textLayer.backgroundColor = [UIColor whiteColor].CGColor;

    [scrollLayer addSublayer:textLayer];

    [self.view.layer addSublayer:scrollLayer];
    [scrollLayer release];
    [textLayer release];
Was it helpful?

Solution

How are you using contentsRect? It's a unit rectangle coordinates, that is each argument is between zero and one (inclusive).

So if you want to display 50 x 50 sub-rectangle at point 30, 30 you would do

textLayer.contentsRect = CGRectMake(30.0f / CONTENT_WIDTH, 30.0f / CONTENT_HEIGHT, 267.0f / CONTENT_WIDTH, 320.0f / CONTENT_HEIGHT);

Where CONTENT_WIDTH and CONTENT_HEIGHT are the size of the contents.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top