Ludicrous Software

‘Hacking’ Dynamic Text Fields inFlash Lite 1.1

Positioning content around dynamic text fields in Flash Lite 1.1 can be very difficult. While you can make the text field any size you want when you’re developing your content, there’s no way to directly increase the size of the text field via ActionScript. This can create a problem if you don’t know how much text will end up in the text field - if the field is too small, not all of the text will show up.

To get around this, you could simply make the text field really big, so that it is certain to contain all of the text that it might end up displaying. This would work, but it makes the placement of other assets on the stage difficult. So one of three things can occur:

There’s not enough room in the text field for the text. In this case, the content underneath the text field lines up nicely with the bottom of the text. But you can’t read all of the text because the text field is too small:

Dynamic text field too small

Or, the the text field is big enough, but now the text overlaps the other content:

Dynamic text field overlap

Or, there will be a large white space because there’s not enough text to fill the field. The text field is large enough to accomodate more text, and the main content has been moved down so that it won’t overlap any of the text. However, since the actual text in the text field is minimal, it creates wasted space between the text and the content:

Dynamic text field too large

(I added the dashed outlines so you could see how large I made the text fields in the IDE.)

I’m going to illustrate two fairly simple methods of using the maxscroll property of the text field to position other content. The Flash help docs define maxscroll as a read-only property that “indicates the line number of the first visible line of text in a scrollable text field when the last line in the field is also visible.”

Our first method will use ActionScript to position our other content based on the value of maxscroll. It’s a pretty simple set-up in Flash, with only three frames required:

dyntext5.png

The first layer is the standard actions layer. The second layer contains our text field, and the ‘bg’ layer contains the content we want to position. The text field layer is what makes the trick work. The first keyframe contains a text field that is one line high. The second keyframe has a much larger text field. We’ll see why in a second.

(You may have noticed that the two keyframes are spread across three frames. The first keyframe assigns a value to the variable displayed in the text field. However, the value of maxscroll isn’t available until the end of that frame. So the first time you can check the value of maxscroll is in the next frame of the clip. We therefore need this one frame ‘buffer’ to get the proper value for maxscroll. You can test this by tracing the value of txtToFit.maxscroll in the first and second frames. The thing to remember is that however you apply this method, you’ll need to have this buffer, or else these methods won’t work.)

On the stage, we have the one-line text field, and the other content. These are positioned at the same spot (the orange rectangle is the content to be positioned; the dashed line is the outline of the text field):

Dynamic text field method 1 set-up

Since the text field will not be moving, it should be placed wherever you want the text to be. Remember that we’ll be moving the other content after we determine maxscroll. The initial position is just our starting reference point.

To start with, we need to figure out the total number of lines. We do this using the one-line text field. If we get the value of maxscroll when the field is one line high, then maxscroll represents the total number of lines of text when all of the text is visible. So if maxscroll == 7, then there are seven lines of text. Remember that the text field at this point must be one line high; if it’s larger than that, you’ll get a different value for maxscroll and this method won’t work.

After assigning a value to the variable in the first frame, in the second frame can then use the value of maxscroll to calculate the new position for the other content. Here’s the code for that:

multiplier = 17; deltaY = txtToFit.maxscroll * multiplier; contentCurrentY = getProperty(“content_mc”, y); setProperty(“content_mc”, y, contentCurrentY + deltaY);

The first line simply calculates how far we need to move the content down the screen; the value is a multiple of maxscroll. By the way, the value for multiplier is no magic number; it was selected on the basis of trial and error to find out what value works best with the particular font being used in the text field. You’ll have to do some testing to determine what works best for your situation.

The second line gets the current position of the content movie clip, and the third line simply moves the content down the screen by adding deltaY to the current _y value of the content. We also increase the size of the text field so that it now shows all of the text. Since we can’t do that via ActionScript, we advance to the second keyframe, in which we have a larger text field. And that’s all there is to it. Here’s what you get:

Results of method 1 Results of method one - shot 2

This method is a little cleaner than the second method I’m about to show you. One downside to the first method is that it can be difficult to find a multiplier that works well with every possible value of maxscroll that you might have. The result can be less than pixel-perfect precision in the placement of your elements. The second method, while somewhat more involved than the first method, allows for that level of precision.

The second method is also quite simple: create a movieclip, and on successive frames make the dynamic text field large enough to fit an additional line of text. We start with the first frame, which again has a one-line text field. We check the value of maxscroll. If maxscroll == 1, then we can stop here because we know all the text is visible. If maxscroll is not 1, then we go to the next frame, with the slightly larger text field, and repeat the process. In each of these frames, the other content is repositioned to line up with the text field. You can repeat this over as many frames as you like.

The movieclip is set up like this:

Frame set-up of resizable dynamic text field

Notice that the ‘buffer’ frame is present again, so that we can get a proper value for maxscroll. If you wanted to place other content, you can create additional layers and position the elements as needed. Now let’s walk through the code. There’s not much too it!

In the first frame of the clip, we have:

_visible = false; txtToFit = “here is the test text”;

I’ve hidden the movie clip because otherwise you get a bit of an animation while the clip seeks out the frame to stop at. Once we’ve found that frame, we’ll display the clip again. I’ve set the value of the text field in this frame, but depending on how your app is set up, this may get done elsewhere. If you download the sample files, you can add more text to see how this works. The second, third, and fourth frames all contain the same single line of code:

call("checkfit");

Since Flash Lite 1.1 doesn’t support functions, we have to emulate functions through the use of call(). This executes the code of another frame within the frame containing the call() statement. This way, we only have to write the code once and can re-use it many times. In this case, we want to execute the code in the ‘checkfit’ frame. That code is what makes this whole thing work:

if (txtToFit.maxscroll == 1) { stop(); _visible = true; }

And that’s it! All we’re doing is checking to see if the value of maxscroll equals one; if it does, we know that all of the text fits inside the text field, so we can stop at this frame. We also set _visible to true so that we can see the movieclip containing our text field. I won’t include screenshots for this method since the shots for method one give you the idea of what’s happening.

You can download sample files to see how these work: Dynamic text sample files

Here are a few things to keep in mind:

This is meant for only relatively limited circumstances, where you don’t know for sure whether the content for a text field will stretch across, say, one to three lines (as in the example). For example, if you’re reading book or CD titles from a database, this would work nicely. If you don’t know how much text you’ll need to display, this may not be the best method for your needs.

Also, I’ve embedded the font used in the text field rather than using a device font. Since device fonts will vary across devices, embedding a font means I can figure how large to make the text fields for each keyframe, and that will work across devices. The method will work with device fonts, of course, but the variation in font size across devices can effect how consistently this will work.

Finally, a slightly quicker way of doing the second method would have been to read the value of maxscroll in the second frame, then jump to a subsequent frame based on that value.

Hope you find this helpful!