TextureGroup / Texture

Smooth asynchronous user interfaces for iOS apps.
https://texturegroup.org/
Other
8.01k stars 1.29k forks source link

[ASTextNode] slash symbol in string acts like new line symbol #173

Open garrettmoon opened 7 years ago

garrettmoon commented 7 years ago

From @iwheelbuy on January 10, 2017 17:53

I have some strings to be presented in ASTextNode

Optional("Дом ученых-А/В «Восточный» (Площадка отстоя)")
Optional("А/В «Восточный» (Площадка отстоя)-Дом ученых")
Optional("Площадка для отстоя а/в Восточный-Студенческий городок")
Optional("Студенческий городок-Площадка для отстоя а/в Восточный")

I don't expect a new line right after the / symbol, but the result is:

2017-01-11 0 50 49

Is there a way not to get new line after the /?

The cell code:

func tableNode(_ tableNode: ASTableNode, nodeForRowAt indexPath: IndexPath) -> ASCellNode {
    let route: TransportRouteObject? = object(connection: connection, mappings: mappings, indexPath: indexPath)
    let cell = ASCellNode()
    cell.selectionStyle = .none
    cell.backgroundColor = .white
    // text
    let text = ASTextNode()
    text.style.flexGrow = 1.0
    text.style.flexShrink = 1.0
    text.backgroundColor = .orange
    text.style.width = ASDimension(unit: ASDimensionUnit.fraction, value: 1.0)
    text.maximumNumberOfLines = 0
    debugPrint(route?.title)
    let textString = NSAttributedString(
        string: route?.title ?? "Надпись",
        attributes: [NSFontAttributeName:UIFont.systemFont(ofSize: 16.0)]
    )
    text.attributedText = textString
    cell.addSubnode(text)
    // code
    let code = ASTextNode()
    code.maximumNumberOfLines = 1
    let codeString = NSAttributedString(
        string: "17",
        attributes: [NSFontAttributeName:UIFont.boldSystemFont(ofSize: 26.0)]
    )
    code.attributedText = codeString
    cell.addSubnode(code)
    //
    cell.layoutSpecBlock = { [unowned text] _ in
        let spec0 = ASStackLayoutSpec(direction: ASStackLayoutDirection.horizontal, spacing: 0, justifyContent: ASStackLayoutJustifyContent.center, alignItems: ASStackLayoutAlignItems.center, children: [code])
        spec0.style.width = ASDimension(unit: ASDimensionUnit.points, value: 60.0)
        let spec1 = ASStackLayoutSpec(direction: ASStackLayoutDirection.horizontal, spacing: 0, justifyContent: ASStackLayoutJustifyContent.start, alignItems: ASStackLayoutAlignItems.center, children: [text])
        spec1.style.flexGrow = 1.0
        spec1.style.flexShrink = 1.0
        let spec2 = ASStackLayoutSpec(direction: ASStackLayoutDirection.horizontal, spacing: 0, justifyContent: ASStackLayoutJustifyContent.start, alignItems: ASStackLayoutAlignItems.center, children: [spec0, spec1])
        return ASInsetLayoutSpec(insets: UIEdgeInsets.init(top: 5.0, left: 0.0, bottom: 5.0, right: 5.0), child: spec2)
    }
    return cell
}

Copied from original issue: facebookarchive/AsyncDisplayKit#2885

garrettmoon commented 7 years ago

From @hannahmbanana on January 10, 2017 22:48

@iwheelbuy - could you check if this matches the behavior of UILabel?

garrettmoon commented 7 years ago

From @iwheelbuy on January 11, 2017 16:15

UILabel is fine

if (route?.title ?? "").contains("ый» (Площадка отстоя)-Дом учен") {
    let label = UILabel.init(frame: UIScreen.main.bounds)
    label.backgroundColor = .white
    label.numberOfLines = 0
    label.text = route?.title
    UIApplication.shared.keyWindow?.addSubview(label)
}
2017-01-11 23 12 28
garrettmoon commented 7 years ago

From @iwheelbuy on January 11, 2017 16:49

That is the page I parse information from: http://mu-kgt.ru/informing/wapold/marsh/?t=1 I use String.Encoding.windowsCP1251 to convert from data to string

garrettmoon commented 7 years ago

From @hannahmbanana on January 12, 2017 19:47

@iwheelbuy - would you be willing to create an example project (or modify examples/layoutSpecExamples-Swift/LayoutExampleNode.swift - class HeaderWithRightAndLeftItems) to show this bug? I'm guessing it has something to do with the string encoding which I'm not too familiar with.

garrettmoon commented 7 years ago

From @iwheelbuy on January 15, 2017 13:38

Sample project is a bit complex, but it shows the issue. pod install -> run -> tap on "Автобус"

garrettmoon commented 7 years ago

From @Jonhory on March 17, 2017 9:45

Demo show the issue.

garrettmoon commented 7 years ago

From @iwheelbuy on March 17, 2017 9:48

Jonhory, there is a broken link in your demo readme

garrettmoon commented 7 years ago

From @Jonhory on March 18, 2017 4:56

My Demo update.

UPDATE:

PNG show the issue:

Here is my code:

func loadTextNode(y: CGFloat, with text: String) {
    let textNode = ASTextNode()
    textNode.attributedText = NSAttributedString(string: text,
                                                 attributes: [NSFontAttributeName: UIFont.systemFont(ofSize: 16),
                                                              NSForegroundColorAttributeName: UIColor.red])
    textNode.frame = CGRect(x: 100, y: y, width: 200, height: 20)
    textNode.backgroundColor = UIColor.blue
    view.addSubnode(textNode)
}
func loadUILabel(y: CGFloat, with text: String) {
    let label = UILabel()
    label.text = text
    label.textColor = UIColor.blue
    label.backgroundColor = UIColor.red
    label.frame = CGRect(x: 100, y: y, width: 200, height: 20)
    view.addSubview(label)
}

If my code have any question, maybe somebody can help me.Thanks.

smeis commented 7 years ago

I know this issue is originally pretty old but I thought it was interesting and maybe someone runs into this in the future.

The difference in behavior between ASTextNode and UILabel observed in the Demo app is caused by the fact that the default truncation settings are different. UILabel has NSLineBreakByTruncatingTail as default and ASTextNode has NSLineBreakByWordWrapping as default. If you set truncationMode to NSLineBreakByTruncatingTail it will behave in the same manner as UILabel.

I did note that ASTextNode and UILabel behave differently when NSLineBreakByWordWrapping is used. In the case of ASTextNode a default character set (https://github.com/TextureGroup/Texture/blob/master/Source/TextKit/ASTextKitRenderer.mm#L76) is being used to determine a truncation point other than the end of the visible character range.

In the comments it's assumed this is a whitespace or a newline (https://github.com/TextureGroup/Texture/blob/master/Source/TextKit/ASTextKitTailTruncater.mm#L134) but ASTextKitRenderer provides a default character set for finding a 'correct' truncation point in a string (). This default set contains the characters .,!?:; next to whitespaces in newlines. This would cause a string like test.string or test:string to be truncated differently.

@Adlai-Holler I think you're the persion to talk to about everything textkit related right? Do you know if the difference in behavior for NSLineBreakByWordWrapping is intentional?

maicki commented 7 years ago

@smeis This is related: https://github.com/TextureGroup/Texture/issues/227