web-dev-qa-db-ja.com

iOS7 TextKit:箇条書きの配置

私はiOS7専用のアプリを書いていますが、編集不可能なUITextViewの箇条書きで適切なフォーマットを取得しようとしています。

箇条書きの文字を挿入するだけで簡単ですが、もちろん左のインデントは続きません。 iOS 7で、箇条書きの後に左インデントを設定する最も簡単な方法は何ですか?

前もって感謝します、

フランク

19
Frank R.

その下に、箇条書きの段落を設定するために使用するコードがあります。これは、動作中のアプリから直接取得され、ユーザーが書式設定ボタンをクリックしたことに応答して、段落全体にスタイルを適用するために使用されます。私はすべての依存メソッドを入れようとしましたが、いくつかを逃した可能性があります。

ほとんどのインデントをセンチメートルで設定しているため、リストの最後に変換関数を使用していることに注意してください。

また、タブ文字(iOSではタブキーがありません!)の存在を確認し、ダッシュとタブを自動的に挿入します。

必要なのが段落スタイルだけの場合は、firstLineIndentなどが設定される以下の最後のいくつかのメソッドを見てください。

これらの呼び出しはすべて[textStorage beginEditing/endEditing]でラップされることに注意してください。以下の(IBAction)にもかかわらず、メソッドはUIオブジェクトによって直接呼び出されていません。

        - (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;
}
9

だから私は周りを見回しました、そしてこれはそれを機能させるためにダンカンの答えから抽出された最小限のコードです:

NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:yourLabel.text];

NSMutableParagraphStyle *paragrahStyle = [[NSMutableParagraphStyle alloc] init];
[paragrahStyle setParagraphSpacing:4];
[paragrahStyle setParagraphSpacingBefore:3];
[paragrahStyle setFirstLineHeadIndent:0.0f];  // First line is the one with bullet point
[paragrahStyle setHeadIndent:10.5f];    // Set the indent for given bullet character and size font

[attributedString addAttribute:NSParagraphStyleAttributeName value:paragrahStyle
                         range:NSMakeRange(0, [self.descriptionLabel.text length])];

yourLabel.attributedText = attributedString;

そして、これが私のアプリでの結果です:

Quadratic Master

45
Lukas Petr

これは私が見つけた最も簡単な解決策です:

let bulletList = UILabel()
let bulletListArray = ["line 1 - enter a bunch of lorem ipsum here so it wraps to the next line", "line 2", "line 3"]
let joiner = "\n"

var paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.headIndent = 10
paragraphStyle.firstLineHeadIndent = 0

let attributes = [NSParagraphStyleAttributeName: paragraphStyle]
let bulletListString = joiner.join(bulletListArray.map { "• \($0)" })

bulletList.attributedText = NSAttributedString(string: bulletListString, attributes: attributes)

配列内の各文字列は「段落」のように機能し、段落スタイルは最初の行で0のインデントを取得し、mapメソッドを使用して箇条書きを追加します。その後、10 pxのインデントを取得した後のすべての行(間隔を調整)フォントメトリック用)

8
thisispete

他の答えは、一定の値でインデントサイズを設定することに依存しています。つまり、フォントを変更する場合は手動で更新する必要があり、動的タイプを使用している場合はうまく機能しません。幸い、テキストの測定は簡単です。

いくつかのテキストといくつかの属性があるとしましょう:

NSString *text = @"• Some bulleted paragraph";
UIFont *font = [UIFont preferredFontForTextStyle:UIFontTextStyleBody];
NSDictionary *attributes = @{NSFontAttributeName: font};

弾丸を測定し、それに応じて段落スタイルを作成する方法は次のとおりです。

NSString *bulletPrefix = @"• ";
CGSize size = [bulletPrefix sizeWithAttributes:attributes];
NSMutableParagraphStyle *paragraphStyle = [NSMutableParagraphStyle new];
paragraphStyle.headIndent = size.width;

これを属性に挿入し、属性付き文字列を作成します。

NSMutableDictionary *indentedAttributes = [attributes mutableCopy];
indentedAttributes[NSParagraphStyleAttributeName] = [paragraphStyle copy];
NSAttributedString *attributedString = [[NSAttributedString alloc] initWithString:text attributes:indentedAttributes];
6
skagedal

