Displaying line of text within predefined width

I would like to display text within predefined area and to trim remaining part of it. 

For example, I have 200px wide area to display text which is much, much wider.

It will be nice to have portion of that text displayed (as much as it is possible within 200px) and to add “…” at the end).

So, the following string: “Lorem ipsum whatever whatever” should look something like: “Lorem ipsum whate…”

It is quite easy to make something like this if I use fixed width font, but I am having problem with normal font…

Is there library or some tip how to achieve that kind of text display?

Thanks

I have the same idea and need. No library function that I know of which will give us what we need. I ended up working something out that works but is not ideal. You can see my code below.

The only way I could find out how long a string would appear on screen was through a call to textObj.width but you can get this only after you call the display.newRetinaText().

So in a nutshell you use display.newRetinaText and put the text up and then see if its >= than the width you don’t want to exceed. If its too long then you use string.sub to keep shortening it in a while loop until its short enough. Downside of this approach is that you need to keep updating textObj.text which in return updates the display.newRetinaText in each iteration to get the new width. This must be CPU intensive. I shorten the text by 2 chars each time to make it go down faster with less impact. Seems to work ok on the simulator. Will try next on the devices to see if the performance is acceptable.

Anyways, here goes. If you improve on it please post here so I and others can benefit too. I also appreciate any other input from anyone who might have a better way to go about this. Thanks much! 

local screenWidth = display.contentWidth local textObj = display.newRetinaText( myOriginalText, 0, 0, "Helvetica", 14 ) local shortenedText = myOriginalText if ( textObj.width \>= (screenWidth - 20) ) then while ( textObj.width \>= (screenWidth - 20) ) do print(textObj.width) print(shortenedText) shortenedText = string.sub(shortenedText, 1, (string.len(shortenedText) - 2)) textObj.text = shortenedText end shortenedText = shortenedText .. "..." textObj.text = shortenedText end 

Edit - some improvements to the code. Realized I don’t need to keep calling display.newRetinaText() over and over. I can simply update the textObj.text and get the new width with textObj.width. Seems to work faster and cleaner.

Yes, I think that your code can be the solution.

Because I have a lot of text I’ll see the how expensive it will be. If there is a problem and I find the solution - I’ll post it here.
Thank you again.

PS. Is display.newRetinaText still necessary for text display on hires devices?

I am using this text in a tableView widget where I load about 200 to 300 records max and lets say 10 to 20 % of the records need to be shortened in this manner. Even on older & slower devices the performance seems to be ok. I think tableView uses lazyload so you’re not waiting there to have all records get manipulated. When you are scrolling down, more rows are populated and if you put this routine into your onRowRender() function then you do what you need to do when you need to do it. It spreads the expense. 

Good catch on display.newRetinaText. I still use it in a mixed manner with display.newText. Should run a search replace one of these days… It is not necessary anymore as display.newText handles high res as well I think. 

Good luck with your trials. Look forward to hearing how it works out for you.

You can roughly guess that a given character will use roughly it’s height in pixels in width if you include the spacing between the letters (perhaps a touch thinner).  Now if you have a string with lots of M’s or W’s it’s going to be pretty long but a string of i’s and l’s will be short, but on average… 

So if you have a 200px length box and you’re using a 20 point font then you’re going to on average fit 10 characters in that space.  You can play around and figure out based on the font face, to tweak it up or down, but it’s a starting point.  Then you can use string.sub(text,1,numChars) … “…”

I have the same idea and need. No library function that I know of which will give us what we need. I ended up working something out that works but is not ideal. You can see my code below.

The only way I could find out how long a string would appear on screen was through a call to textObj.width but you can get this only after you call the display.newRetinaText().

So in a nutshell you use display.newRetinaText and put the text up and then see if its >= than the width you don’t want to exceed. If its too long then you use string.sub to keep shortening it in a while loop until its short enough. Downside of this approach is that you need to keep updating textObj.text which in return updates the display.newRetinaText in each iteration to get the new width. This must be CPU intensive. I shorten the text by 2 chars each time to make it go down faster with less impact. Seems to work ok on the simulator. Will try next on the devices to see if the performance is acceptable.

Anyways, here goes. If you improve on it please post here so I and others can benefit too. I also appreciate any other input from anyone who might have a better way to go about this. Thanks much! 

local screenWidth = display.contentWidth local textObj = display.newRetinaText( myOriginalText, 0, 0, "Helvetica", 14 ) local shortenedText = myOriginalText if ( textObj.width \>= (screenWidth - 20) ) then while ( textObj.width \>= (screenWidth - 20) ) do print(textObj.width) print(shortenedText) shortenedText = string.sub(shortenedText, 1, (string.len(shortenedText) - 2)) textObj.text = shortenedText end shortenedText = shortenedText .. "..." textObj.text = shortenedText end 

Edit - some improvements to the code. Realized I don’t need to keep calling display.newRetinaText() over and over. I can simply update the textObj.text and get the new width with textObj.width. Seems to work faster and cleaner.

Yes, I think that your code can be the solution.

Because I have a lot of text I’ll see the how expensive it will be. If there is a problem and I find the solution - I’ll post it here.
Thank you again.

PS. Is display.newRetinaText still necessary for text display on hires devices?

I am using this text in a tableView widget where I load about 200 to 300 records max and lets say 10 to 20 % of the records need to be shortened in this manner. Even on older & slower devices the performance seems to be ok. I think tableView uses lazyload so you’re not waiting there to have all records get manipulated. When you are scrolling down, more rows are populated and if you put this routine into your onRowRender() function then you do what you need to do when you need to do it. It spreads the expense. 

Good catch on display.newRetinaText. I still use it in a mixed manner with display.newText. Should run a search replace one of these days… It is not necessary anymore as display.newText handles high res as well I think. 

Good luck with your trials. Look forward to hearing how it works out for you.

You can roughly guess that a given character will use roughly it’s height in pixels in width if you include the spacing between the letters (perhaps a touch thinner).  Now if you have a string with lots of M’s or W’s it’s going to be pretty long but a string of i’s and l’s will be short, but on average… 

So if you have a 200px length box and you’re using a 20 point font then you’re going to on average fit 10 characters in that space.  You can play around and figure out based on the font face, to tweak it up or down, but it’s a starting point.  Then you can use string.sub(text,1,numChars) … “…”