Skip to content Skip to sidebar Skip to footer

Recyclerview With Alphabet Index

I am attempting to build a RecyclerView list, with an alphabetical indexer down the right hand side. I have the list displaying perfectly and am able to scroll. I am wondering if s

Solution 1:

I believe this is the information you have been looking for as I have

You can check these libraries here:

danoz73/RecyclerViewFastScroller

enter image description here

as far as I remember he is the one who actually made the first alphabet indexer in recyclerview. I never made it work in my app because there was lots of problem customizing it.

AndroidDeveloperLB/LollipopContactsRecyclerViewFastScroller

enter image description here

the readme said hes got lots of optimizations made, So i think this is the best one i could use, but i havent made it work in my app for now.

code-computerlove/FastScrollRecyclerView

enter image description here

I think this is the design you want right? So either of these libs you used it should suffice your needs.

hope it helps

Solution 2:

If anyone would like to use the FastScrollRecyclerView mentioned above in Xamarin, I just ported the main classes (you'll still need to create the xml resource and prep your index etc etc - see the original repo for a guide, it's pretty simple).

I included the tweaks suggested in the issues page to improve the ScrollToPosition and index height (which also makes it work in landscape) and also switched out the Java Handler class for an async Task.Delay. It may still have issues, it's a straight port otherwise. Seems to be ok though. Hopefully I have saved someone some time :)

publicinterfaceIFastScrollRecyclerViewAdapter
{
    Dictionary<string, int> GetMapIndex();
}

//

publicclassFastScrollRecyclerView : RecyclerView
{
    publicconstint INDWIDTH = 25;
    publicconstint INDHEIGHT = 18;
    publicfloat ScaledWidth { get; set; }
    publicfloat ScaledHeight { get; set; }
    publicstring[] Sections { get; set; }
    publicfloat Sx { get; set; }
    publicfloat Sy { get; set; }
    publicstring Section { get; set; }
    publicbool ShowLetter { get; set; }

    private ListHandler _listHandler;
    privatebool _setupThings = false;
    private Context _context;

    publicFastScrollRecyclerView(Context context) : base(context)
    {
        _context = context;
    }

    publicFastScrollRecyclerView(Context context, IAttributeSet attrs) : base(context, attrs)
    {
        _context = context;
    }

    publicFastScrollRecyclerView(Context context, IAttributeSet attrs, int defStyle) : base(context, attrs, defStyle)
    {
        _context = context;
    }

    publicoverridevoidOnDraw(Canvas c)
    {
        if (!_setupThings && GetAdapter() != null)
            SetupThings();
        base.OnDraw(c);
    }

    privatevoidSetupThings()
    {
        //create az text datavar sectionSet = ((IFastScrollRecyclerViewAdapter)GetAdapter()).GetMapIndex().Keys;
        var listSection = new List<string>(sectionSet);
        listSection.Sort();
        Sections = newstring[listSection.Count];
        int i = 0;
        foreach (var s in listSection)
        {
            Sections[i++] = s;
        }

        ScaledWidth = INDWIDTH * _context.Resources.DisplayMetrics.Density;
        var divisor = sectionSet.Count == 0 ? 1 : sectionSet.Count;
        ScaledHeight = Height / divisor ;// INDHEIGHT * _context.Resources.DisplayMetrics.Density;
        Sx = Width - PaddingRight - (float)(1.2 * ScaledWidth);
        Sy = (float)((Height - (ScaledHeight * Sections.Length)) / 2.0);
        _setupThings = true;
    }

    publicoverrideboolOnTouchEvent(MotionEvent motionEvent)
    {
        if (_setupThings)
        {
            var adapter = GetAdapter() as IFastScrollRecyclerViewAdapter;

            var x = motionEvent.GetX();
            var y = motionEvent.GetY();

            switch (motionEvent.Action)
            {
                case MotionEventActions.Down:
                    {
                        if (x < Sx - ScaledWidth || y < Sy || y > (Sy + ScaledHeight * Sections.Length))
                        {
                            returnbase.OnTouchEvent(motionEvent);
                        }
                        else
                        {
                            //// We touched the index barfloat yy = y - PaddingTop - PaddingBottom - Sy;
                            int currentPosition = (int)Math.Floor(yy / ScaledHeight);
                            if (currentPosition < 0) currentPosition = 0;
                            if (currentPosition >= Sections.Length) currentPosition = Sections.Length - 1;
                            Section = Sections[currentPosition];
                            ShowLetter = true;
                            int positionInData = 0;
                            if (adapter.GetMapIndex().ContainsKey(Section.ToUpper()))
                            {
                                positionInData = adapter.GetMapIndex()[Section.ToUpper()];
                            }

                            (GetLayoutManager() as LinearLayoutManager).ScrollToPositionWithOffset(positionInData, 20);
                            Invalidate();
                        }
                        break;
                    }
                case MotionEventActions.Move:
                    {
                        if (!ShowLetter && (x < Sx - ScaledWidth || y < Sy || y > (Sy + ScaledHeight * Sections.Length)))
                        {
                            returnbase.OnTouchEvent(motionEvent);
                        }
                        else
                        {
                            float yy = y - Sy;
                            int currentPosition = (int)Math.Floor(yy / ScaledHeight);
                            if (currentPosition < 0) currentPosition = 0;
                            if (currentPosition >= Sections.Length) currentPosition = Sections.Length - 1;
                            Section = Sections[currentPosition];
                            ShowLetter = true;
                            int positionInData = 0;
                            if (adapter.GetMapIndex().ContainsKey(Section.ToUpper()))
                                positionInData = adapter.GetMapIndex()[Section.ToUpper()];
                            (GetLayoutManager() as LinearLayoutManager).ScrollToPositionWithOffset(positionInData, 20);
                            Invalidate();
                        }
                        break;
                    }
                case MotionEventActions.Up:
                    {
                        _listHandler = new ListHandler(this);
                        _listHandler.DelayClear();
                        if (x < Sx - ScaledWidth || y < Sy || y > (Sy + ScaledHeight * Sections.Length))
                        {
                            returnbase.OnTouchEvent(motionEvent);
                        }
                        else
                        {
                            returntrue;
                        }
                    }
            }
        }

        returntrue;
    }

    privateclassListHandler
    {
        FastScrollRecyclerView _parent;
        publicListHandler (FastScrollRecyclerView parent)
        {
            _parent = parent;
        }

        publicasyncvoidDelayClear()
        {
            await Task.Delay(100);
            _parent.ShowLetter = false;
            _parent.Invalidate();
        }
    }
}

