I have a UITextView that has a maximum number of lines 3 :
textView.textContainer.maximumNumberOfLines = 3
The text is longer than 3 lines, and I would like that the last word visible would be more.
E.g :
For the string :
This string is pretty long and we would like to be able to identify the last word visible so we can display "more" instead of the word found.
For 3 lines, the text displayed is :
This string is pretty long and we would like to be able to identify
The result that I'm looking for :
This string is pretty long and we would like to be able to more
Is there any API in UITextView, or in the text container that would allow me to get that last word displayed?
I would suggest you the ilyapuchka ReadMoreTextView library which is on this link. It is the easiest way to achieve this and it is pretty lightweight.
You can install it with CocoaPods, just implement pod 'ReadMoreTextView' into the podfile and you can use it like this:
let textView = ReadMoreTextView()
textView.text = "Lorem ipsum dolor ..."
textView.shouldTrim = true
textView.maximumNumberOfLines = 3
textView.trimText = "Read more"
Related
I'm trying to create an expandable label that looks like the one in the picture:
I have two problems:
How do I make the label truncate the tail such that it leaves enough place for the More button/clickable text?
How do I place the More text?
Maybe, I am going about it the wrong way? Instead of playing with the number of lines, should I maybe try to calculate how much text goes into one and a half line and present it only, and then when clicking More I present the whole text?
Would appreciate any advice, thanks!
You can use this library to achieve your expected output.
https://github.com/apploft/ExpandableLabel
Specify the number of lines you want to display default.
expandableLabel.numberOfLines = 2
Set true if the label should be collapsed or false for expanded.
expandableLabel.collapsed = true
collapsedAttributedLink
Set the link name that is shown when collapsed.
expandableLabel.collapsedAttributedLink = NSAttributedString(string: "More")
expandedAttributedLink
Set the link name that is shown when expanded. It is optional and can be nil.
expandableLabel.expandedAttributedLink = NSAttributedString(string: "Less")
I've got a UIButton, it's a simple segue to another page.
I've set Title to attributed and then selected word wrap. This works fine, the second word wraps down to the next line.
However, it is all left justified. When I select "Align Centre" (using the buttons just under the "Title", the word wrap no longer works and simply runs .... so you can't see it all. (e.g. "next pa" instead of "next page")
Am I missing something here? It seems like such a trivial thing to do! There's an old answer here can't get word wrap to work on UIButton but it's both old and uses code - surely you don't need code to centre the button text if you want to word wrap it to 2 lines!?
I've set Title to attributed and then selected word wrap. This works fine, the second word wraps down to the next line. However, it is all left justified.
Once you've decided to use an attributed string, you must do everything with the attributed string. So give your attributed string a paragraph style that centers the text.
let para = NSMutableParagraphStyle()
para.alignment = .center
para.lineBreakMode = .byWordWrapping
let s = NSAttributedString(
string: "Hello World", attributes: [.paragraphStyle : para])
self.button.setAttributedTitle(s, for: .normal)
You will also need to set the button's title label to allow multiple lines.
self.button.titleLabel?.numberOfLines = 0
Result:
surely you don't need code to centre the button text if you want to word wrap it to 2 lines!?
Not to center it, no; you can set the centering in the storyboard. So you could eliminate the first batch of code and configure it in the storyboard. But you must use code to turn the title label into a multiline label:
self.button.titleLabel?.numberOfLines = 0
There is no way to do that in the storyboard, because you have no access to the title label there.
I've just been playing round with this and I've found it works if you set it to 'character wrap' rather than 'word wrap' once you've selected centre alignment.
If anyone has a better solution please add it, as I guess this might have issues if you slightly change the width etc when using auto layout for different screen sizes etc if you want it to adapt its width so this might not be the best solution but it does work
I am currently writing my first app on ios using swift 3. I have a plist that has a list of different pieces of information and each is a long paragraph with sections throughout it. for each section, I want to bold the text for the title or at least have the option to format it a certain way rather than just display all the text. I currently have a simple table view that displays text in a text view once tapped. I cannot figure out how to read the paragraph into a string, and compare parts of the string and bold that specific text.
For example, If I had a string that was read from the plist and said:
"My name is #Bob and I like to #dance."
How could I change "#Bob" to "Bob" and "#dance" to "dance" without hard coding it?
#IBOutlet var paragraphTextView: UITextView!
.
.
.
if let text = paragraph["Text"] {
paragraphTextView.text = text
}
The simplest solution is to use some HTML markup in the text in your plist file.
Instead of the plain text:
My name is #Bob and I like to #dance.
Use:
My name is <b>Bob</b> and I like to <b>dance</b>.
This gives you far more flexibility. You can add bold, underline, and italic simply by using the appropriate <b></b>, <u></u>, and <i></i> tags as needed. It also allows you to markup more general ranges than single words.
Once the text has the proper markup, you create an NSAttributedString from the marked up string and then set that to the text viewsattributedTextproperty instead of using thetext` property.
For a good example of how to create an NSAttributedString from HTML text, see HTML Format in UITextView
I am trying to display an article in a ViewController.
The output that I receive from the API divides the article into paragraphs, and each paragraph is a node in the JSON. For example,
{
"para" : 1,
"content" : "some long paragraph"
},
{
"para" : 1,
"content" : "some long paragraph"
}
I want to display this content as one long article, but I want to let each paragraph to be viewed in one textView instead of combining all the paragraphs and view in one textView.
I am on Xcode 8, Swift 3. I use Cocoapods, so libraries are welcome.
If you want to use Text view , then you don't need to create multiple textview. Just use a single textview.
Use a for loop on your response object and append all the paragraph's content in a single string using /n after each paragraph. And then simply set that string value into textview. That's it. I hope it will work for you better..
I have been struggling with this. User needs to enter text and/or emoticons in a TextView. I got an emoticon keyboard with my own images to enter emoticons. Problem is I need to keep a symbol (e.g. "(smile)" for the emoticon within the text while AT THE SAME TIME showing the emoticon picture on top of the symbol.
So user would see "Hello [the picture]" while the TextView.text property would return "Hello (smile)".
On Android you can use Spanned strings which allow you to cover part of your text with an image. Thus on Android I managed to achieve my objective without problem.
On iOS, I thought Attributed Strings were a similar concept to Spanned but so far all I have been able to do is entirely replace the emoticon's code with the picture (using NSTextAttachment). Is there a way to achieve my objective without having to maintain one attributed string containing pictures and one separate string containing codes?
You can use this method, Hope it will work for you.
- (NSAttributedString*) parseEmoticons:(NSAttributedString*)text {
text = [text stringByReplacingOccurrencesOfString:#":-)" withString:#"😄"];
text = [text stringByReplacingOccurrencesOfString:#";P" withString:#"😜"];
text = [text stringByReplacingOccurrencesOfString:#"B-)" withString:#"😎"];
text = [text stringByReplacingOccurrencesOfString:#";-P" withString:#"😜"];
return text;
}
Having failed to find a more elegant solution, I resorted to maintaining one attributedstring containing the emoticon picture, and one regular string to hold the emoticon codes. So my attString is for instance "Hello [Smiling picture]" while my string is "Hello %101%". If you are interested in building a chatting app as I am, here is the pseudo code:
In emoticon keyboard:
{
Insert picture into attributed string at location loc;
Call textView shouldChangeTextInRange:(loc,0) replacementText:"%101";
}
In the view controller at shouldChangeTextInRange:(loc,length) replacementText:text:
{
Parse regular string to jump over emoticon codes already there to find the location matching loc;
Replace text (for instance %101%) in regular string} at the identified location.
}
Note: shouldChangeTextInRange is also called for regular keyboard entries including delete.