• 8.快速索引、listview


    实现这样的效果

    布局:
    1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    2. xmlns:tools="http://schemas.android.com/tools"
    3. android:layout_width="match_parent"
    4. android:layout_height="match_parent"
    5. tools:context=".MainActivity" >
    6. <ListView
    7. android:id="@+id/lv_main"
    8. android:layout_width="match_parent"
    9. android:layout_height="match_parent" >
    10. </ListView>
    11. <com.itheima.quickindex.ui.QuickIndexBar
    12. android:id="@+id/bar"
    13. android:layout_width="30dp"
    14. android:layout_height="match_parent"
    15. android:layout_alignParentRight="true"
    16. android:background="#ff0000" />
    17. <TextView
    18. android:id="@+id/tv_center"
    19. android:layout_width="160dp"
    20. android:layout_height="100dp"
    21. android:background="@drawable/bg_index"
    22. android:gravity="center"
    23. android:textSize="32sp"
    24. android:visibility="gone"
    25. android:textColor="#ffffff"
    26. android:layout_centerInParent="true"
    27. android:text="A" />
    28. </RelativeLayout>
    字的shape:
    1. <shape xmlns:android="http://schemas.android.com/apk/res/android"
    2. android:shape="rectangle" >
    3. <solid android:color="#66000000"/>
    4. <corners android:radius="20dp"/>
    5. </shape>
    QuickIndexBar

    1. /**
    2. * 快速索引
    3. *
    4. * 用于根据字母快速定位联系人
    5. * @author poplar
    6. *
    7. */
    8. public class QuickIndexBar extends View {
    9. private static final String[] LETTERS = new String[]{
    10. "A", "B", "C", "D", "E", "F",
    11. "G", "H", "I", "J", "K", "L",
    12. "M", "N", "O", "P", "Q", "R",
    13. "S", "T", "U", "V", "W", "X",
    14. "Y", "Z"};
    15. private static final String TAG = "TAG";
    16. private Paint mPaint;
    17. private int cellWidth;
    18. private float cellHeight;
    19. /**
    20. * 暴露一个字母的监听,交给main执行
    21. */
    22. public interface OnLetterUpdateListener{
    23. void onLetterUpdate(String letter);
    24. }
    25. private OnLetterUpdateListener listener;
    26. public OnLetterUpdateListener getListener() {
    27. return listener;
    28. }
    29. /**
    30. * 设置字母更新监听
    31. * @param listener
    32. */
    33. public void setListener(OnLetterUpdateListener listener) {
    34. this.listener = listener;
    35. }
    36. public QuickIndexBar(Context context) {
    37. this(context, null);
    38. }
    39. public QuickIndexBar(Context context, AttributeSet attrs) {
    40. this(context, attrs, 0);//这样写,只需要在三个参数的构造函数初始化就可以了
    41. }
    42. public QuickIndexBar(Context context, AttributeSet attrs, int defStyle) {
    43. super(context, attrs, defStyle);
    44. mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    45. mPaint.setColor(Color.WHITE);
    46. mPaint.setTypeface(Typeface.DEFAULT_BOLD);//当点中的时候变粗
    47. }
    48. @Override
    49. protected void onDraw(Canvas canvas) {
    50. for (int i = 0; i < LETTERS.length; i++) {
    51. String text = LETTERS[i];
    52. // 计算坐标
    53. int x = (int) (cellWidth / 2.0f - mPaint.measureText(text) / 2.0f);//先转成float再转成int,因为有可能丢失精度
    54. // 获取文本的高度
    55. Rect bounds = new Rect();// 矩形
    56. mPaint.getTextBounds(text, 0, text.length(), bounds);//字是矩形,通过矩形获得高
    57. int textHeight = bounds.height();
    58. int y = (int) (cellHeight / 2.0f + textHeight / 2.0f + i * cellHeight);
    59. // 根据按下的字母, 设置画笔颜色
    60. mPaint.setColor(touchIndex == i ? Color.GRAY : Color.WHITE);
    61. // 绘制文本A-Z
    62. canvas.drawText(text, x, y, mPaint);
    63. }
    64. }
    65. int touchIndex = -1;
    66. @Override
    67. public boolean onTouchEvent(MotionEvent event) {
    68. int index = -1;
    69. switch (MotionEventCompat.getActionMasked(event)) {
    70. case MotionEvent.ACTION_DOWN:
    71. // 获取当前触摸到的字母索引
    72. index = (int) (event.getY() / cellHeight);
    73. if(index >= 0 && index < LETTERS.length){
    74. // 判断是否跟上一次触摸到的一样
    75. if(index != touchIndex) {
    76. if(listener != null){
    77. listener.onLetterUpdate(LETTERS[index]);
    78. }
    79. Log.d(TAG, "onTouchEvent: " + LETTERS[index]);
    80. touchIndex = index;
    81. }
    82. }
    83. break;
    84. case MotionEvent.ACTION_MOVE:
    85. index = (int) (event.getY() / cellHeight);
    86. if(index >= 0 && index < LETTERS.length){
    87. // 判断是否跟上一次触摸到的一样
    88. if(index != touchIndex){
    89. if(listener != null){
    90. listener.onLetterUpdate(LETTERS[index]);
    91. }
    92. Log.d(TAG, "onTouchEvent: " + LETTERS[index]);
    93. touchIndex = index;
    94. }
    95. }
    96. break;
    97. case MotionEvent.ACTION_UP:
    98. touchIndex = -1;
    99. break;
    100. default:
    101. break;
    102. }
    103. invalidate();
    104. return true;
    105. }
    106. @Override
    107. protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    108. super.onSizeChanged(w, h, oldw, oldh);
    109. // 获取单元格的宽和高
    110. cellWidth = getMeasuredWidth();
    111. int mHeight = getMeasuredHeight();
    112. cellHeight = mHeight * 1.0f / LETTERS.length;
    113. }
    114. }
    PinyinUtils
    1. public class PinyinUtils {
    2. /**
    3. * 根据传入的字符串(包含汉字),得到拼音
    4. * 黑马 -> HEIMA
    5. * 黑 马*& -> HEIMA
    6. * 黑马f5 -> HEIMA
    7. * @param str 字符串
    8. * @return
    9. */
    10. public static String getPinyin(String str) {
    11. HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat();
    12. format.setCaseType(HanyuPinyinCaseType.UPPERCASE);
    13. format.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
    14. StringBuilder sb = new StringBuilder();
    15. char[] charArray = str.toCharArray();
    16. for (int i = 0; i < charArray.length; i++) {
    17. char c = charArray[i];
    18. // 如果是空格, 跳过
    19. if(Character.isWhitespace(c)){
    20. continue;
    21. }
    22. if(c >= -127 && c < 128){
    23. // 肯定不是汉字
    24. sb.append(c);
    25. }else {
    26. String s = "";
    27. try {
    28. // 通过char得到拼音集合. 单 -> dan, shan
    29. s = PinyinHelper.toHanyuPinyinStringArray(c, format)[0];
    30. sb.append(s);
    31. } catch (BadHanyuPinyinOutputFormatCombination e) {
    32. e.printStackTrace();
    33. sb.append(s);
    34. }
    35. }
    36. }
    37. return sb.toString();
    38. }
    39. }
    Person
    1. public class Person implements Comparable<Person>{//实现比较功能
    2. private String name;
    3. private String pinyin;
    4. public Person(String name) {
    5. super();
    6. this.name = name;
    7. this.pinyin = PinyinUtils.getPinyin(name);
    8. }
    9. public String getName() {
    10. return name;
    11. }
    12. public void setName(String name) {
    13. this.name = name;
    14. }
    15. public String getPinyin() {
    16. return pinyin;
    17. }
    18. public void setPinyin(String pinyin) {
    19. this.pinyin = pinyin;
    20. }
    21. @Override
    22. public int compareTo(Person another) {
    23. return this.pinyin.compareTo(another.getPinyin());
    24. }
    25. }
    adapter布局
    1. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    2. android:layout_width="match_parent"
    3. android:layout_height="match_parent"
    4. android:orientation="vertical" >
    5. <TextView
    6. android:id="@+id/tv_index"
    7. android:layout_width="match_parent"
    8. android:layout_height="40dp"
    9. android:background="#888888"
    10. android:gravity="center_vertical"
    11. android:paddingLeft="20dp"
    12. android:text="A"
    13. android:textColor="#ffffff"
    14. android:textSize="20sp" />
    15. <TextView
    16. android:id="@+id/tv_name"
    17. android:layout_width="match_parent"
    18. android:layout_height="50dp"
    19. android:gravity="center_vertical"
    20. android:paddingLeft="20dp"
    21. android:text="宋江"
    22. android:textSize="24sp" />
    23. </LinearLayout>
    HaoHanAdapter
    1. public class HaoHanAdapter extends BaseAdapter {
    2. private Context mContext;
    3. private ArrayList<Person> persons;
    4. public HaoHanAdapter(Context mContext, ArrayList<Person> persons) {
    5. this.mContext = mContext;
    6. this.persons = persons;
    7. }
    8. @Override
    9. public int getCount() {
    10. // TODO Auto-generated method stub
    11. return persons.size();
    12. }
    13. @Override
    14. public Object getItem(int position) {
    15. return persons.get(position);
    16. }
    17. @Override
    18. public long getItemId(int position) {
    19. return position;
    20. }
    21. @Override
    22. public View getView(int position, View convertView, ViewGroup parent) {
    23. View view = convertView;
    24. if(convertView == null){
    25. view = view.inflate(mContext, R.layout.item_list, null);
    26. }
    27. ViewHolder mViewHolder = ViewHolder.getHolder(view);
    28. Person p = persons.get(position);
    29. String str = null;
    30. String currentLetter = p.getPinyin().charAt(0) + "";
    31. // 根据上一个首字母,决定当前是否显示字母
    32. if(position == 0){
    33. str = currentLetter;
    34. }else {
    35. // 上一个人的拼音的首字母
    36. String preLetter = persons.get(position - 1).getPinyin().charAt(0) + "";
    37. if(!TextUtils.equals(preLetter, currentLetter)){
    38. str = currentLetter;
    39. }
    40. }
    41. // 根据str是否为空,决定是否显示索引栏
    42. mViewHolder.mIndex.setVisibility(str == null ? View.GONE : View.VISIBLE);
    43. mViewHolder.mIndex.setText(currentLetter);
    44. mViewHolder.mName.setText(p.getName());
    45. return view;
    46. }
    47. static class ViewHolder {
    48. TextView mIndex;
    49. TextView mName;
    50. public static ViewHolder getHolder(View view) {//了解这种写法
    51. Object tag = view.getTag();
    52. if(tag != null){
    53. return (ViewHolder)tag;
    54. }else {
    55. ViewHolder viewHolder = new ViewHolder();
    56. viewHolder.mIndex = (TextView) view.findViewById(R.id.tv_index);
    57. viewHolder.mName = (TextView) view.findViewById(R.id.tv_name);
    58. view.setTag(viewHolder);
    59. return viewHolder;
    60. }
    61. }
    62. }
    63. }
    MainActivity
    1. public class MainActivity extends Activity {
    2. private ListView mMainList;
    3. private ArrayList<Person> persons;
    4. private TextView tv_center;
    5. @Override
    6. protected void onCreate(Bundle savedInstanceState) {
    7. super.onCreate(savedInstanceState);
    8. setContentView(R.layout.activity_main);
    9. QuickIndexBar bar = (QuickIndexBar) findViewById(R.id.bar);
    10. // 设置监听,和回调一个意思
    11. bar.setListener(new OnLetterUpdateListener() {
    12. @Override
    13. public void onLetterUpdate(String letter) {
    14. // Utils.showToast(getApplicationContext(), letter);
    15. showLetter(letter);
    16. // 根据字母定位ListView, 找到集合中第一个以letter为拼音首字母的对象,得到索引
    17. for (int i = 0; i < persons.size(); i++) {
    18. Person person = persons.get(i);
    19. String l = person.getPinyin().charAt(0) + "";
    20. if(TextUtils.equals(letter, l)){
    21. // 匹配成功
    22. mMainList.setSelection(i);
    23. break;
    24. }
    25. }
    26. }
    27. });
    28. mMainList = (ListView) findViewById(R.id.lv_main);
    29. persons = new ArrayList<Person>();
    30. // 填充数据 , 排序
    31. fillAndSortData(persons);
    32. mMainList.setAdapter(new HaoHanAdapter(MainActivity.this , persons));
    33. tv_center = (TextView) findViewById(R.id.tv_center);
    34. }
    35. private Handler mHandler = new Handler();
    36. /**
    37. * 显示字母
    38. * @param letter
    39. */
    40. protected void showLetter(String letter) {
    41. tv_center.setVisibility(View.VISIBLE);
    42. tv_center.setText(letter);
    43. mHandler.removeCallbacksAndMessages(null);
    44. mHandler.postDelayed(new Runnable() {
    45. @Override
    46. public void run() {
    47. tv_center.setVisibility(View.GONE);
    48. }
    49. }, 2000);
    50. }
    51. private void fillAndSortData(ArrayList<Person> persons) {
    52. // 填充数据
    53. for (int i = 0; i < Cheeses.NAMES.length; i++) {
    54. String name = Cheeses.NAMES[i];
    55. persons.add(new Person(name));
    56. }
    57. // 进行排序
    58. Collections.sort(persons);
    59. }
    60. }








    附件列表

    • 相关阅读:
      制作你的第一个HTML 5游戏
      拒绝臆想,让我们脚踏实地做设计!
      HTML 5或者Silverlight?
      如何替换掉回车键
      杀死团队的武器与修复团队的方法
      Google趋势中显示jQuery是最流行的JavaScript框架
      关于脚本载入器的思考
      简化Web开发的12个HTML5CSS框架
      线框图(demo草图)制作的总结
      江苏南通周边经纬度
    • 原文地址:https://www.cnblogs.com/sixrain/p/5041941.html
    Copyright © 2020-2023  润新知