Swift 4

NSAttributedStringの拡張機能を作成し、さまざまなタイプのリストを適切にインデントする便利な初期化子を追加しました。

extension NSAttributedString {

    convenience init(listString string: String, withFont font: UIFont) {
        self.init(attributedListString: NSAttributedString(string: string), withFont: font)
    }

    convenience init(attributedListString attributedString: NSAttributedString, withFont font: UIFont) {
        guard let regex = try? NSRegularExpression(pattern: "^(\\d+\\.|[•\\-\\*])(\\s+).+$",
                                                   options: [.anchorsMatchLines]) else { fatalError() }
        let matches = regex.matches(in: attributedString.string, options: [],
                                    range: NSRange(location: 0, length: attributedString.string.utf16.count))
        let nsString = attributedString.string as NSString
        let mutableAttributedString = NSMutableAttributedString(attributedString: attributedString)

        for match in matches {
            let size = NSAttributedString(
                string: nsString.substring(with: match.range(at: 1)) + nsString.substring(with: match.range(at: 2)),
                attributes: [.font: font]).size()
            let indentation = ceil(size.width)
            let range = match.range(at: 0)

            let paragraphStyle = NSMutableParagraphStyle()

            if let style = attributedString.attribute(.paragraphStyle, at: 0, longestEffectiveRange: nil, in: range)
                as? NSParagraphStyle {
                paragraphStyle.setParagraphStyle(style)
            }

            paragraphStyle.tabStops = [NSTextTab(textAlignment: .left, location: indentation, options: [:])]
            paragraphStyle.defaultTabInterval = indentation
            paragraphStyle.firstLineHeadIndent = 0
            paragraphStyle.headIndent = indentation

            mutableAttributedString.addAttribute(.font, value: font, range: range)
            mutableAttributedString.addAttribute(.paragraphStyle, value: paragraphStyle, range: range)
        }

        self.init(attributedString: mutableAttributedString)
    }
}

使用例: How the convenience initializer is used

各弾丸の後のスペースの数などは関係ありません。コードは、弾丸の後に配置することを決定したタブまたはスペースの数に基づいて、適切なインデント幅を動的に計算します。

属性付き文字列にすでに段落スタイルがある場合、コンビニエンスイニシャライザはその段落スタイルのオプションを保持し、独自のオプションをいくつか適用します。

サポートされている記号:•、-、*、数字の後にピリオドが続く(例:8)

3
Toni Sučić

この簡単なことは、属性インスペクターを使用して、インデントフィールドを選択し、やりたい変更をすべて行うことができます:)

enter image description here

2
Infaz

Lukasの実装に基づいてSwiftソリューション(現時点ではSwift 2.3)を作成しました。箇条書きのない行に少し問題があったので、オプションで渡すことができるように拡張を作成しました段落スタイルを適用する範囲。

extension String{

    func getAllignedBulletPointsMutableString(bulletPointsRange: NSRange = NSMakeRange(0, 0)) -> NSMutableAttributedString{

        let attributedString: NSMutableAttributedString = NSMutableAttributedString(string: self)
        let paragraphStyle = NSMutableParagraphStyle()
        paragraphStyle.paragraphSpacing = 0
        paragraphStyle.paragraphSpacingBefore = 0
        paragraphStyle.firstLineHeadIndent = 0
        paragraphStyle.headIndent = 7.5

        attributedString.addAttributes([NSParagraphStyleAttributeName: paragraphStyle], range: bulletPointsRange)
        return attributedString
    }

}
0
Swift Rabbit

thisispete のソリューションに基づいて、Swift 4.2に更新されました。

Swift 4.2

let array = ["1st", "2nd", "3rd"]
let textView = UITextView()
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.firstLineHeadIndent = 0
paragraphStyle.headIndent = 12
let bulletListText = array.map { "• \($0)" }.joined(separator: "\n")
let attributes = [
    NSAttributedString.Key.paragraphStyle: paragraphStyle,
    NSAttributedString.Key.font: UIFont.systemFont(ofSize: 17.0)
]
textView.attributedText = NSAttributedString(string: bulletListText, attributes: attributes)
0
Jayden Irwin