Share Your Code

Text Wrapper Class

Posted by sunmils, Posted on December 22, 2011, Last updated October 14, 2012

GitHub URL: 
https://github.com/sunmils/corona_sdk_wrapper-class

There are two main usages of the module:

  1. You can wrap any text to a desired width, the height will be appointed automatically.
  2. You can wrap any text to a desired width and height, the font-size will be appointed automatically. This feature is very useful if you want a text shown in a spezific frame without knowing its lenth. If it is fetched from internet or entered by the user for example.
.

Adjustable Parameters:

  • text
  • width
  • height (for auto fontSize)
  • font
  • fontSize
  • lineSpace
  • alignment
  • fontColor
  • fontSizeMin
  • fontSizeMax
  • incrementSize
.

If you have some suggestions, I would be pleased to hear it. For preview or download please follow the github link.

.

Changelog

v1.1
1) Fixed errors with content scaling.
2) Added a new feature: you can now use \n for line break
3) In fact of the content-scaling error, alignment can not longer changed with the align function. Its now fix after initialization.

v1.2
1)fixed bugs related to the new linebreak feature, should work now without limitations.

v1.21
1) little corrections
2) added new Parameters for speed tweaking (see parameter list)

v1.22
1) added fontSizeMax parameter

v1.23
1) fixed error caused by changes on coronas content-scaling, where size parameters are now relative to the content size.
2) small corrections

v1.24
1) fixed error caused by missed linebreakes if the string is fetched from a file

.
.

If this module is useful for you, please klick the "like" button, so that other users can find it easier. Thanks!


Replies

jch_apple
User offline. Last seen 10 hours 13 min ago. Offline
Joined: 4 Apr 2010

Hi,

It doesn't work (at least on my computer !). I have downloaded from Github, unzipped and tested in simulator.

attempt to perform arithmetic on a string value....

Does anybody else made a test ?

sunmils
User offline. Last seen 5 days 13 hours ago. Offline
Joined: 18 Apr 2011

Hi,

I followed your steps with a new download, and everything worked fine. Could you please post the exact terminal output?

jch_apple
User offline. Last seen 10 hours 13 min ago. Offline
Joined: 4 Apr 2010

Sure

Copyright (C) 2009-2011 A n s c a , I n c .
Version: 2.0.0
Build: 2011.704
The file sandbox for this project is located at the following folder:
(/Users/jch/Library/Application Support/Corona Simulator/sunmils-corona_sdk_wrapper-class-02ed811-30264F6FCC7D60317DBCC2B84CC9C990)
Runtime error
?:0: attempt to perform arithmetic on a string value
stack traceback:
[C]: ?
?: in function 'newRetinaText'
...sunmils-corona_sdk_wrapper-class-02ed811/wrapper.lua:92: in function 'newParagraph'
...NA/sunmils-corona_sdk_wrapper-class-02ed811/main.lua:10: in main chunk
Runtime error: ?:0: attempt to perform arithmetic on a string value
stack traceback:
[C]: ?
?: in function 'newRetinaText'
...sunmils-corona_sdk_wrapper-class-02ed811/wrapper.lua:92: in function 'newParagraph'
...NA/sunmils-corona_sdk_wrapper-class-02ed811/main.lua:10: in main chunk

sunmils
User offline. Last seen 5 days 13 hours ago. Offline
Joined: 18 Apr 2011

there is a little error in the wrapper.lua in line 82. It should be:

1
local fontSize = params.fontSize or _H / 30     

furthermore you should take care if the selected font is installed on your system. Just comment line 14 in main.lua for standard-font.

hope that helps.

Github code is updated already. Just strange that it worked on my system.

jch_apple
User offline. Last seen 10 hours 13 min ago. Offline
Joined: 4 Apr 2010

I will test ASAP.

Some reasons that can explain things:

I'm still on iOS 4 (for company reasons I have too keep my iPhone 4 with iOS 4. We have iPhones 4S with iOS 5 I will also test)

I'm using Corona build 704

I'm using French iOS (frog enabled one :o))

jch_apple
User offline. Last seen 10 hours 13 min ago. Offline
Joined: 4 Apr 2010

Hi Sunmils,

I've made the change and it's working like a charm, thank you for sharing.

Have a nice Christmas

JC

sunmils
User offline. Last seen 5 days 13 hours ago. Offline
Joined: 18 Apr 2011

oh, I drived to France yesterday by mountainbike. I live next to the border in Germany :)

Glad to hear that it is working now.

A nice Christmas for you, too

Mike

jch_apple
User offline. Last seen 10 hours 13 min ago. Offline
Joined: 4 Apr 2010

