Thursday, August 19, 2010

Creating Multiple TextFields and Positioning Them Using Arrays and for Loops in Flash ActionScript 3.0

In this tutorial, we are going to learn how to create multiple text fields and how to position them in different locations using an array and a for loop in Flash using ActionScript 3.

Go ahead and create a new Flash ActionScript 3.0 document. Select frame 1, then go to the Actions Panel and we'll begin writing the code.

First, create an array in which we can store the TextFields. Then create a Number variable which will be equal to the number of TextFields that we'd like to create. Let's make 5 TextFields.
var aTextFields:Array = new Array();
var nTextFields:Number = 5;

Next, create the for loop. Make i equal to 0 and make the for loop run as long as i is less than nTextFields. After each iteration of the for loop, increment i by 1.
var aTextFields:Array = new Array();
var nTextFields:Number = 5;

for(var i:Number = 0; i < nTextFields; i++) {
// We'll create the TextFields in here
}

Inside the for loop, create new instances of the TextField class and put each instance in the array using array access notation.

Example:
aTextFields[0] = new TextField();
// This create a new instance of the TextField class and
// places it in the aTextFields array with an index of 0

But, again, this will be inside the for loop, so instead of using 0 or any other number, we'll replace it with i. So the for loop will now look like this:
for(var i:Number = 0; i < nTextFields; i++) {
aTextFields[i] = new TextField();
}

Each time the for loop iterates, it will create a new TextField and place it inside the aTextFields array. So when the for loop finishes, we will have 5 TextFields inside the aTextFields array. And each of those TextFields can be targeted using Array Access Notation. For example, if we'd like to set the border property of the TextFields to true, then we can type aTextFields[i].border = true; . So let's go back into the for loop and set some of the properties that we want our TextFields to have.
for(var i:Number = 0; i < nTextFields; i++) {
aTextFields[i] = new TextField();
aTextFields[i].width = 100;
aTextFields[i].height = 25;
aTextFields[i].border = true;
aTextFields[i].text = "This is TextField " + i;
}

If you test the movie now, you won't see the TextFields just yet. That's because we still need to add them to the display list. So let's make sure we do that.
for(var i:Number = 0; i < nTextFields; i++) {
aTextFields[i] = new TextField();
aTextFields[i].width = 100;
aTextFields[i].height = 25;
aTextFields[i].border = true;
aTextFields[i].text = "This is TextField " + i;
addChild(aTextFields[i]);
}

And then if you test the movie now, you'll see all the TextFields come out on the same spot. If we didn't put in the text inside the TextFields, then it will actually look like we only have 1 TextField. But we have 5. They're just all on the same spot and are just on top of each other. We could try randomizing their x and y properties so that they'll come out in different locations on the stage. We can use the random() method of the Math class for that. For example, we could type aTextFields[i].x = Math.random * 300; . That will create a number that can be anywhere between 0 or greater, but less than 300, which will then be assigned to the x property of the TextField. So let's go ahead and randomize the locations of our TextFields.
for(var i:Number = 0; i < nTextFields; i++) {
aTextFields[i] = new TextField();
aTextFields[i].width = 100;
aTextFields[i].height = 25;
aTextFields[i].border = true;
aTextFields[i].text = "This is TextField " + i;
aTextFields[i].x = Math.random() * 300;
aTextFields[i].y = Math.random() * 300;
addChild(aTextFields[i]);
}

So now, every time you test the movie, the TextFields will appear in different locations. But that's not actually what I'd like to do. Instead of having the TextFields appear at random positions, I'd like them all to be distributed evenly in one column. They'll all have the same x coordinate, but their y coordinate will each be adjusted so that they'll be displayed in a neat vertical fashion. I'll first change the x coordinate to 0 so that all the TextFields will be aligned to the left side of the stage.
for(var i:Number = 0; i < nTextFields; i++) {
aTextFields[i] = new TextField();
aTextFields[i].width = 100;
aTextFields[i].height = 25;
aTextFields[i].border = true;
aTextFields[i].text = "This is TextField " + i;
aTextFields[i].x = 0;
aTextFields[i].y = Math.random() * 300;
addChild(aTextFields[i]);
}

Now for the y coordinate of each TextField, I'd like the value to adjust accordingly. The 1st TextField (aTextFields[0]), should have a y coordinate of 0 so that it will appear at the topmost part of the stage. Then for the 2nd TextField (aTextFields[1]), I'd like for it to have a y coordinate that will put it right below the 1st TextField. Then the 3rd TextField should be below the second one, then the 4th TextField should be below the 3rd one, and so on...

