Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multi-line label in swift 2 sprite-kit?

I need to be able to make a multi-line label in swift 2 sprite-kit for a game. The text needs to wrap around rather than go off of the screen. Bellow is what I have but I do not know what to do

import Foundation
import UIKit
import SpriteKit

class JDQuotes: SKLabelNode {

    var number = 0

    init(num: Int) {
        super.init()

        if num == 1 { 

            text = "\"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. laborum.\""

        }
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}
like image 976
JaredD101 Avatar asked Feb 01 '16 00:02

JaredD101


People also ask

How do I allow multiple lines of a label in Swift?

To set the number of lines we want our UILabel to support we will use a numberOfLines property. For example, to make UILabel support two lines, we will set the numberOfLines property to 2.

How do I make text multiline in Swiftui?

To force a minimum number of lines to a text view, you append a new line character ( \n ) to your text. Here is my ProductCard view.


2 Answers

Starting iOS 11, this finally becomes possible with SKLabelNode:

    let lb = SKLabelNode(fontNamed: "Copperplate")
    lb.text = "Put your long text here..."
    lb.numberOfLines = 0
    lb.preferredMaxLayoutWidth = 1000
like image 150
Mike Keskinov Avatar answered Sep 27 '22 21:09

Mike Keskinov


There is a Github solution over here as SKLabelNodes do not support multiple lines.

Code quoted:

import SpriteKit

class SKMultilineLabel: SKNode {
//props
var labelWidth:Int {didSet {update()}}
var labelHeight:Int = 0
var text:String {didSet {update()}}
var fontName:String {didSet {update()}}
var fontSize:CGFloat {didSet {update()}}
var pos:CGPoint {didSet {update()}}
var fontColor:UIColor {didSet {update()}}
var leading:Int {didSet {update()}}
var alignment:SKLabelHorizontalAlignmentMode {didSet {update()}}
var dontUpdate = false
var shouldShowBorder:Bool = false {didSet {update()}}
//display objects
var rect:SKShapeNode?
var labels:[SKLabelNode] = []

init(text:String, labelWidth:Int, pos:CGPoint, fontName:String="ChalkboardSE-Regular",fontSize:CGFloat=10,fontColor:UIColor=UIColor.blackColor(),leading:Int=10, alignment:SKLabelHorizontalAlignmentMode = .Center, shouldShowBorder:Bool = false)
{
    self.text = text
    self.labelWidth = labelWidth
    self.pos = pos
    self.fontName = fontName
    self.fontSize = fontSize
    self.fontColor = fontColor
    self.leading = leading
    self.shouldShowBorder = shouldShowBorder
    self.alignment = alignment

    super.init()

    self.update()
}

//if you want to change properties without updating the text field,
//  set dontUpdate to false and call the update method manually.
func update() {
    if (dontUpdate) {return}
    if (labels.count>0) {
        for label in labels {
            label.removeFromParent()
        }
        labels = []
    }
    let separators = NSCharacterSet.whitespaceAndNewlineCharacterSet()
    let words = text.componentsSeparatedByCharactersInSet(separators)

    let len = countElements(text)

    var finalLine = false
    var wordCount = -1
    var lineCount = 0
    while (!finalLine) {
        lineCount++
        var lineLength = CGFloat(0)
        var lineString = ""
        var lineStringBeforeAddingWord = ""

        // creation of the SKLabelNode itself
        var label = SKLabelNode(fontNamed: fontName)
        // name each label node so you can animate it if u wish
        label.name = "line\(lineCount)"
        label.horizontalAlignmentMode = alignment
        label.fontSize = fontSize
        label.fontColor = UIColor.whiteColor()

        while lineLength < CGFloat(labelWidth)
        {
            wordCount++
            if wordCount > words.count-1
            {
                //label.text = "\(lineString) \(words[wordCount])"
                finalLine = true
                break
            }
            else
            {
                lineStringBeforeAddingWord = lineString
                lineString = "\(lineString) \(words[wordCount])"
                label.text = lineString
                lineLength = label.width
            }
        }
        if lineLength > 0 {
            wordCount--
            if (!finalLine) {
                lineString = lineStringBeforeAddingWord
            }
            label.text = lineString
            var linePos = pos
            if (alignment == .Left) {
                linePos.x -= CGFloat(labelWidth / 2)
            } else if (alignment == .Right) {
                linePos.x += CGFloat(labelWidth / 2)
            }
            linePos.y += CGFloat(-leading * lineCount)
            label.position = CGPointMake( linePos.x , linePos.y )
            self.addChild(label)
            labels.append(label)
            //println("was \(lineLength), now \(label.width)")
        }

    }
    labelHeight = lineCount * leading
    showBorder()
}
func showBorder() {
    if (!shouldShowBorder) {return}
    if let rect = self.rect {
        self.removeChildrenInArray([rect])
    }
    self.rect = SKShapeNode(rectOfSize: CGSize(width: labelWidth, height: labelHeight))
    if let rect = self.rect {
        rect.strokeColor = UIColor.whiteColor()
        rect.lineWidth = 1
        rect.position = CGPoint(x: pos.x, y: pos.y - (CGFloat(labelHeight) / 2.0))
        self.addChild(rect)
    }

}
}

EDIT: You might as well check this version too as it's updated for Swift2

like image 20
Akaino Avatar answered Sep 27 '22 21:09

Akaino