Hi,

If you have some time to spend and work for outside companies maybe you can help me. I need something that would work like slideView but with pinch/zoom (something that would mimic the apple photo album behaviour).

May be this is not the place for such request in this case please tell me.

Rgds

JCH

sunmils
User offline. Last seen 5 days 13 hours ago. Offline
Joined: 18 Apr 2011

thanks, but unfortunately there is really less time. But do you know this already?

http://developer.anscamobile.com/content/pinch-zoom-gesture

Could be a start maybe.

In addition, possibility to send Personal-Messages in the Ansca-Forums would be very nice indeed.

ojnab
User offline. Last seen 1 week 2 days ago. Offline
Joined: 5 Jan 2011

Hey Mike. Thanks this wrapper is very usefull to me.
Saves me a lot of time!

ojnab
User offline. Last seen 1 week 2 days ago. Offline
Joined: 5 Jan 2011

Hi again. I have a small problem though...
If I try to wrap a long text without spaces like this for example:

text = "Corona'sframeworkdramaticallyincreaseproductivity.TaskslikeanimatingobjectsinOpenGL"

then the wrapper doesn't split it up into separate lines.
I tried to modify your code to force a line break when max width is reached but couldn't figure it out.

How would I do that? Thanks again!

sunmils
User offline. Last seen 5 days 13 hours ago. Offline
Joined: 18 Apr 2011

Hi,

thats correct. But this is already abserved on top of the wrapper.lua at "known issues" (Nr.2).

As you can see, the width of a word will only measured if there is a space or hyphen. In your case, you have to check the width afer every char.

So you simply need to avoid the if condition at line 105 by commend it. But keep in mind, that space characters will not generate a line-break in that case.

ojnab
User offline. Last seen 1 week 2 days ago. Offline
Joined: 5 Jan 2011

Sorry didn't see that Nr. 2
I need both kinds of line break...
I will let you know if I come up with some kind of solution.

larremp
User offline. Last seen 33 weeks 21 hours ago. Offline
Joined: 7 Jun 2011

Thanks for posting this, sunmils.

I am a newbie at Lua/Corona, so please be patient with my question. Can I use this with a multi-line text input by a user?

Do you also know of a method to input multi-line text using the native keyboard? Based on what I have read the native.newTextField() is limited to a single line. I might be wrong.

Any feedback is much appreciated. Thanks.

sunmils
User offline. Last seen 5 days 13 hours ago. Offline
Joined: 18 Apr 2011

Hi, and welcome to Corona :)

This class is only for text output. Technically its only a extension of the display.newRetinaText factory function.

It's a bit off topic, but here is a snippet for multiline-input I tested some time ago:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
local function textfeldHandler(event)
        
                
                
        if ("ended" == event.phase) or ("submitted" == event.phase) then
                -- wird bei "Abbruch" oder Return aufgerufen
            
                if ausgabe ~= nil then
                        ausgabe.isVisible = false
                end
                
                ausgabe = display.newText( textfeld.text, 30, 200, native.systemFont, 18 ) --nicht lokal, da sonst nicht löschbar!
                
--[[
                textfeld:removeSelf()
                textfeld = native.newTextBox( 10, 30, 180, tHeight, textfeldHandler )
                textfeld.font = native.newFont( native.systemFontBold, inputFontSize )
                textfeld.isEditable = true
--]]
                
        end
end
 
textfeld = native.newTextBox( 10, 30, 180, 100, textfeldHandler )
textfeld.font = native.newFont( native.systemFontBold, inputFontSize )
textfeld.isEditable = true

larremp
User offline. Last seen 33 weeks 21 hours ago. Offline
Joined: 7 Jun 2011

Thanks for your quick feedback, sunmils. I will try this later.

chris_raz
User offline. Last seen 1 day 21 hours ago. Offline
Joined: 11 May 2011

Hi,

Is there a way to remove the text from object?

for example. i want to have dynamic text, which will update, i want to be able to change the text and not just add to it. is it possible with this?

Thanks,
Chris.

sunmils
User offline. Last seen 5 days 13 hours ago. Offline
Joined: 18 Apr 2011

Hi Chris,

cause a new text must be wrapped anyway, you have to generate a new object for text changes.

Just changing the text will not work.

iTrain Dev
User offline. Last seen 1 year 35 weeks ago. Offline
Joined: 20 Jan 2011

Thanks, it is so very useful, and works with all the parameters you'd expect from a native multi line text object.

sunmils
User offline. Last seen 5 days 13 hours ago. Offline
Joined: 18 Apr 2011

Glad to here that it is helpful.

