The best example I can think of is the "Peggy," A Light Emitting Pegboard Display. It is a 25x25 LED matrix display driven by an ATmega168 (which is pin compatible with the ATmega328)
The wiki page has a lot of good information. Including a detailed schematic.
There are few things to notice in their layout.
For one, they use a row common anode setup. That is the current source is on the row, and sink on the column. You have yours in row common cathode. There is nothing inherently right or wrong with either layout. Just something to keep in mind when designing your circuit. If using discrete leds, it just means flipping the led connections. If using a prebuilt LED matrix, it is something important to know. (I'll assume you can easily swap the order to match the peggy schematic. If not, just swap column for row in your head)
They use 74HC154 4-16 decoder/demux chips for row select. Since you only need 10 rows (or cols) you can get away with just one. Of course, there is the issue of current. In your case, at 10 x 30mA = 300mA minimum. To solve that problem they used 2STX2220 PNP transistors which will be able to source up to 1.5A per row. A bit over kill in your case. Since you will just use these as row select switches, just about any other pnp transistor that can source your max current should work just as well. Take a look at Transistor Circuits to figure out what resistor values you'll need for full on/off operations.
On the Peggy board, for the column sink driver they use an STP16DP05. But I have found these difficult to find and expensive. There are many other alternatives like the TLC5916 These use a serial input, and can be easily cascaded. If not, a digikey of mouser search for led sink driver will yield many results.
Alternatively, since you already have ULN2803 arrays, you could use two of these with a single current limit resistor per column. That's a lot of pins, so you'll have to get creative, but it could work for the column sink as well.
Avago published a nice application note titled "Introduction to Driving LED Matrices". It covers this and a few other things.
This is running on the assumption that you are using a supply of 5v.
For the resistor calculations you want to use Ohms law V = IR, where I is the current you want to flow through the LED and V is the voltage difference between what you are supplying and what the LED is specified for. The voltage you want to use is the typical voltage listed on the datasheet, so for the case of red you have (5v - 2.1v) = 20mA * R -> R = 2.9v/20mA = 145 Ohm. The green and blue channels are calculated similarly using a voltage of 3.8v and 2.7v respectively.
Best Answer
A good way to think about an LED is as a variable resistance (or impedances, more commonly). At very low voltages, it has very high impedance, so not a lot of current will flow through the device. If you have a current source, as davr suggests, the current flowing through the LED times the impedance will create a voltage (Ohm's law). If you force enough current, the voltage will quickly rise and the impedance will drop. The point where current seems to flow easily is past the "turn-on" voltage you speak of. Past this point the impedance of the device is very low and large changes in current will create small changes in voltage.
I know this can still be confusing, but I would suggest staring at an I-V curve for a while (current plotted versus voltage). This is a simple looking chart but is in fact quite complex. The thing that I did not grasp until much further into my career is that the instantaneous slope of the line is actually the impedance. Once you grasp that concept, what I said earlier may become clearer.
(source: utc.edu)