So how do we make the y coordinate update within the for loop?
Well, one way of going about this would be to multiply i by the TextField's height. And then we assign the outcome of that to the y property of the TextField like so: aTextFields[i].y = i * aTextFields[i].height; . Each time the value of i increases, then the outcome of multiplying it by the TextField's height will increase as well (in Flash, the top most part of the stage is where y is equal to 0, and as we move down the stage, the value of y increases).

So our updated for loop will look like this:
for(var i:Number = 0; i < nTextFields; i++) {
aTextFields[i] = new TextField();
aTextFields[i].width = 100;
aTextFields[i].height = 25;
aTextFields[i].border = true;
aTextFields[i].text = "This is TextField " + i;
aTextFields[i].x = 0;
aTextFields[i].y = i * aTextFields[i].height;
addChild(aTextFields[i]);
}

So the 1st time the for loop runs, i will be equal to 0. And 0 multiplied by 25 (which is the TextField's height) will still be 0, so therefore, the y coordinate of the 1st TextField (aTextFields[0]) will be 0. The 2nd time the for loop runs, i will be equal to 1. And 1 multiplied by 25 is equal to 25. So the y coordinate of the 2nd TextField (aTextFields[1]) will be 25. And then the 3rd time the for loop runs, i will be equal to 2. And 2 multiplied by 25 is equal to 50. So the y coordinate of the 3rd TextField (aTextFields[2]) will be 50. And so on... So here, you'll see that after the 1st TextField, each succeeding TextField will appear right below the previous one.

NOTE: This works properly (meaning the TextFields are distributed evenly) because the TextFields all have the same height. If they didn't have the same height, the distribution will be uneven (some might overlap or others might have larger or smaller gaps between them).

Great! So now that we've been able to arrange our TextFields in one neat little column, let's just make a few more adjustments. I don't want the TextFields to be too close to the edge, so I'll just add a little offset (I'll make it 15 pixels). I'll change the x coordinate to 15, and then for the y coordinate, I'll add 15 pixels to i * aTextFields[i].height . This will put in 15 pixels worth of space from the left and top most edges of the stage.
for(var i:Number = 0; i < nTextFields; i++) {
aTextFields[i] = new TextField();
aTextFields[i].width = 100;
aTextFields[i].height = 25;
aTextFields[i].border = true;
aTextFields[i].text = "This is TextField " + i;
aTextFields[i].x = 15;
aTextFields[i].y = 15 + i * aTextFields[i].height;
addChild(aTextFields[i]);
}

So if you test the movie now, you should see that the TextFields aren't hugging the edges of the stage anymore.

And finally, one more adjustment. I think the TextFields are a little too close to each other and I would like to put vertical gaps in between them. I'll put in a gap of 5 pixels each. Now, I can't just add 5 pixels to the current y coordinate equation which is 15 + i * aTextFields[i].height . If I add 5, then it's just going to be added to the 15 pixels that we added for the initial offset. What we want is to create a 5 pixel gap in between the TextFields. So what we need to do instead is to add i * 5 to our current y coordinate equation so that it becomes 15 + i * aTextFields[i].height + i * 5 . This will give us the desired result.
for(var i:Number = 0; i < nTextFields; i++) {
aTextFields[i] = new TextField();
aTextFields[i].width = 100;
aTextFields[i].height = 25;
aTextFields[i].border = true;
aTextFields[i].text = "This is TextField " + i;
aTextFields[i].x = 15;
aTextFields[i].y = 15 + i * aTextFields[i].height + i * 5;
addChild(aTextFields[i]);
}

So if you test the movie now, you should now see some vertical space in between the TextFields.

Here's the code in full:
var aTextFields:Array = new Array();
var nTextFields:Number = 5;

for(var i:Number = 0; i < nTextFields; i++) {
aTextFields[i] = new TextField();
aTextFields[i].width = 100;
aTextFields[i].height = 25;
aTextFields[i].border = true;
aTextFields[i].text = "This is TextField " + i;
aTextFields[i].x = 15;
aTextFields[i].y = 15 + i * aTextFields[i].height + i * 5;
addChild(aTextFields[i]);
}

5 comments:

  1. at first I had an issue flash did want to work then for some reason it just worked thank you sir

    ReplyDelete
  2. me again thank you been looking for this answer for a weeks

    ReplyDelete
  3. great stuff! again!

    ReplyDelete