【问题标题】:RecyclerView with Alphabet Index带有字母索引的 RecyclerView
【发布时间】:2015-09-28 03:48:38
【问题描述】:

我正在尝试构建一个 RecyclerView 列表,右侧有一个按字母顺序排列的索引器。我的列表显示完美,可以滚动。

我想知道是否有人可以在构建字母索引器方面给我一些指导。我相信我需要遍历我的列表并确定使用的字母(我可以这样做)。然后构建字母列表(用于索引器),然后在选择字母时使用 scrollToPosition(int position) 移动到列表中的右侧项目。

我无法解决的主要问题不是建立另一个列表,而是两个列表之间的通信。任何帮助将不胜感激。

【问题讨论】:

    标签: android listview android-recyclerview


    【解决方案1】:

    我相信这是您一直在寻找的信息

    您可以在此处查看这些库:

    danoz73/RecyclerViewFastScroller

    据我所知,他实际上是在 recyclerview 中制作了第一个字母索引器的人。我从来没有让它在我的应用程序中运行,因为自定义它有很多问题。

    AndroidDeveloperLB/LollipopContactsRecyclerViewFastScroller

    自述文件说他做了很多优化,所以我认为这是我可以使用的最好的,但我现在还没有让它在我的应用程序中工作。

    code-computerlove/FastScrollRecyclerView

    我想这就是你想要的设计吧?因此,您使用的这些库中的任何一个都应该足以满足您的需求。

    希望对你有帮助

    【讨论】:

    • @BassemQoulta 欢迎您的兄弟,我很高兴它有帮助:)
    • Xamarin 端口的 FastScrollRecyclerView 下面:)
    【解决方案2】:

    如果有人想在 Xamarin 中使用上面提到的 FastScrollRecyclerView ,我只是移植了主要类(您仍然需要创建 xml 资源并准备索引等 - 请参阅原始存储库以获取指南,很简单)。

    我在问题页面中包含了建议的调整,以改进 ScrollToPosition 和索引高度(这也使它在横向工作)并且还为异步 Task.Delay 切换了 Java Handler 类。它可能仍然存在问题,否则它是一个直接端口。不过似乎还可以。希望我已经为某人节省了一些时间:)

    public interface IFastScrollRecyclerViewAdapter
    {
        Dictionary<string, int> GetMapIndex();
    }
    

    //

    public class FastScrollRecyclerView : RecyclerView
    {
        public const int INDWIDTH = 25;
        public const int INDHEIGHT = 18;
        public float ScaledWidth { get; set; }
        public float ScaledHeight { get; set; }
        public string[] Sections { get; set; }
        public float Sx { get; set; }
        public float Sy { get; set; }
        public string Section { get; set; }
        public bool ShowLetter { get; set; }
    
        private ListHandler _listHandler;
        private bool _setupThings = false;
        private Context _context;
    
        public FastScrollRecyclerView(Context context) : base(context)
        {
            _context = context;
        }
    
        public FastScrollRecyclerView(Context context, IAttributeSet attrs) : base(context, attrs)
        {
            _context = context;
        }
    
        public FastScrollRecyclerView(Context context, IAttributeSet attrs, int defStyle) : base(context, attrs, defStyle)
        {
            _context = context;
        }
    
        public override void OnDraw(Canvas c)
        {
            if (!_setupThings && GetAdapter() != null)
                SetupThings();
            base.OnDraw(c);
        }
    
        private void SetupThings()
        {
            //create az text data
            var sectionSet = ((IFastScrollRecyclerViewAdapter)GetAdapter()).GetMapIndex().Keys;
            var listSection = new List<string>(sectionSet);
            listSection.Sort();
            Sections = new string[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;
        }
    
        public override bool OnTouchEvent(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))
                            {
                                return base.OnTouchEvent(motionEvent);
                            }
                            else
                            {
                                //// We touched the index bar
                                float 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)))
                            {
                                return base.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))
                            {
                                return base.OnTouchEvent(motionEvent);
                            }
                            else
                            {
                                return true;
                            }
                        }
                }
            }
    
            return true;
        }
    
        private class ListHandler
        {
            FastScrollRecyclerView _parent;
            public ListHandler (FastScrollRecyclerView parent)
            {
                _parent = parent;
            }
    
            public async void DelayClear()
            {
                await Task.Delay(100);
                _parent.ShowLetter = false;
                _parent.Invalidate();
            }
        }
    }
    

    //

    public class FastScrollRecyclerViewItemDecoration : ItemDecoration
        {
            private Context _context;
            public FastScrollRecyclerViewItemDecoration(Context context)
            {
                _context = context;
            }
    
            public override void OnDrawOver(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 middle
                if (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);
                    }
                }
            }
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-05
      • 1970-01-01
      • 1970-01-01
      • 2012-05-12
      • 1970-01-01
      • 2018-04-13
      相关资源
      最近更新 更多