0

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];
joverboard
  • 335
  • 1
  • 3
  • 13

1 Answers1

0

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.

lorean
  • 2,150
  • 19
  • 25
  • I've spent some time playing with the values based on your formula and unfortunately all I've managed to get is blurry text that is offset up and to the left and stretched on the edges. I'm still not getting any scrolling, regardless of what I put in. Any further insight? – joverboard Dec 21 '11 at 14:56
  • Try setting layer.contentGravity = kCAGravityCenter and make sure that you have if ([[UIScreen mainsScreen] respondsToSelector:@selector(scale)] { layer.contentsScale = [[UIScreen mainScreen] scale];} – lorean Dec 21 '11 at 16:47
  • Within certain values, that fixes the blurryness and stretching, however the words are getting cut off on the sides, still without scrolling. – joverboard Dec 21 '11 at 17:44
  • The words being cut off on the side sounds like it can't fit the content width into the provided layer frame. (e.g. you're trying to display 200px wide text in 180 wide view frame). As for scrolling, I'm confused about your expectation. CALayer doesn't provide any functionality for processing touch input. You'd have to listen to and process the touch events manually while adjusting the contentRect. – lorean Dec 21 '11 at 18:10
  • In another SO post, someone had stated CALayer and CATextLayer both could be scrolled, and it was based on that accepted answer that I thought it was something more simple I was overlooking. So, for my own reference, I would adjust the 30.0f in the previous example by the offset of a touch event to give the appearance of scrolling? Would I be better suited going another route? – joverboard Dec 21 '11 at 18:40
  • You might want to have a look at http://developer.apple.com/library/ios/#documentation/GraphicsImaging/Reference/CAScrollLayer_class/Introduction/Introduction.html – lorean Dec 21 '11 at 18:51
  • This solution also requires touch events to be programmed in manually, but it's safe to say this is the correct way to go about what I initially asked. Questions answered, thanks much. – joverboard Dec 21 '11 at 19:31