SKLabelNode - 当超过一行时如何居中对齐?

SKLabelNode - how to center align when more than one line?

使用 SKLabelNode 时,似乎当您分到多行时,

结果总是

abcde
fg

而不是

abcde
 fg

真的,SKLabelNode 似乎只是左对齐,仅此而已。

是否有解决方案 - 如何使多行 SKLabelNode 居中对齐?


注意 - horizo​​ntalAlignmentMode 完全无关。它只是让你选择整个标签区域的锚点是在位置的左侧、右侧还是中心。

A​​pple 的 SKLabel 似乎根本没有 居中多行文本。 (截至 2018 年。)

该行为只能被描述为损坏 - 无论设置如何,第二行和后面的行都向左对齐。

一种解决方案是使用“第二个标签”,示例如下。

稍后...

@MartinŠkorc 似乎发现您可以将 AttributedString 与 SKLabels 一起使用 - 太棒了!谢谢马丁!

import SpriteKit

class StupidMultilineSKLabelNode: SKLabelNode {
    
    // Apple's SKLabel does not center multi-line text
    
    // this class works around the problem by making
    // a "sub" SKLabel for the second line
    
    // if the .text includes a newline, a line break,
    // this class will present it as a two-line SKLabel,
    // but properly centered (each line itself centered).
    // (this example allows just the one extra line)
    
    // please note,
    // this is not meant to be a generalized class;
    // rather it is meant to work quick in a specific case.
    // you can change it as needed
    
    // using a "second label" does seem to be the only solution
    // until Apple address the issue
    
    var stupidExtraLabel: SKLabelNode
    
    override init() {
        
        stupidExtraLabel = SKLabelNode()
        super.init()
        
        stupidExtraLabel.basicSettings()
        // the simplest approach: in "basicSettings" simply set
        // your point size, font, color, etc etc as you wish
        // just always use that call to set all labels in the project

        stupidExtraLabel.position = CGPoint(x: 0, y: -10)
        stupidExtraLabel.text = ""
        
        self.addChild(stupidExtraLabel)
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    override var alpha: CGFloat {
        
        didSet {
            
            super.alpha = alpha
            stupidExtraLabel.alpha = alpha
        }
    }
    
    override var fontColor: UIColor? {
        
        didSet {
            
            super.fontColor = fontColor
            stupidExtraLabel.fontColor = fontColor
        }
    }
    
    override var text: String? {
        
        didSet {
            
            let lines: [String] = text!.components(separatedBy: ["\n"])
            super.text = ""
            stupidExtraLabel.text = ""
            if lines.count > 0 { super.text = lines[0] }
            if lines.count > 1 { stupidExtraLabel.text = lines[1] }
            
            stupidExtraLabel.position = CGPoint(x: 0, y: -10)
        }
    }
}

跟进 - 我发布了 link 而不是代码,这是一种禁忌。我没有大代表(菜鸟),所以我还不能编辑:)

我最近发现您可以将 UIKit 叠加在 scenekit 之上(可能还有 Sprite Kit)。我已经尝试过了,它在 FPS 上没有任何损失,所以我删除了我所有的 Spritekit 叠加层(menus/labels)并使用了 UIKit 基础知识(UIButton、UILabel)。如果对此感兴趣,我可以分享一些代码。我仍在想办法解决问题,但我认为它会奏效。

我通过将 attributedText 设置为 SKLabelNode 解决了这个问题。似乎是最简单的方法,希望 Apple 尽快解决这个问题。

Swift 4

let attrString = NSMutableAttributedString(string: yourString)
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.alignment = .center
let range = NSRange(location: 0, length: yourString.count)
attrString.addAttribute(NSAttributedStringKey.paragraphStyle, value: paragraphStyle, range: range)
attrString.addAttributes([NSAttributedStringKey.foregroundColor : UIColor.black, NSAttributedStringKey.font : UIFont.systemFont(ofSize: 30)], range: range)
yourLabelNode.attributedText = attrString