2015-09-28 88 views
4

我正在嘗試構建一個RecyclerView列表,右下角是一個按字母順序排列的索引器。我有清單顯示完美,並能夠滾動。RecyclerView與字母索引

我想知道如果有人可以給我一些指導建設的字母索引。我相信我需要遍歷我的列表並確定使用的字母(我可以這樣做)。然後構建字母列表(對於索引器),然後在選擇字母時使用scrollToPosition(int position)移動到列表中的右側項目。

我無法解決的主要問題不是建立另一個列表,而是兩個列表之間的通信。任何幫助將不勝感激。

回答

8

我相信這是你一直在尋找的,因爲我有

您可以檢查這些庫這裏的信息:

danoz73/RecyclerViewFastScroller

enter image description here

據我記得他是實際上是在recyclerview中製作第一個字母索引器的人。我從來沒有在我的應用中使用它,因爲定製它有很多問題。

AndroidDeveloperLB/LollipopContactsRecyclerViewFastScroller

enter image description here

自述說hes得到了很多做優化的,所以我覺得這是最好的一個我可以使用,但我還沒有取得它在我的應用程序的工作現在。

code-computerlove/FastScrollRecyclerView

enter image description here

我覺得這是你想要右側的設計?所以你使用的這些庫都應該滿足你的需求。

希望它有助於

+0

更多真棒!男人你沒救了我。謝謝:) –

+0

@BassemQoulta你的歡迎兄弟,我很高興它幫助:) – david

+1

Xamarin的FastScrollRecyclerView端口:) – Ryan

1

如果有人想用以上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); 
       } 
      } 
     } 
    }