私は次のようにプログラムで作成したUILabel
を持っています:
var label = UILabel()
次に、次のようなフォントを含むラベルのスタイリングを宣言しました。
label.frame = CGRect(x: 20, y: myHeaderView.frame.height / 2, width: 300, height: 30)
label.font = UIFont(name: "Typo GeoSlab Regular Demo", size: 15)
label.textColor = UIColor(hue: 0/360, saturation: 0/100, brightness: 91/100, alpha: 1)
ラベルの最初の部分は常に読み取ります:"Filter:"
の後に、文字列の別の部分が続きます。たとえば、「Most Popular」
Wordフィルターを太字にしたいので、全体は次のようになります。
フィルター:最も人気
このエフェクトを作成する最も簡単な方法が欲しいです。私はこれを達成する方法をインターネットで検索してきましたが、非常に多くの方法があり、コードのページのように見えるものもあります。そして、そのほとんどはObjective-Cにあるようです。 Swiftお願いします:)
私が正しい行にいるかどうかはわかりませんが、これはNSRange
が達成するのに役立ちますか?前もって感謝します
更新
一連のif
ステートメントを使用して、label
変数を変更します。といった:
if indexArray == 1 {
label.text = "Filter: Film name"
} else if indexArray == 2 {
label.text = "Filter: Most popular"
} else if indexArray == 3 {
label.text = "Filter: Star rating"
}
attributedString
を使用すると、文字列などの一部のスタイルを設定できます。これは、2つのスタイル(1つは標準、1つは太字)を設定し、それらを結合することで実行できます。
let boldText = "Filter:"
let attrs = [NSFontAttributeName : UIFont.boldSystemFontOfSize(15)]
let attributedString = NSMutableAttributedString(string:boldText, attributes:attrs)
let normalText = "Hi am normal"
let normalString = NSMutableAttributedString(string:normalText)
attributedString.appendAttributedString(normalString)
ラベルに割り当てる場合:
label.attributedText = attributedString
NSMutableAttributedStringとNSAttributedStringを使用して、カスタマイズされた文字列を作成できます。以下の関数は、指定された文字列で指定されたboldStringを太字にします。
Swift
func attributedText(withString string: String, boldString: String, font: UIFont) -> NSAttributedString {
let attributedString = NSMutableAttributedString(string: string,
attributes: [NSFontAttributeName: font])
let boldFontAttribute: [String: Any] = [NSFontAttributeName: UIFont.boldSystemFont(ofSize: font.pointSize)]
let range = (string as NSString).range(of: boldString)
attributedString.addAttributes(boldFontAttribute, range: range)
return attributedString
}
使用例
authorLabel.attributedText = attributedText(withString: String(format: "Author : %@", user.name), boldString: "Author", font: authorLabel.font)
Swift 4
func attributedText(withString string: String, boldString: String, font: UIFont) -> NSAttributedString {
let attributedString = NSMutableAttributedString(string: string,
attributes: [NSAttributedStringKey.font: font])
let boldFontAttribute: [NSAttributedStringKey: Any] = [NSAttributedStringKey.font: UIFont.boldSystemFont(ofSize: font.pointSize)]
let range = (string as NSString).range(of: boldString)
attributedString.addAttributes(boldFontAttribute, range: range)
return attributedString
}
Swift 4.2および5
func attributedText(withString string: String, boldString: String, font: UIFont) -> NSAttributedString {
let attributedString = NSMutableAttributedString(string: string,
attributes: [NSAttributedString.Key.font: font])
let boldFontAttribute: [NSAttributedString.Key: Any] = [NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: font.pointSize)]
let range = (string as NSString).range(of: boldString)
attributedString.addAttributes(boldFontAttribute, range: range)
return attributedString
}
結果:
Swift 4.2&5.0:
まず、UILabel
とUITextField
の両方が採用できるプロトコルを作成します。
_public protocol ChangableFont: AnyObject {
var text: String? { get set }
var attributedText: NSAttributedString? { get set }
var rangedAttributes: [RangedAttributes] { get }
func getFont() -> UIFont?
func changeFont(ofText text: String, with font: UIFont)
func changeFont(inRange range: NSRange, with font: UIFont)
func changeTextColor(ofText text: String, with color: UIColor)
func changeTextColor(inRange range: NSRange, with color: UIColor)
func resetFontChanges()
}
_
テキストに複数の変更を追加できるようにするため、rangedAttributes
プロパティを作成します。これは、属性とそれらが適用される範囲を保持するカスタム構造体です。
_public struct RangedAttributes {
let attributes: [NSAttributedString.Key: Any]
let range: NSRange
public init(_ attributes: [NSAttributedString.Key: Any], inRange range: NSRange) {
self.attributes = attributes
self.range = range
}
}
_
もう1つの問題は、UILabel
のfont
プロパティが強力で、UITextField
のfont
プロパティがweak/optionalであることです。両方をChangableFont
プロトコルで動作させるために、getFont() -> UIFont?
メソッドを含めます。
_extension UILabel: ChangableFont {
public func getFont() -> UIFont? {
return font
}
}
extension UITextField: ChangableFont {
public func getFont() -> UIFont? {
return font
}
}
_
これで、プロトコルを拡張して、UILabel
とUITextField
の両方のデフォルト実装を作成できます。
_public extension ChangableFont {
public var rangedAttributes: [RangedAttributes] {
guard let attributedText = attributedText else {
return []
}
var rangedAttributes: [RangedAttributes] = []
let fullRange = NSRange(
location: 0,
length: attributedText.string.count
)
attributedText.enumerateAttributes(
in: fullRange,
options: []
) { (attributes, range, stop) in
guard range != fullRange, !attributes.isEmpty else { return }
rangedAttributes.append(RangedAttributes(attributes, inRange: range))
}
return rangedAttributes
}
public func changeFont(ofText text: String, with font: UIFont) {
guard let range = (self.attributedText?.string ?? self.text)?.range(ofText: text) else { return }
changeFont(inRange: range, with: font)
}
public func changeFont(inRange range: NSRange, with font: UIFont) {
add(attributes: [.font: font], inRange: range)
}
public func changeTextColor(ofText text: String, with color: UIColor) {
guard let range = (self.attributedText?.string ?? self.text)?.range(ofText: text) else { return }
changeTextColor(inRange: range, with: color)
}
public func changeTextColor(inRange range: NSRange, with color: UIColor) {
add(attributes: [.foregroundColor: color], inRange: range)
}
private func add(attributes: [NSAttributedString.Key: Any], inRange range: NSRange) {
guard !attributes.isEmpty else { return }
var rangedAttributes: [RangedAttributes] = self.rangedAttributes
var attributedString: NSMutableAttributedString
if let attributedText = attributedText {
attributedString = NSMutableAttributedString(attributedString: attributedText)
} else if let text = text {
attributedString = NSMutableAttributedString(string: text)
} else {
return
}
rangedAttributes.append(RangedAttributes(attributes, inRange: range))
rangedAttributes.forEach { (rangedAttributes) in
attributedString.addAttributes(
rangedAttributes.attributes,
range: rangedAttributes.range
)
}
attributedText = attributedString
}
public func resetFontChanges() {
guard let text = text else { return }
attributedText = NSMutableAttributedString(string: text)
}
}
_
デフォルトの実装では、NSRange
のsubstring
を取得するための小さなヘルパーメソッドを使用します。
_public extension String {
public func range(ofText text: String) -> NSRange {
let fullText = self
let range = (fullText as NSString).range(of: text)
return range
}
}
_
完了です!これで、テキストの一部をそのフォントとテキストの色を変更できます。
_titleLabel.text = "Welcome"
titleLabel.font = UIFont.systemFont(ofSize: 70, weight: .bold)
titleLabel.textColor = UIColor.black
titleLabel.changeFont(ofText: "lc", with: UIFont.systemFont(ofSize: 60, weight: .light))
titleLabel.changeTextColor(ofText: "el", with: UIColor.blue)
titleLabel.changeTextColor(ofText: "co", with: UIColor.red)
titleLabel.changeTextColor(ofText: "m", with: UIColor.green)
_
Swift 4の代替:
let attrs = [NSAttributedStringKey.font : UIFont.boldSystemFont(ofSize: 14)]
let attributedString = NSMutableAttributedString(string: "BOLD TEXT", attributes:attrs)
let normalString = NSMutableAttributedString(string: "normal text")
attributedString.append(normalString)
myLabel.attributedText = attributedString
Swift 4.0。
import UIKit
extension UILabel {
/** Sets up the label with two different kinds of attributes in its attributed text.
* @params:
* - primaryString: the normal attributed string.
* - secondaryString: the bold or highlighted string.
*/
func setAttributedText(primaryString: String, textColor: UIColor, font: UIFont, secondaryString: String, secondaryTextColor: UIColor, secondaryFont: UIFont) {
let completeString = "\(primaryString) \(secondaryString)"
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.alignment = .center
let completeAttributedString = NSMutableAttributedString(
string: completeString, attributes: [
.font: font,
.foregroundColor: textColor,
.paragraphStyle: paragraphStyle
]
)
let secondStringAttribute: [NSAttributedStringKey: Any] = [
.font: secondaryFont,
.foregroundColor: secondaryTextColor,
.paragraphStyle: paragraphStyle
]
let range = (completeString as NSString).range(of: secondaryString)
completeAttributedString.addAttributes(secondStringAttribute, range: range)
self.attributedText = completeAttributedString
}
}
必要に応じて、Stringを直接実行できます。
extension String {
func withBoldText(text: String, font: UIFont? = nil) -> NSAttributedString {
let _font = font ?? UIFont.systemFont(ofSize: 14, weight: .regular)
let fullString = NSMutableAttributedString(string: self, attributes: [NSAttributedString.Key.font: _font])
let boldFontAttribute: [NSAttributedString.Key: Any] = [NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: _font.pointSize)]
let range = (self as NSString).range(of: text)
fullString.addAttributes(boldFontAttribute, range: range)
return fullString
}}
使用法:
label.attributeString = "my full string".withBoldText(text: "full")
Swift 4.0ソリューション
let font = UIFont.systemFont(ofSize: 14)
func boldSearchResult(searchString: String, resultString: String) -> NSMutableAttributedString {
let attributedString: NSMutableAttributedString = NSMutableAttributedString(string: resultString)
guard let regex = try? NSRegularExpression(pattern: searchString.lowercased(), options: []) else {
return attributedString
}
let range: NSRange = NSMakeRange(0, resultString.count)
regex.enumerateMatches(in: resultString.lowercased(), options: [], range: range) { (textCheckingResult, matchingFlags, stop) in
guard let subRange = textCheckingResult?.range else {
return
}
attributedString.addAttributes([NSAttributedString.Key.font : font], range: subRange)
}
return attributedString
}
拡張機能を好む人のために
Swift 5.
/// will set a regual and a bold text in the same label
public func setRegualAndBoldText(regualText: String,
boldiText: String) {
let attrs = [NSAttributedString.Key.font : UIFont.boldSystemFont(ofSize: font.pointSize)]
let regularString = NSMutableAttributedString(string: regualText)
let boldiString = NSMutableAttributedString(string: boldiText, attributes:attrs)
regularString.append(boldiString)
attributedText = regularString
}
そして使用:
label.setRegualAndBoldText(regualText: "height: ", boldiText: "1.65 :(")