Aligning half line to the left and the second to the right in CoreText
Asked Answered
P

4

8

I am creating a Point-of-Sale (POS) receipt and need to have item names with a certain width and need to have a price on the right (like float-right in CSS).

I am using https://github.com/FuerteInternational/FTCoreText to create the content. Any ideas how to achieve this without having to create two views and place them on top of each other?

Just to clarify, I need to have this:

Coffee                  £1.45
   milk, skinny
Danish Pastry           £1.75
Coca Cola               £1.10
Full English Bfst      £12.50

So pretty much I need a string to be floating on the left and other string floating on the right ...

Paphlagonia answered 18/12, 2013 at 9:48 Comment(2)
I don't think there is a way to do that without having two objects, one with left alignment and one with right alignment. Even CSS would require two objects to achieve this.Donniedonnish
we need 2 objects either in HTML & CSS or our native code. I agree with @BrianShamblen. Best thing is go for web view with HTML and CSS.Giorgi
L
1

The only thing I can think of is inserting in each string f.e. 30 spaces after the first string and assigning wordWrap = truncate middle. Not so sure that this is exactly what you're looking for.

I agree with Brian Shamblen it'l be pretty easy to do with 2 labels.

Landon answered 20/12, 2013 at 16:40 Comment(0)
O
1

It looks like what you want isn't really a second column, which Core Text cannot do out of the box, but rather a tabular layout (like good ol' <table>). Fortunately tabular layout can be acheived in Core Text by using tab stops. The only 2 things you need are:

  • the CHARACTER TABULATION (U+0009) character,
  • and a paragraph style with the correct tab stops setting.

That can be done this way:

NSString *string = @"Coffee\t£1.45\n  milk, skinny\nDanish Pastry\t£1.75\nCoca Cola\t£1.10\nFull English Bfst\t£12.50";
CGFloat width = 200;

NSArray *tabs = @[CFBridgingRelease(CTTextTabCreate(kCTTextAlignmentRight, width, NULL))];
CTParagraphStyleSetting setting = {kCTParagraphStyleSpecifierTabStops, sizeof(tabs), &tabs};
CTParagraphStyleRef paragraphStyle = CTParagraphStyleCreate(&setting, 1);
NSDictionary *attributes = @{CFBridgingRelease(kCTParagraphStyleAttributeName): CFBridgingRelease(paragraphStyle)};
NSAttributedString *attributedString = [[NSAttributedString alloc] initWithString:string attributes:attributes];

There are two caveats:

  • You need to know the width of the view when creating the paragraph style.
  • Core Text won't wrap lines on tab stops which means you have to make sure your text is short enough to fit.
Otic answered 23/12, 2013 at 11:49 Comment(0)
C
0

Perhaps you could do the following with just one UILabel per line:

  • Define a left word like "Coffee" and a right one like "£1.45".

  • Make a string by concatenating the left word with a space and the right one.

  • Define the width and height of the frame that you want the label with that string to be contained in, with CGSizeMake(width, height).

  • Estimate the size of that label using sizeThatFits providing the CGSize constraints that you want as an argument.

  • If the estimated width of the label is smaller than the required width, increase the size of your label, by adding a space to your string and repeat.

In code:

NSArray *leftWords = @[@"Coffee", @"    milk, skinny", @"Danish Pastry", @"Coca Cola", @"Full English Bfst"];
    NSArray *rightWords = @[@"£1.45", @"", @"£1.75", @"£1.10", @"£12.50"];

    CGFloat xOffset = 5;
    CGFloat yOffset = 60;
    CGFloat labelHeight = 44;
    CGFloat labelWidth = 300;

    for (int i = 0; i < leftWords.count; i ++) {

        UILabel *aLabel = [[UILabel alloc] initWithFrame:CGRectMake(xOffset, yOffset + i * labelHeight, labelWidth, labelHeight)];
        aLabel.numberOfLines = 1;
        aLabel.textAlignment = NSTextAlignmentLeft;
        aLabel.layer.borderColor = [UIColor greenColor].CGColor;
        aLabel.layer.borderWidth = 1.0f;

        NSString *leftWord = [leftWords objectAtIndex:i];
        NSString *rightWord = [rightWords objectAtIndex:i];
        NSMutableString *spaces = [[NSMutableString alloc] initWithString:@" "];

        const CGFloat MAX_WIDTH = 310;
        CGSize maxLabelSize = CGSizeMake(MAX_WIDTH, CGFLOAT_MAX);

        CGSize expectedSize = CGSizeMake(0, 0);
        CGFloat expectedWidth = 0.0;

        NSString *phrase = @"";
        do {
            phrase = [NSString stringWithFormat:@"%@%@%@", leftWord, spaces, rightWord];
            aLabel.text = phrase;
            expectedSize = [aLabel sizeThatFits:maxLabelSize];
            expectedWidth = expectedSize.width;
            // Increase spaces
            [spaces appendString:@" "];

        } while (expectedWidth < MAX_WIDTH);

        CGRect frame = aLabel.frame;
        frame.size = expectedSize;
        aLabel.frame = frame;

        [self.view addSubview:aLabel];
    }

I have placed the above within my viewDidLoad and did #import <QuartzCore/QuartzCore.h> to allow marking of the border of the UILabel.

Here is a screenshot of my working code:

enter image description here

It works for the "milk, skinny" line too as the text alignment of the label is set to NSTextAlignmentLeft.

Colewort answered 27/12, 2013 at 11:59 Comment(0)
E
0

I recently came across this problem and found no answers.. so I created a class for anyone that needs it! Let's say you want to create a list of strings like the example in the question:

- (void)createReceipt {

    NSString *coffee = [LRString LRStringWithLeft:@"Coffee" right:@"£1.45" maxlength:29 maxleft:16 maxright:11];

}

This "coffee" string would look like this:

Coffee                  £1.45

"maxlength" is the maximum length of your string
"maxleft" is the maximum length of your left string (coffee)
"maxright" is the maximum length of your right string (price)

If the name exceeds the "maxleft" length, then the last 3 letters of the name (coffee) will be replaced with "..."

Check it out on GitHub here: https://github.com/iosdec/LRString

Exarchate answered 22/11, 2018 at 9:38 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.