Search code examples
ioscocoa-touchios7uitextviewtextkit

iOS7 TextKit: bullet point alignment


I'm writing an app for iOS 7 only and I'm trying to get decent formatting on bullet points in a non-editable UITextView.

It's easy enough to just insert a bullet point character, but of course the left indentation won't follow. What's the easiest way on iOS 7 to set a left indent after a bullet point?

Thanks in advance,

Frank


Solution

  • Below it the code I use to set a bulleted paragraph. This comes straight out of a working app and is used to apply the style to the entire paragraph in response to a user clicking on a formatting button. I have tried to put in all the dependent methods but may have missed some.

    Note that I am setting most indents in centimetres and hence the use of the conversion functions at the end of the listing.

    I am also checking for the presence of a tab character (no tab key on iOS!) and automatically insert a dash and a tab.

    If all you need is the paragraph style then look at the last few methods below where the firstLineIndent etc get set up.

    Note that these calls all get wrapped in [textStorage beginEditing/endEditing]. Despite the (IBAction) below the method is not getting called by a UI object directly.

            - (IBAction) styleBullet1:(id)sender
            {
                NSRange charRange = [self rangeForUserParagraphAttributeChange];
                NSTextStorage *myTextStorage = [self textStorage];
    
                // Check for "-\t" at beginning of string and add if not found
                NSAttributedString *attrString = [myTextStorage attributedSubstringFromRange:charRange];
                NSString *string = [attrString string];
    
                if ([string rangeOfString:@"\t"].location == NSNotFound) {
                    NSLog(@"string does not contain tab so insert one");
                    NSAttributedString * aStr = [[NSAttributedString alloc] initWithString:@"-\t"];
                    // Insert a bullet and tab
                    [[self textStorage] insertAttributedString:aStr atIndex:charRange.location];
    
                } else {
                    NSLog(@"string contains tab");
                }
    
                if ([self isEditable] && charRange.location != NSNotFound)
                {
                    [myTextStorage setAttributes:[self bullet1Style] range:charRange];
                }
            }
    
            - (NSDictionary*)bullet1Style
            {
                return [self createStyle:[self getBullet1ParagraphStyle] font:[self normalFont] fontColor:[UIColor blackColor] underlineStyle:NSUnderlineStyleNone];
    
            }
    
            - (NSDictionary*)createStyle:(NSParagraphStyle*)paraStyle font:(UIFont*)font fontColor:(UIColor*)color underlineStyle:(int)underlineStyle
            {
                NSMutableDictionary *style = [[NSMutableDictionary alloc] init];
                [style setValue:paraStyle forKey:NSParagraphStyleAttributeName];
                [style setValue:font forKey:NSFontAttributeName];
                [style setValue:color forKey:NSForegroundColorAttributeName];
                [style setValue:[NSNumber numberWithInt: underlineStyle] forKey:NSUnderlineStyleAttributeName];
    
                FLOG(@" font is %@", font);
    
                return style;
            }
    
            - (NSParagraphStyle*)getBullet1ParagraphStyle
            {
                NSMutableParagraphStyle *para;
                para = [self getDefaultParagraphStyle];
                NSMutableArray *tabs = [[NSMutableArray alloc] init];
                [tabs addObject:[[NSTextTab alloc] initWithTextAlignment:NSTextAlignmentLeft location:[self ptsFromCMF:1.0] options:nil]];
                //[tabs addObject:[[NSTextTab alloc] initWithType:NSLeftTabStopType location:[self ptsFromCMF:1.0]]];
                [para setTabStops:tabs];
                [para setDefaultTabInterval:[self ptsFromCMF:2.0]];
                [para setFirstLineHeadIndent:[self ptsFromCMF:0.0]];
                //[para setHeaderLevel:0];
                [para setHeadIndent:[self ptsFromCMF:1.0]];
                [para setParagraphSpacing:3];
                [para setParagraphSpacingBefore:3];
                return para;
            }
        - (NSMutableParagraphStyle*)getDefaultParagraphStyle
        {
            NSMutableParagraphStyle *para;
            para = [[NSParagraphStyle defaultParagraphStyle]mutableCopy];
            [para setTabStops:nil];
            [para setAlignment:NSTextAlignmentLeft];
            [para setBaseWritingDirection:NSWritingDirectionLeftToRight];
            [para setDefaultTabInterval:[self ptsFromCMF:3.0]];
            [para setFirstLineHeadIndent:0];
            //[para setHeaderLevel:0];
            [para setHeadIndent:0.0];
            [para setHyphenationFactor:0.0];
            [para setLineBreakMode:NSLineBreakByWordWrapping];
            [para setLineHeightMultiple:1.0];
            [para setLineSpacing:0.0];
            [para setMaximumLineHeight:0];
            [para setMinimumLineHeight:0];
            [para setParagraphSpacing:6];
            [para setParagraphSpacingBefore:3];
            //[para setTabStops:<#(NSArray *)#>];
            [para setTailIndent:0.0];
            return para;
        }
    -(NSNumber*)ptsFromCMN:(float)cm
    {
        return [NSNumber numberWithFloat:[self ptsFromCMF:cm]];
    }
    -(float)ptsFromCMF:(float)cm
    {
        return cm * 28.3464567;
    }