iphone UITextView установить межстрочный интервал - PullRequest
14 голосов
/ 25 ноября 2010

Как я могу увеличить пространство строк в UITextView, чтобы оно выглядело как приложение «Заметки» в iPhone?

Ответы [ 8 ]

25 голосов
/ 21 октября 2012

Что ж, теперь на iOS6 есть возможность, используя NSParagraphStyle, но она очень плохо документирована и, кажется, работает редко.

Я сейчас работаю над этим так:

UITextView *lab = [LocalTexts objectAtIndex:j];

NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
paragraphStyle.lineHeightMultiple = 50.0f;
paragraphStyle.maximumLineHeight = 50.0f;
paragraphStyle.minimumLineHeight = 50.0f;

NSString *string = lab.text;
NSDictionary *ats = @{
    NSFontAttributeName: [UIFont fontWithName:@"DIN Medium" size:16.0f],
    NSParagraphStyleAttributeName: paragraphStyle, 
};

lab.attributedText = [[NSAttributedString alloc] initWithString:string attributes:ats];

Проблема в том, что при установке шрифта высота строки перестает работать. Очень странно. Я еще не нашел решения для этого.

Также вы можете создать пользовательский вид Attributed CoreText ... но он более технический, вы можете найти демонстрацию того, как это делается здесь

Ну, я надеюсь, что-то поможет.

15 голосов
/ 20 января 2018

В Swift 4 и iOS 11, в зависимости от ваших потребностей, вы можете выбрать одну из 3 следующих реализаций , чтобы решить вашу проблему.


# 1. Использование String и UIFontDescriptorSymbolicTraits traitLooseLeading свойство

traitLooseLeading имеет следующую декларацию:

Шрифт использует более свободные начальные значения.

static var traitLooseLeading: UIFontDescriptorSymbolicTraits { get }

В следующем коде показано, как реализовать traitLooseLeading, чтобы получить более свободный шрифт, ведущий к вашему UItextView.

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        let textView = UITextView()
        view.addSubview(textView)

        textView.text = """
        Lorem ipsum
        Dolor sit amet,
        consectetur adipiscing elit
        """

        if let fontDescriptor = UIFontDescriptor
            .preferredFontDescriptor(withTextStyle: UIFontTextStyle.body)
            .withSymbolicTraits(UIFontDescriptorSymbolicTraits.traitLooseLeading) {
            let looseLeadingFont = UIFont(descriptor: fontDescriptor, size: 0)
            textView.font = looseLeadingFont
        }

        // Layout textView
        textView.translatesAutoresizingMaskIntoConstraints = false
        textView.topAnchor.constraint(equalTo: view.readableContentGuide.topAnchor).isActive = true
        textView.bottomAnchor.constraint(equalTo: view.readableContentGuide.bottomAnchor).isActive = true
        textView.leadingAnchor.constraint(equalTo: view.readableContentGuide.leadingAnchor).isActive = true
        textView.trailingAnchor.constraint(equalTo: view.readableContentGuide.trailingAnchor).isActive = true
    }

}

# 2. Использование NSAttributedString и NSMutableParagraphStyle lineSpacing свойство

lineSpacing имеет следующую декларацию:

Расстояние в пунктах между нижней частью одного фрагмента строки и вершиной следующей.

var lineSpacing: CGFloat { get set }

В следующем коде показано, как реализовать lineSpacing, чтобы иметь определенный межстрочный интервал для некоторого приписанного текста в вашем UItextView.

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        let string = """
        Lorem ipsum
        Dolor sit amet,
        consectetur adipiscing elit
        """

        let paragraphStyle = NSMutableParagraphStyle()
        paragraphStyle.lineSpacing = 15

        let attributes: [NSAttributedStringKey: Any] = [NSAttributedStringKey.paragraphStyle: paragraphStyle]
        let attributedString = NSAttributedString(string: string, attributes: attributes)

        let textView = UITextView()
        textView.attributedText = attributedString
        view.addSubview(textView)

        // Layout textView
        textView.translatesAutoresizingMaskIntoConstraints = false
        textView.topAnchor.constraint(equalTo: view.readableContentGuide.topAnchor).isActive = true
        textView.bottomAnchor.constraint(equalTo: view.readableContentGuide.bottomAnchor).isActive = true
        textView.leadingAnchor.constraint(equalTo: view.readableContentGuide.leadingAnchor).isActive = true
        textView.trailingAnchor.constraint(equalTo: view.readableContentGuide.trailingAnchor).isActive = true
    }

}

