I have a goal to implement local search inside Core Data entities. Technical part of finding occurrences is pretty clear. But I'm not sure how to display it correctly. Case: we have string in our entity
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor
and user want to find entries with word adipiscing. We have UILabel with width i.e. 320dp and numberOfLines = 1. If we will display whole string without correct trimming it would be
Lorem ipsum dolor sit amet, consec...
which just useless for user. I want label to look like
...consectetur adipiscing elit, se...
So in other words I want search occurrence to be "focused" somewhere about middle of UILabel. How can I trim the string where occurrence has happened depending on label font and width?
It's not complete, but should bring you on track:
let wholeString = "This is a very long Hello world in a simple String"
let someSearch = wholeString.range(of: "Hello")!
// Make sure to call dropLast() twice to remove the space before 'Hello'
var stringBeforeSomeSearch = wholeString[wholeString.startIndex...someSearch.lowerBound].dropLast().dropLast()
// This is everything before the searched string
let prefixRange = stringBeforeSomeSearch.range(of: " ", options: .backwards)!.upperBound...someSearch.lowerBound
print(wholeString[prefixRange]) // prints "long H"
print(wholeString[prefixRange.lowerBound...someSearch.upperBound]) // prints "long Hello "
If you need more explanation, I'll be back later on.
Here's a solution that uses UITextView instead of UILabel, to achieve the desired search visualisation.
The concept is to use a UITextView with userInteraction and vertical scroll disabled and horizontal scroll enabled.
Use the textView method of scroll to range to show the desired word.
let textView = UITextView()
textView.isUserInteractionEnabled = false
textView.contentSize = CGSize(width: textWidth, height: textView.frame.size.width)
scrollTo(text: "swift")
func scrollTo(text: String) {
if let string = textView.text,
let range = string.localizedStandardRange(of: text) {
let viewRange = NSRange(range, in: string)
textView.scrollRangeToVisible(viewRange)
}
}
textWidth is the width of your total text. Follow this link for help.
Related
I am working with an UILabel that is constrained to a fixed width, and no more than a certain height (fixed to, say, half the screen size)
To allow our app to work across iOS devices, I set adjustsfontsizetofitwidth to be true on the UILabel. This leads to a resulting adjustment of the font size of the text if the screen size is small.
However, it appears that if the font is actually resized, the UILabel now has extra top and bottom padding to the text. This is marked as part of its intrinsic content size.
This extra vertical padding is problematic, because I have a button that needs to sit right below the baseline of the last line of text.
I need a method to now readjust my frame to tightly fit the newly adjusted text size.
I tried using sizeToFit() as well as invalidateIntrinsicContentSize in layoutSubviews() for my view class, but to no avail.
It seems similar to this and this, neither of which have answers that work for me.
class ProblemExample: UIViewController {
private let instructionsLabel: UILabel = {
let label = UILabel().disableAutoresizingMask()
label.numberOfLines = 0
label.text = "Lorem ipsum dolor sit amet, ut adhuc argumentum vix, vix eruditi appetere corrumpit in. Quod cibo mnesarchum ex sea. Ad qui case assum delicata, ei laudem prodesset democritum per, alia admodum efficiantur has id. Semper integre ei est, quo dolor causae definitionem ei. Malis impedit vim at, vero quas sit ea. Quaeque expetenda an est."
label.font = Theme.headingFont // BIG FONT
label.setLineSpacing(multiple: 1.15)
label.textColor = .black
label.lineBreakMode = .byTruncatingTail
label.adjustsFontSizeToFitWidth = true;
label.minimumScaleFactor = 0.5
return label
}()
override func viewDidLoad() {
super.viewDidLoad()
self.addSubview(instructionsLabel)
// Using https://github.com/roberthein/TinyConstraints for syntactical lightness
instructionsLabel.widthToSuperview(multiplier:0.5)
instructionsLabel.heightToSuperview(multiplier:0.5, relation:.equalOrLess)
instructionsLabel.centerYToSuperview()
button = UIButton()
self.addSubView()
button.bottom(to: instructionsLabel)
}
}
You can profit from the built-in behavior when you need either to fit text into the frame, or stretch frame according to the text size. It seems to me, you need both. Hence you have to do it yourself.
The approximate flow would be the following:
get the text that you are going to assign to the label
calculate the text's height knowing its width (see this)
if text height is more than max label height, set label to max height, otherwise set it to text height
assign text to label
Try by using following code, always add runtime rendering in viewDidLayoutSubViews or after viewDidLayoutSubViews
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewDidLayoutSubViews(){
super.viewDidLayoutSubViews()
self.addSubview(instructionsLabel)
// Using https://github.com/roberthein/TinyConstraints for syntactical lightness
instructionsLabel.widthToSuperview(multiplier:0.5)
instructionsLabel.heightToSuperview(multiplier:0.5, relation:.equalOrLess)
instructionsLabel.centerYToSuperview()
if button == nil {
button = UIButton()
self.addSubView()
button.bottom(to: instructionsLabel)
}
}
When i Add let say following text into my UILabel,
Lorem, Ipsum, is simply, dummy text of, the printing, and typesetting industry.
Now, let say my UILabel's width is limited but number of lines = 0(unlimited), then it will show the text like:
Lorem, Ipsum, is
simply, dummy text
of, the printing,
and typesetting
industry.
Here, you can see that line breaks are done at whitespaces, now i want them to update, and i want line breaks only when there is newline or comma(,) is there. So, How can i Implement that.
My Expected output is
Lorem, Ipsum,
is simply,
dummy text of,
the printing,
and typesetti
ng industry.
Tested solution
Create text and customText empty string
let text = "Lorem, Ipsum, is simply, dummy text of, the printing, and typesetting industry."
var customText = ""
Populate customText by substituting spaces with non-breakable spaces \u{00a0} if previous character is not ,
text.characters.enumerated().forEach { (idx, character) in
let prevChar = text[text.index(text.startIndex, offsetBy: max(0, idx-1))]
if character == " " && prevChar != "," {
customText.append("\u{00a0}")
}
else {
customText.append(character)
}
}
Create your label and assign customText to its text
let label = UILabel(frame: CGRect(x: 0, y: 0, width: 115, height: 5))
label.numberOfLines = 0
label.text = customText
label.sizeToFit()
NSString *string = #"Lorem, Ipsum,\n is simply,\n dummy text of,\n the printing,\n and typesett\ning industry.";
Now use this string
Maybe you should subclass the UILabel,CustomLabel.You should calculate the content and commas and add \n。
Swift 3.0
Simply add text like this. I have tested this and here you go with your expected output, but don't forget to set the label height according to this.
label33.text = "Lorem Ipsum,\nis simply,\ndummy text of,\nthe printing,\nand typesetti\nng industry."
I'm trying to align a UILabel inside a UICollectionViewCell like Whatsapp, Telegram, etc... Last line aligned to the left of the hour label, the others that ends on top of it.
I've tried adding at the end of the text some transparent characters and it worked until I tried some emojis; extra characters changed emoji code.
This is a sample of the code I'm using with TTTAttributedLabel for links detection.
let text = "Lorem ipsum dolor sit amet, enim apeirian his cu. Saperet interesset ex cum, ut per altera quodsi causae."
let endTransparentText = "aaaaa"
let showingText = text + endTransparentText
cell.lblMessage.setText(showingText) { (attributedString) -> NSMutableAttributedString? in
attributedString?.addAttribute(kCTForegroundColorAttributeName as String, value: UIColor.clear, range: NSMakeRange((showingText.characters.count-endTransparentText.characters.count), endTransparentText.characters.count))
return attributedString
}
Someone had to deal with this problem?
I am facing a strange problem with boundingRectWithSize and a multiline UILabel using the Swift language. I am currently working in a Xcode playground so I can see the result and updates of UI in real-time.
What I am trying to do is to calculate a given UILabel height dynamically based on it's content, I know this has been discusses over an over in other StackOverflow questions but this seems too strange to me.
The multi line label has this text in NSAttributedString form. Text is a simple Lorem ipsum placeholder:
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Donec et mollis dolor.
Here's the code for the UILabel:
let valueString = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Donec et mollis dolor."
var dataValue = UILabel()
dataValue.numberOfLines = 0
dataValue.lineBreakMode = .ByWordWrapping
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.alignment = .Justified
paragraphStyle.lineBreakMode = .ByWordWrapping
paragraphStyle.firstLineHeadIndent = 0.1
let attributedText = NSAttributedString.init(
string:valueString,
attributes:[NSParagraphStyleAttributeName:paragraphStyle, NSFontAttributeName:dataValue.font])
let textString = dataValue.text! as NSString
dataValue.attributedText = attributedText
dataValue.frame = CGRect(
x:CGFloat(kMargin),
y:dataType.frame.origin.y + CGFloat(kLabelHeight),
width:CGFloat((maxLabelWidth) - kMargin * 2),
height:textString.boundingRectWithSize(
CGSizeMake(CGFloat(kMaxWidth), CGFloat.max),
options:[.UsesLineFragmentOrigin, .UsesFontLeading],
attributes:[NSParagraphStyleAttributeName:paragraphStyle, NSFontAttributeName:dataValue.font],
context:nil).size.height)
The problem is that the UILabel only shows 3 lines of text, stopping at the mauris word of the text and truncating the last ones as you can see from the Playground preview feature:
One obvious problem is that valueString and textString are two different strings. So there is no reason to believe that string you're putting into the label is the same as the string you're measuring.
You use valueString here:
let attributedText = NSAttributedString.init(
string:valueString, // ...
But you use dataString here:
height:textString.boundingRectWithSize(
Also, do not try to combine label attributes with attributed text. This can cause all kinds of problems. The dataValue label should have no font. You should not be fetching this font value. Do everything using the attributed string. You should not be constructing two different style dictionaries; you should be assigning and measuring the exact same attributed string.
To put it another way, do not measure valueString or textString at all, with or without attributes. Measure attributedString.
Finally, make sure that the label has the same width as you are using during measurement. You are saying
CGSizeMake(CGFloat(kMaxWidth) // ...
but there is no evidence that the label itself is going to have this width.
I would like to make lowercase every first string of a sentence, that user writes into a UITextView.
Example
lorem ipsum dolor sit amet. consectetur adipiscing elit. phasellus et
tincidunt eros at faucibus orci.
There are a lot of related question for UITextfield, but I couldn't find any useful answers that deals with UITextview. Is it possible with a UITextView property or I need to check every string and make them lowercase? I've tried to set the keyboard in Interface Builder without any success.
Check this
textField.autocapitalizationType = UITextAutocapitalizationTypeNone;
there are following you can use -
typedef enum : NSInteger {
UITextAutocapitalizationTypeNone ,
UITextAutocapitalizationTypeWords ,
UITextAutocapitalizationTypeSentences ,
UITextAutocapitalizationTypeAllCharacters ,
} UITextAutocapitalizationType;
Default is The default value for this property is UITextAutocapitalizationTypeSentences.