IndexBar.java 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. package me.yokeyword.indexablerv;
  2. import android.content.Context;
  3. import android.graphics.Canvas;
  4. import android.graphics.Paint;
  5. import android.graphics.drawable.Drawable;
  6. import android.os.Build;
  7. import android.text.TextUtils;
  8. import android.util.TypedValue;
  9. import android.view.View;
  10. import java.util.ArrayList;
  11. import java.util.Arrays;
  12. import java.util.HashMap;
  13. import java.util.List;
  14. /**
  15. * Created by YoKey on 16/10/6.
  16. */
  17. class IndexBar extends View {
  18. private int mTotalHeight;
  19. private float mTextSpace;
  20. private List<String> mIndexList = new ArrayList<>();
  21. // 首字母 到 mIndexList 的映射
  22. private HashMap<String, Integer> mMapping = new HashMap<>();
  23. private ArrayList<EntityWrapper> mDatas;
  24. private int mSelectionPosition;
  25. private float mIndexHeight;
  26. private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
  27. private Paint mFocusPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
  28. public IndexBar(Context context) {
  29. super(context);
  30. }
  31. void init(Drawable barBg, int barTextColor, int barFocusTextColor, float barTextSize, float textSpace) {
  32. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
  33. setBackground(barBg);
  34. } else {
  35. setBackgroundDrawable(barBg);
  36. }
  37. this.mTextSpace = textSpace;
  38. mPaint.setColor(barTextColor);
  39. mPaint.setTextAlign(Paint.Align.CENTER);
  40. mPaint.setTextSize(barTextSize);
  41. mFocusPaint.setTextAlign(Paint.Align.CENTER);
  42. mFocusPaint.setTextSize(barTextSize + (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 1, getResources().getDisplayMetrics()));
  43. mFocusPaint.setColor(barFocusTextColor);
  44. }
  45. @Override
  46. protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  47. int mode = MeasureSpec.getMode(widthMeasureSpec);
  48. int height = MeasureSpec.getSize(heightMeasureSpec);
  49. if (mIndexList.size() > 0) {
  50. mTotalHeight = (int) (((mIndexList.size() - 1) * mPaint.getTextSize()
  51. + mFocusPaint.getTextSize())
  52. + (mIndexList.size() + 1) * mTextSpace);
  53. }
  54. if (mTotalHeight > height) {
  55. mTotalHeight = height;
  56. }
  57. // // TODO: 16/10/8 Measure AT_MOST
  58. // if (mode == MeasureSpec.AT_MOST) {
  59. // int maxWidth = (int) getResources().getDimension(R.dimen.default_indexBar_layout_width);
  60. // super.onMeasure(MeasureSpec.makeMeasureSpec(maxWidth, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(mTotalHeight, MeasureSpec.EXACTLY));
  61. // return;
  62. // }
  63. super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(mTotalHeight, MeasureSpec.EXACTLY));
  64. }
  65. @Override
  66. protected void onDraw(Canvas canvas) {
  67. super.onDraw(canvas);
  68. if (mIndexList.size() == 0) return;
  69. mIndexHeight = ((float) getHeight()) / mIndexList.size();
  70. for (int i = 0; i < mIndexList.size(); i++) {
  71. if (mSelectionPosition == i) {
  72. canvas.drawText(mIndexList.get(i), getWidth() / 2, mIndexHeight * 0.85f + mIndexHeight * i, mFocusPaint);
  73. } else {
  74. canvas.drawText(mIndexList.get(i), getWidth() / 2, mIndexHeight * 0.85f + mIndexHeight * i, mPaint);
  75. }
  76. }
  77. }
  78. int getPositionForPointY(float y) {
  79. if (mIndexList.size() <= 0) return -1;
  80. int position = (int) (y / mIndexHeight);
  81. if (position < 0) {
  82. position = 0;
  83. } else if (position > mIndexList.size() - 1) {
  84. position = mIndexList.size() - 1;
  85. }
  86. return position;
  87. }
  88. int getSelectionPosition() {
  89. return mSelectionPosition;
  90. }
  91. void setSelectionPosition(int position) {
  92. this.mSelectionPosition = position;
  93. invalidate();
  94. }
  95. int getFirstRecyclerViewPositionBySelection() {
  96. String index = mIndexList.get(mSelectionPosition);
  97. if (mMapping.containsKey(index)) {
  98. return mMapping.get(index);
  99. }
  100. return -1;
  101. }
  102. List<String> getIndexList() {
  103. return mIndexList;
  104. }
  105. void setDatas(boolean showAllLetter, ArrayList<EntityWrapper> datas) {
  106. this.mDatas = datas;
  107. this.mIndexList.clear();
  108. this.mMapping.clear();
  109. ArrayList<String> tempHeaderList = null;
  110. if (showAllLetter) {
  111. mIndexList = Arrays.asList(getResources().getStringArray(R.array.indexable_letter));
  112. mIndexList = new ArrayList<>(mIndexList);
  113. tempHeaderList = new ArrayList<>();
  114. }
  115. for (int i = 0; i < datas.size(); i++) {
  116. EntityWrapper wrapper = datas.get(i);
  117. if (wrapper.getItemType() == EntityWrapper.TYPE_TITLE || wrapper.getIndexTitle() == null) {
  118. String index = wrapper.getIndex();
  119. if (!TextUtils.isEmpty(index)) {
  120. if (!showAllLetter) {
  121. mIndexList.add(index);
  122. } else {
  123. if (IndexableLayout.INDEX_SIGN.equals(index)) {
  124. mIndexList.add(IndexableLayout.INDEX_SIGN);
  125. } else if (mIndexList.indexOf(index) < 0) {
  126. if (wrapper.getHeaderFooterType() == EntityWrapper.TYPE_HEADER && tempHeaderList.indexOf(index) < 0) {
  127. tempHeaderList.add(index);
  128. } else if (wrapper.getHeaderFooterType() == EntityWrapper.TYPE_FOOTER) {
  129. mIndexList.add(index);
  130. }
  131. }
  132. }
  133. if (!mMapping.containsKey(index)) {
  134. mMapping.put(index, i);
  135. }
  136. }
  137. }
  138. }
  139. if (showAllLetter) {
  140. mIndexList.addAll(0, tempHeaderList);
  141. }
  142. requestLayout();
  143. }
  144. void setSelection(int firstVisibleItemPosition) {
  145. if (mDatas == null || mDatas.size() <= firstVisibleItemPosition || firstVisibleItemPosition < 0)
  146. return;
  147. EntityWrapper wrapper = mDatas.get(firstVisibleItemPosition);
  148. int position = mIndexList.indexOf(wrapper.getIndex());
  149. if (mSelectionPosition != position && position >= 0) {
  150. mSelectionPosition = position;
  151. invalidate();
  152. }
  153. }
  154. }