# 3. Используя String и NSLayoutManagerDelegate протокол layoutManager(_:lineSpacingAfterGlyphAt:withProposedLineFragmentRect:) метод

layoutManager(_:lineSpacingAfterGlyphAt:withProposedLineFragmentRect:) имеет следующую декларацию:

Возвращает интервал после строки, заканчивающейся указанным индексом глифа. [...] Это сообщение отправляется во время размещения каждой строки, чтобы делегат менеджера макета мог настроить форму линии.

optional func layoutManager(_ layoutManager: NSLayoutManager, lineSpacingAfterGlyphAt glyphIndex: Int, withProposedLineFragmentRect rect: CGRect) -> CGFloat

В следующем коде показано, как реализовать layoutManager(_:lineSpacingAfterGlyphAt:withProposedLineFragmentRect:) чтобы иметь определенный межстрочный интервал для вашего UItextView.

import UIKit

class ViewController: UIViewController, NSLayoutManagerDelegate {

    override func viewDidLoad() {
        super.viewDidLoad()

        let textView = UITextView()
        textView.layoutManager.delegate = self
        view.addSubview(textView)

        textView.text = """
        Lorem ipsum
        Dolor sit amet,
        consectetur adipiscing elit
        """

        // Layout textView
        textView.translatesAutoresizingMaskIntoConstraints = false
        textView.topAnchor.constraint(equalTo: view.readableContentGuide.topAnchor).isActive = true
        textView.bottomAnchor.constraint(equalTo: view.readableContentGuide.bottomAnchor).isActive = true
        textView.leadingAnchor.constraint(equalTo: view.readableContentGuide.leadingAnchor).isActive = true
        textView.trailingAnchor.constraint(equalTo: view.readableContentGuide.trailingAnchor).isActive = true
    }

    // MARK: - NSLayoutManagerDelegate

    func layoutManager(_ layoutManager: NSLayoutManager, lineSpacingAfterGlyphAt glyphIndex: Int, withProposedLineFragmentRect rect: CGRect) -> CGFloat {
        return 15
    }

}

В качестве альтернативы предыдущему коду, следующий код показывает, как реализовать layoutManager(_:lineSpacingAfterGlyphAt:withProposedLineFragmentRect:) в подклассе UITextView.

import UIKit

class LineSpacingTextView: UITextView, NSLayoutManagerDelegate {

    override init(frame: CGRect, textContainer: NSTextContainer?) {
        super.init(frame: frame, textContainer: textContainer)
        layoutManager.delegate = self
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    // MARK: - NSLayoutManagerDelegate

    func layoutManager(_ layoutManager: NSLayoutManager, lineSpacingAfterGlyphAt glyphIndex: Int, withProposedLineFragmentRect rect: CGRect) -> CGFloat {
        return 15
    }

}
import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        let textView = LineSpacingTextView()
        view.addSubview(textView)

        textView.text = """
        Lorem ipsum
        Dolor sit amet,
        consectetur adipiscing elit
        """

        // Layout textView
        textView.translatesAutoresizingMaskIntoConstraints = false
        textView.topAnchor.constraint(equalTo: view.readableContentGuide.topAnchor).isActive = true
        textView.bottomAnchor.constraint(equalTo: view.readableContentGuide.bottomAnchor).isActive = true
        textView.leadingAnchor.constraint(equalTo: view.readableContentGuide.leadingAnchor).isActive = true
        textView.trailingAnchor.constraint(equalTo: view.readableContentGuide.trailingAnchor).isActive = true
    }

}
11 голосов
/ 30 апреля 2014