And don't forget to hit the like button if you like it ;)

Mike

iTrain Dev
User offline. Last seen 1 year 35 weeks ago. Offline
Joined: 20 Jan 2011

done!

I hadn't even noticed this button before ? What does it do? Does it give a better rating in the search result, or what is it ?

sunmils
User offline. Last seen 5 days 13 hours ago. Offline
Joined: 18 Apr 2011

exactly, and its good for my mood :)

Naomi
User offline. Last seen 2 days 8 hours ago. Offline
Joined: 6 Jun 2011

Wow, awesome wrapper. It worked like a charm with no hassle! Thank you so much for sharing, and yes, I liked it too!

Naomi

Naomi
User offline. Last seen 2 days 8 hours ago. Offline
Joined: 6 Jun 2011

Hey, @sunmils, while you are still in good mood, I'm wondering if you could add a line-break function to the wrapper. It would be so helpful. (I tried using \n within the text but it was ignored.)

Naomi

Naomi
User offline. Last seen 2 days 8 hours ago. Offline
Joined: 6 Jun 2011

Urrm, @sunmils, I just noticed that this class works fine on iPhone, but goes haywire on iPhone4 and iPad on simulator. (Same appears to be true with the device.) I'm using daily build 706.

Naomi

sunmils
User offline. Last seen 5 days 13 hours ago. Offline
Joined: 18 Apr 2011

Hi Naomi,

what exactly do you mean? I have no errors on this devices. Please post your code with a little error description.

thanks

iTrain Dev
User offline. Last seen 1 year 35 weeks ago. Offline
Joined: 20 Jan 2011

For my part, i'm using this class on an iPhone build installed on iPad 2, and it works as intended...Haven't tried an iPad specific or universal build though...

Naomi
User offline. Last seen 2 days 8 hours ago. Offline
Joined: 6 Jun 2011

@sunmils and @b00stup, thank you for getting back to me. Here's the code I use:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
local Wrapper = require("wrapper")
local screenW = display.contentWidth;
local screenH = display.contentHeight;
local myParagraph1 = Wrapper:newParagraph({
    text = "Here's my first paragraph.  Please check this out and let me know if it works.",
    width = 0.7 * screenW,
    font = fontName1,  -- this is a custom font I use
    fontSize = 20,
    lineSpace = 2,
    alignment  = "left"
})
myParagraph1:setReferencePoint(display.TopLeftReferencePoint)
myParagraph1.x = 0.2*screenW ;
myParagraph1.y = 100;
myParagraph1:setTextColor({255,255,255})
localGroup:insert(myParagraph1);
 
local myParagraph2 = Wrapper:newParagraph({
    text = "And here's my second paragraph.  Again, does this look good to you?",
    width = 0.7 * screenW,
    font = fontName1,  -- this is a custom font I use
    fontSize = 20,
    lineSpace = 2,
    alignment  = "left"
})
myParagraph2:setReferencePoint(display.TopLeftReferencePoint)
myParagraph2.x = myParagraph1.x;
myParagraph2.y = 0.5*screenH;
myParagraph2:setTextColor({255,255,255})
localGroup:insert(myParagraph2);

I use Director Class 1.4, and my config.lua is set for 320x480 with letterbox scaling. When I look at the text on Simulator, it looks perfectly fine on iPhone, but when I switch the View As from iPhone to iPhone4 / iPad, the paragraphs do not fit right. The spacing becomes way off, etc. I hope you can replicate the issue I'm seeing.

Naomi

ethanpil
User offline. Last seen 44 weeks 4 days ago. Offline
Joined: 18 Dec 2011

This code works for me but its excruciatingly slow. I am not doing anything crazy, with it, using the basic example code with the rect behind the text.

Does anyone else find it slow? Am I doing anything wrong?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
local _W = display.contentWidth
local _H = display.contentHeight
 
myParagraph = Wrapper:newParagraph({
        text = "Lorem ipsum sorem delet the quick brown fox jumps over the lazy dog.",
        width = display.contentWidth*.8,
        height = display.contentHeight*.4,                      -- fontSize will be calculated automatically if set 
        font = "helvetica",     -- make sure the selected font is installed on your system
        --fontSize = 14,
        --lineSpace = 5,
        alignment  = "center"
})
myParagraph:setReferencePoint(display.TopCenterReferencePoint)
myParagraph.x = _W/2
myParagraph.y = 50
myParagraph:setTextColor({0,0,0})
myParagraph.alpha=.65
 