//

publicclassFastScrollRecyclerViewItemDecoration : ItemDecoration
    {
        private Context _context;
        publicFastScrollRecyclerViewItemDecoration(Context context)
        {
            _context = context;
        }

        publicoverridevoidOnDrawOver(Canvas canvas, RecyclerView parent, State state)
        {
            base.OnDrawOver(canvas, parent, state);

            float scaledWidth = ((FastScrollRecyclerView)parent).ScaledWidth;
            float sx = ((FastScrollRecyclerView)parent).Sx;
            float scaledHeight = ((FastScrollRecyclerView)parent).ScaledHeight;
            float sy = ((FastScrollRecyclerView)parent).Sy;
            string[] sections = ((FastScrollRecyclerView)parent).Sections;
            string section = ((FastScrollRecyclerView)parent).Section;
            bool showLetter = ((FastScrollRecyclerView)parent).ShowLetter;

            // We draw the letter in the middleif (showLetter & section != null && !section.Equals(""))
            {
                //overlay everything when displaying selected index Letter in the middle
                Paint overlayDark = new Paint();
                overlayDark.Color = Color.Black;
                overlayDark.Alpha = 100;
                canvas.DrawRect(0, 0, parent.Width, parent.Height, overlayDark);
                float middleTextSize = _context.Resources.GetDimension(Resource.Dimension.fast_scroll_overlay_text_size );
                Paint middleLetter = new Paint();
                middleLetter.Color = new Color(ContextCompat.GetColor(_context, Resource.Color.primary));
                middleLetter.TextSize = middleTextSize;
                middleLetter.AntiAlias = true;
                middleLetter.FakeBoldText = true;
                middleLetter.SetStyle(Paint.Style.Fill);
                int xPos = (canvas.Width - (int)middleTextSize) / 2;
                int yPos = (int)((canvas.Height / 2) - ((middleLetter.Descent() + middleLetter.Ascent()) / 2));


                canvas.DrawText(section.ToUpper(), xPos, yPos, middleLetter);
            }

            //        // draw indez A-Z

            Paint textPaint = new Paint();
            textPaint.AntiAlias = true;
            textPaint.SetStyle(Paint.Style.Fill);

            for (int i = 0; i < sections.Length; i++)
            {
                if (showLetter & section != null && !section.Equals("") && section != null
                        && sections[i].ToUpper().Equals(section.ToUpper()))
                {
                    textPaint.Color = Color.White;
                    textPaint.Alpha = 255;
                    textPaint.FakeBoldText = true;
                    textPaint.TextSize = scaledWidth / 2;
                    canvas.DrawText(sections[i].ToUpper(),
                            sx + textPaint.TextSize / 2, sy + parent.PaddingTop
                                    + scaledHeight * (i + 1), textPaint);
                    textPaint.TextSize = scaledWidth;
                    canvas.DrawText("•",
                            sx - textPaint.TextSize / 3, sy + parent.PaddingTop
                                    + scaledHeight * (i + 1) + scaledHeight / 3, textPaint);

                }
                else
                {
                    textPaint.Color = new Color(ContextCompat.GetColor(_context, Resource.Color.primary));
                    textPaint.Alpha = 200;
                    textPaint.FakeBoldText = false;
                    textPaint.TextSize = scaledWidth / 2;
                    canvas.DrawText(sections[i].ToUpper(),
                            sx + textPaint.TextSize / 2, sy + parent.PaddingTop
                                    + scaledHeight * (i + 1), textPaint);
                }
            }
        }
    }

Post a Comment for "Recyclerview With Alphabet Index"