Alphabet Scrollbar like iOS Contact List

Hello,

I’m trying to implement an alphabet type scroll bar for a contact list I have which is based on a ScrollRect. I want it to function like the iOS contact list:

http://cdn.iphonehacks.com/wp-content/uploads/2012/01/copic1.png

I’m able to render the alphabet on the scrollbar, but how do I get it to jump to the particular letter in the alphabet when a user taps that letter, while maintaining regular drag scrolling functionality?

Any help appreciated :slight_smile:

-Brett

That would be a very interesting control, will add a request to the UI Extensions project for it.

As for implementation, the scrollview does have a vertical scroll position value, the trouble is matching that to the local position of the control within it. So you would need to work out the vertical scroll position for each of the group letters and cache that somehow plus update it when a new contact is added.

I was able to get this working for my case. A couple of assumptions are made:

  1. You are using a vertical scrollbar (Bottom to Top)
  2. The scrollbar has all letters of the alphabet in it (even if some are not used):

  1. The ScrollView has an extra page of space on the end to allow for the last letters to get to the top:

Note that it only jumps to the letter on the initial press. Dragging is using default scrollbar behavior so it may not line up.

Here’s the code if anyone’s interested:

using UnityEngine;
using UnityEngine.UI;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.EventSystems;
public class AlphabetScrollbar : Scrollbar
{
    public float[] letterPercentages = new float[26];
    private bool initialized = false;
    public AlphabetScrollbar()
    {
        if (!initialized)
            Initialize();
    }
    private void Initialize()
    {
        for (int i = 0; i < 26; i++)
            letterPercentages[i] = (float)(26.0f - (float)i) / 26.0f;
        initialized = true;
    }
    public void SetLetterPercentages(ref List<string> names)
    {
        int[] letterCount = new int[26];
        for (int i=0; i<names.Count; i++)
        {
            char curletter = names[i][0];
            if (curletter >= 'A' && curletter <= 'Z')
                letterCount[curletter - 'A']++;
            else if (curletter >= 'a' && curletter <= 'z')
                letterCount[curletter - 'a']++;
        }
        float lastPercentage = 0.0f;
        for (int i=0; i<26; i++)
        {
            letterPercentages[i] = lastPercentage;
            lastPercentage = (float)((float)letterCount[i] / (float)names.Count) + letterPercentages[i];
        }
    }
    public override void OnPointerDown(PointerEventData eventData)
    {
        RectTransform barRect = (RectTransform)gameObject.transform;
        Vector3[] worldCorners = new Vector3[4];
        barRect.GetWorldCorners(worldCorners);
        float top = worldCorners[0].y;
        float bottom = worldCorners[1].y;
        float yHit = bottom - eventData.position.y;
        float scrollHeight = bottom - top;
        float percentage = yHit / scrollHeight;
        int index = (int)(percentage * 26.0f);
        value = 1.0f - letterPercentages[index];
    }
}

-Brett

Great stuff, will have to test that out.

You OK with this being added to the UI Extensions project @Rom ?

No problem Simon! And thank you for organizing the UI Extensions project, it’s a very useful archive.

1 Like

More than that, it includes an installable asset to easily deploy all the controls, plus editor scripts to use them as easily as the native UI controls. Someday I’ll get round to publishing it on the store for free as well.
Need to get all the community built controls in one easy to use place.