Fork us on GitHub

Alphabet Scroll

An easy way to implement the UI pattern from iOS
Post Image

Alphabet Scroll

We got a lot of requests from developers over the years to do an iOS style alphabet side scroll. Some developers implements such scrolling but no one made it generic or contributed it back. So a recent stack overflow question got me thinking about how easy it would be to actually implement something like that and I decided to try…​

I ended up building this in 10 minutes and the concept is remarkably simple. I have two containers, one contains the list of the people and the other one contains the letters used for these people. Notice that I chose to only use letters that used in the names, I could have just hardcoded the English alphabet but chose to avoid that as this would break for internationalization and include letters that might not be common in such cases such as 'Z'.

Thanks to the usage of layered layout the containers just appear on top of one another, notice that in the sample code below I had to cancel the default scrollability of the form to allow the two containers to have their own scrollability. The scrolling isn’t nested in this case since these are two separate containers that just happen to be one on top of the other.

We scroll to the selected component by finding it as we loop over the components in the actual container and using scrollComponentToVisible which is pretty convenient for this case.

Check out the live demo on the right side thanks to the JavaScript port

You can also check out the full project on github here and see the relevant code below:

String[] characters = { "Tyrion Lannister", "Jaime Lannister", "Cersei Lannister", "Daenerys Targaryen",
    "Jon Snow", "Petyr Baelish", "Jorah Mormont", "Sansa Stark", "Arya Stark", "Theon Greyjoy",
    "Bran Stark", "Sandor Clegane", "Joffrey Baratheon", "Catelyn Stark", "Robb Stark", "Ned Stark",
    "Robert Baratheon", "Viserys Targaryen", "Varys", "Samwell Tarly", "Bronn","Tywin Lannister",
    "Shae", "Jeor Mormont","Gendry","Tommen Baratheon","Jaqen H'ghar","Khal Drogo","Davos Seaworth",
    "Melisandre","Margaery Tyrell","Stannis Baratheon","Ygritte","Talisa Stark","Brienne of Tarth","Gilly",
    "Roose Bolton","Tormund Giantsbane","Ramsay Bolton","Daario Naharis","Missandei","Ellaria Sand",
    "The High Sparrow","Grand Maester Pycelle","Loras Tyrell","Hodor","Gregor Clegane","Meryn Trant",
    "Alliser Thorne","Othell Yarwyck","Kevan Lannister","Lancel Lannister","Myrcella Baratheon",
    "Rickon Stark","Osha","Janos Slynt","Barristan Selmy","Maester Aemon","Grenn","Hot Pie",
    "Pypar","Rast","Ros","Rodrik Cassel","Maester Luwin","Irri","Doreah","Eddison Tollett","Podrick Payne",
    "Yara Greyjoy","Selyse Baratheon","Olenna Tyrell","Qyburn","Grey Worm","Meera Reed","Shireen Baratheon",
    "Jojen Reed","Mace Tyrell","Olly","The Waif","Bowen Marsh"
};

Toolbar.setGlobalToolbar(true);

Form f = new Form("Letter Scroll", new LayeredLayout());

f.setScrollable(false);
Container characterContainer = new Container(BoxLayout.y());
Container lettersContainer = new Container(BoxLayout.y());
characterContainer.setScrollableY(true);
lettersContainer.setScrollableY(true);

char lastLetter = 0;
Arrays.sort(characters, new CaseInsensitiveOrder());
for(String character : characters) {
    MultiButton mb = new MultiButton(character);
    characterContainer.add(mb);
    char c = Character.toUpperCase(character.charAt(0));
    if(c != lastLetter) {
        lastLetter = c;
        Button btn = new Button("" + lastLetter);
        lettersContainer.add(btn);
        btn.getAllStyles().setPadding(0, 0, 0, 0);
        btn.getAllStyles().setMargin(0, 0, 0, 0);
        btn.addActionListener(e -> {
            for(Component cmp : characterContainer) {
                MultiButton m = (MultiButton)cmp;
                if(Character.toUpperCase(m.getTextLine1().charAt(0)) == c) {
                    characterContainer.scrollComponentToVisible(m);
                    return;
                }
            }
        });
    }
}

f.add(characterContainer).
        add(BorderLayout.east(lettersContainer));

f.show();
Share this Post:

Posted by Shai Almog

Shai is the co-founder of Codename One. He's been a professional programmer for over 25 years. During that time he has worked with dozens of companies including Sun Microsystems.
For more follow Shai on Twitter & github.