rect = display.newRoundedRect(0,0,myParagraph.width+15, myParagraph.height+15, 15 )
rect:setReferencePoint(display.CenterReferencePoint)
rect.x = _W/2
rect.y = 50+myParagraph.height/2
rect:setFillColor(0,0,0)
rect.alpha=0.2
--rect:setStrokeColor(255,200)
--rect.strokeWidth = 1  
 
myParagraph:toFront()
rect:toFront()

sunmils
User offline. Last seen 5 days 13 hours ago. Offline
Joined: 18 Apr 2011

@Naomi

there was a little error with the content-scaling. If you detect the width of an scaled object, you receive the real pixels, not the relative to your content size. I fixed it already. Please download the newest code at github.

But there is still an error if you use content scaling with alignment set to "right" or "center". I tried to fix it, but it seems to be impossible. The behavior of the group is very very strange if scaled.

I will keep at it.

@ethan8
I have no problems with speed. Does your app need to much time to load, or what's the problem?

Naomi
User offline. Last seen 2 days 8 hours ago. Offline
Joined: 6 Jun 2011

@sunmils, thank you for looking into this. I'm glad to hear you've identified the issue I saw. From what you noted above, with the latest fix, I assume left alignment works perfectly fine with the content scaling.

Thanks again!
Naomi

sunmils
User offline. Last seen 5 days 13 hours ago. Offline
Joined: 18 Apr 2011

In fact of the content-scaling error, i revised the hole class to fix it correct. The text will now aligned bofore it will grouped. It should work now as expected in all situations.

You can also use \n for line-break now.

Download the new code from github. Detailed information can you find in the wrapper.lua file.

happy wrapping :)

Naomi
User offline. Last seen 2 days 8 hours ago. Offline
Joined: 6 Jun 2011

That is awesome, @sunmils! Thank you for taking the time to fix the content scaling issue and adding the line-break!! I can't wait to try it out.

Cheers!
Naomi

sunmils
User offline. Last seen 5 days 13 hours ago. Offline
Joined: 18 Apr 2011

Hey folks, again a new update to v1.2

It fixes some bugs with the new linebreak function. Should work now without limitations.

Please follow the github-link as before

ethanpil
User offline. Last seen 44 weeks 4 days ago. Offline
Joined: 18 Dec 2011

My code is still very slow. I have removed what I pasted above and my project is now 500% faster at least.

When I test on lower resolution devices it seems to be a bit better, but perhaps it has to do with my large font size? I cant see anything I am doing differently from the example.

Does anyone have any suggestion?

sunmils
User offline. Last seen 5 days 13 hours ago. Offline
Joined: 18 Apr 2011

@ ethanpil,

You are right, it depends on the fontsize. First of all, dont set up a hight will make it very much faster.

If you set up a height, the fontsize starts at 6 by default, and the text will so many times wrapped, until it fits your parameters. If your final fontsize is 29 as in your example IIRC, it went 23 times trough the hole prozess (+2 for detection and final wrapping). And thats very calculation intensive of course.

One solution is to change the start value of the fontsize to an higher one, if you can appraise the text length. (line 249).

Another possibility is to increase the amount of the fontsize raise to 2 instead 1 (line 264 and 267). That should approximately halve the time.

You can trace the time with that litte addidtion (real values on device only of course).

1
2
3
4
5
6
7
8
9
10
11
12
13
local t = system.getTimer()
 
myParagraph = Wrapper:newParagraph({
        text = "Lorem ipsum sorem delet the quick brown fox jumps over the lazy dog.",
        width = display.contentWidth*.8,
        --height = display.contentHeight*.4,                      -- fontSize will be calculated automatically if set 
        font = "helvetica",     -- make sure the selected font is installed on your system
        --fontSize = 14,
        --lineSpace = 5,
        alignment  = "center"
})
 
display.newText(tostring(system.getTimer() - t), 10, display.contentHeight - 22, nil, 20)

hope that helps

ethanpil
User offline. Last seen 44 weeks 4 days ago. Offline
Joined: 18 Dec 2011

@sunmils

Thanks for your help. I have submitted a modification via github pull request, based on your suggestion, which now allows me to start higher and increment as I need to (based on detected screen size, i can guess a number that is close enough..)

I use the code like this and now it works great! Thanks!!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
local _W = display.contentWidth
                local _H = display.contentHeight
 
                myParagraph = Wrapper:newParagraph({
                        text = "Lorem ipsum sorom delet blah...",
                        width = display.contentWidth*.8,
                        height = display.contentHeight*.4,                      -- fontSize will be calculated automatically if set 
                        font = "helvetica",     -- make sure the selected font is installed on your system
                        fontSizeMin     = 72,
                        incrementSize = 3,
                        --fontSize = 14,
                        --lineSpace = 5,
                        alignment  = "center"
                })
                myParagraph:setReferencePoint(display.TopCenterReferencePoint)
                myParagraph.x = _W/2
                myParagraph.y = 50
                myParagraph:setTextColor({0,0,0})
                myParagraph.alpha=.65

