SKLabelNode多行

时间:2015-07-10 23:27:15

标签: ios objective-c sprite-kit

我在SKLabelNode中显示多行标签时遇到了一些麻烦。首先,我知道没有lines属性或类似的任何东西。我得到那里的GitHub项目可以做到,但我宁愿不使用它们。

我需要多行的原因是我的应用程序内购买的方式。有时,描述不能全部符合一行。例如,以最大的DynamicType标题字体大小呈现字符串:

Cheat and get 25% of the points needed for the "Chaos" theme!

不适合纵向布局上的任何iOS手机。我试过调用这个函数:

-(NSString*)autoInsertLineBreaksInString:(NSString*)string {
    NSLog(@"Function called with %@", string);
    NSMutableArray* arrayOfSpaceIndexes = [NSMutableArray array];
    NSMutableString* returnString = [string mutableCopy];
    for (int i = 0; i < string.length; i++) {
        if ([string characterAtIndex:i] == [@" " characterAtIndex:0]) {
            NSLog(@"Adding %i to array of space indexes.", i);
            [arrayOfSpaceIndexes addObject:@(i)];
        } else {
            NSLog(@"Not adding %i to array of space indexes.", i);
        }
    }
    [returnString replaceCharactersInRange:NSMakeRange([[arrayOfSpaceIndexes objectAtIndex:(NSUInteger)(floorf((arrayOfSpaceIndexes.count - 1) / 2))] unsignedIntegerValue], 1) withString:@"\n"];
    NSLog(@"Retruning %@", returnString);
    return returnString;
}

这会在正确的位置插入\n并输出此...

Cheat and get 25% of the
points needed for the "Chaos" theme.

...但标签节点将\n解释为空格,为我提供原始字符串。我真的不想使用第二个标签节点。关于如何解决这个问题的任何想法?

2 个答案:

答案 0 :(得分:1)

将注释正式化为答案:如果您选择使用多个SKLabelNode实例,则可以创建一个包装器SKNode并将每个SKLabelNode添加到包装器中。将包装器添加到场景时,只需管理一个包装器,就可以隐藏/显示/移动/等所有标签节点。

答案 1 :(得分:1)

这个帖子帮助我走上了正确的方向。这是我建议的解决方案的目标c实现:

NSInteger fontSize = 40;
SKNode *messageNode;
messageNode = [[SKNode alloc] init];

NSArray *components = [messageString componentsSeparatedByString:@"\n"];

for(int i = 0; i < [components count]; i++){
    SKLabelNode *subNode = [SKLabelNode labelNodeWithFontNamed:@"Helvetica-Bold"];
    subNode.text = [components objectAtIndex:i];
    subNode.position = CGPointMake(0, -fontSize*i);
    subNode.fontSize = fontSize;
    subNode.fontColor = [SKColor blackColor];
    subNode.verticalAlignmentMode = SKLabelVerticalAlignmentModeCenter;
    [messageNode addChild:subNode];
}

请注意,由于每个新行相对于父节点垂直向下移动,因此当您在场景中放置messageNode时,位置将基于第一行文本的中心点,而不是整个文本块的中心点。通过将totalNeight / 2 - lineHeight / 2调整为messageNode的中心点,可以轻松修复这个问题。请参阅下面背景代码中的backgroundNode.position行。

我写了一些代码来为文本块创建背景:

    //Get widest child frame
    NSInteger frameWidth = 0;
    for(int i = 0; i < [messageNode.children count]; i++){
        if([messageNode.children objectAtIndex:i].frame.size.width > frameWidth){
            frameWidth = [messageNode.children objectAtIndex:i].frame.size.width;
        }
    }

    NSInteger singleLineHeight = [messageNode.children objectAtIndex:0].frame.size.height;
    NSInteger lineCount = [messageNode.children count];
    NSInteger totalFrameHeight = singleLineHeight * lineCount;

    CGSize backgroundFrameSize = CGSizeMake(frameWidth * 1.1, totalFrameHeight * 1.5);
    CGFloat cornerRadius = 10;
    SKShapeNode *backgroundNode = [SKShapeNode shapeNodeWithRectOfSize:backgroundFrameSize cornerRadius:cornerRadius];

    //Bump the frame down so it is vertically centered around all lines of text, rather than vertically centered on the first line.
    backgroundNode.position = CGPointMake(0, -(totalFrameHeight/2 - singleLineHeight/2) );
    backgroundNode.zPosition = -1;
    [messageNode addChild:backgroundNode];