Чтобы изменить межстрочный интервал:

NSString *textViewText =self.myTextView.text;

NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:textViewText];
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
paragraphStyle.lineSpacing = 30;
NSDictionary *dict = @{NSParagraphStyleAttributeName : paragraphStyle };
[attributedString addAttributes:dict range:NSMakeRange(0, [textViewText length])];

self.myTextView.attributedText = attributedString;
9 голосов
/ 25 ноября 2010

Достаточно взглянуть на документацию для UITextView, чтобы определить, что изменение межстрочного интервала не поддерживается этим элементом управления.

Для iOS 6 и выше:

Есть возможность, используя NSParagraphStyle,

NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
paragraphStyle.lineHeightMultiple = 50.0f;
paragraphStyle.maximumLineHeight = 50.0f;
paragraphStyle.minimumLineHeight = 50.0f;
NSString *string = @"your paragraph here";
NSDictionary *attribute = @{
   NSParagraphStyleAttributeName : paragraphStyle, 
   };
[textview setFont:[uifont fontwithname:@"Arial" size:20.0f]];
textview.attributedText = [[NSAttributedString alloc] initWithString:string attributes:attribute];
5 голосов
/ 05 мая 2016

Для Swift 2.2

let paragraphStyle: NSMutableParagraphStyle = NSMutableParagraphStyle()
paragraphStyle.lineHeightMultiple = 20.0
paragraphStyle.maximumLineHeight = 20.0
paragraphStyle.minimumLineHeight = 20.0
let ats = [NSFontAttributeName: UIFont(name: "Helvetica Neue", size: 11.0)!, NSParagraphStyleAttributeName: paragraphStyle]
cell.textView.attributedText = NSAttributedString(string: "you string here", attributes: ats)
4 голосов
/ 30 марта 2016

Если конечным результатом является увеличение межстрочного интервала, вы можете сделать это прямо в конструкторе интерфейсов.Установите для свойства Text значение «Attributed», а затем нажмите ... справа.Установка свойства Spacing должна корректно обновлять межстрочный интервал.

1 голос
/ 11 марта 2016

В нескольких ответах выше атрибут lineHeightMultiple используется неправильно:

paragraphStyle.lineHeightMultiple = 50.0f;

Следуя официальной документации lineHeightMultiple является множителем, а не абсолютной высотой строки:

Естественная высота линии приемника умножается на этот коэффициент (если он положительный) до ограничения минимальной и максимальной высотой строки.Значение по умолчанию этого свойства - 0.0.https://developer.apple.com/library/prerelease/ios/documentation/Cocoa/Reference/ApplicationKit/Classes/NSParagraphStyle_Class/index.html#//apple_ref/occ/instp/NSParagraphStyle/maximumLineHeight

При этом код ниже:

paragraphStyle.lineHeightMultiple = 50.0f;
paragraphStyle.maximumLineHeight = 50.0f;
paragraphStyle.minimumLineHeight = 50.0f;

эквивалентен

paragraphStyle.lineHeight = 50.0f
0 голосов
/ 01 марта 2013
 NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
   paragraphStyle.lineHeightMultiple = 50.0f;
   paragraphStyle.maximumLineHeight = 50.0f;
   paragraphStyle.minimumLineHeight = 50.0f;
     NSString *string = @"if you want reduce or increase space between lines in uitextview ,you can do this with this,but donot set font on this paragraph , set this on uitextveiw.";

    NSDictionary *ats = @{
   NSParagraphStyleAttributeName : paragraphStyle, 
     };

    [textview setFont:[uifont fontwithname:@"Arial" size:20.0f]];
    textview.attributedText = [[NSAttributedString alloc] initWithString:string attributes:ats];
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...