ethanpil
User offline. Last seen 44 weeks 4 days ago. Offline
Joined: 18 Dec 2011

Just one more comment, what is great now, depending on the device resolution I detect, I can make a guessed minimum fontsize, and everything will customize pretty well to the larger or smaller screen,and I can reduce the computation needed as well!

sunmils
User offline. Last seen 5 days 13 hours ago. Offline
Joined: 18 Apr 2011

@ethanpil

I thank you very much for the addition. I will integrate it soon. Only the firstloop flag makes no sense in my eyes. Breaking the firt loop means, that the initial font size is already to large. So it should be incremented anyway.

Mike

ethanpil
User offline. Last seen 44 weeks 4 days ago. Offline
Joined: 18 Dec 2011

@sunmils

Thanks for considering my suggestions. The reason I break the loop was because i was finding that it would reduce the size of the text anyway. However, in my mind I would expect the code to use the minimum size I set *despite* the fact that it is too big. Thats why its a hard minimum.

Without the break the code would actually return a box that had text smaller than my minimum size.

I was thinking of implementing an optional maximum size as well, which would break the loop even if there was extra room, for the same reason...

What do you think?

sunmils
User offline. Last seen 5 days 13 hours ago. Offline
Joined: 18 Apr 2011

@ethanpil

ok, i see.

I consider the fontSizeMax parameter as also useful. I added it even now ..

Maybe in the next days, I will drop the incrementSize parameter again, and let it calculate automatically, related to the textlength and given properties. That could improve the speed somewhat more.

photiscta
User offline. Last seen 1 week 5 days ago. Offline
Joined: 16 Feb 2011

Thank you sunmils, great class.

Seems to work fine for my project, in combination with director and scrollView.

Naomi
User offline. Last seen 2 days 8 hours ago. Offline
Joined: 6 Jun 2011

@sunmils, a quick note to let you know that the text wrapper class works as expected on iPad3 (retina). Thanks again for sharing this class!

Cheers,
Naomi

sunmils
User offline. Last seen 5 days 13 hours ago. Offline
Joined: 18 Apr 2011

ok, thanks for the feedback!

photiscta
User offline. Last seen 1 week 5 days ago. Offline
Joined: 16 Feb 2011

I have to display a long text with 1600 words (3 pages A4). I am also using scrollview.lua
The pages is being displayed with delay (up to 6 seconds!).
Has anyone a workaround?

Fotis

sunmils
User offline. Last seen 5 days 13 hours ago. Offline
Joined: 18 Apr 2011

Do you really need the special features of this class? These are the auto font-sizing if you set width and height, or if you set width and fontSize, the calculated height. Both needs time to calculate, first more, second less.

If you don't need this features (height is already known e.g.) its faster using the wrap function of coronas standard newText function.

For further questions please tell me your exact needs and maybe a code-sample.

photiscta
User offline. Last seen 1 week 5 days ago. Offline
Joined: 16 Feb 2011

Thank you sunmils for the reply!
I tried the the newText wrap feature, bu the proble is that it cannot has height greater to 2048.
So, I had to split the text and put one sentence (display.newText object) after the other.
The problem is that corona seems not to calculate correctly the coordinates, when you use scale in config. the spaces between the sentences are not the same for different devices with different size of display (screen).
What's your opinion?

sunmils
User offline. Last seen 5 days 13 hours ago. Offline
Joined: 18 Apr 2011

My first idea is, its maybe better if you use a textbox with scrolling, if it is possible in your context. You can hide the background, so it can look great in your App. I played a bit with the possibilities, and its really nice for displaying text (but there are still problems with editing). There was a blog entry concerning recently.

If you implicitly need several pages, you probably have to write your own wrapper with adapted positioning or you customize one of the shared.

neoroman
User offline. Last seen 3 weeks 5 days ago. Offline
Joined: 23 Jan 2012

Thank you for your efforts!

I red all the comments above.
Did anyone need to setText or text setter?
I think they should be in wrapper.lua.

sunmils
User offline. Last seen 5 days 13 hours ago. Offline
Joined: 18 Apr 2011

This topic is already mentioned in wrapper.lua under issues:

1
-- 3. In fact that a new text must be wrapped anyway, you have to generate a new object for text changes.

hope that helps,

Mike