你的位置:首页 > 操作系统

[操作系统]快速索引

如下是快速索引的效果图,是从网上下的实例。如图实现的难点1:是最右侧的索引是用自定义View来实现的,主要通过onDraw的方法将其画出;

难点2:是如何拿到每个名字的首字母用的是pinyin4j-2.5.0.jar  将汉字转化成拼音再去第一个字符;难点3:ListView的adapte不好实现

下图的布局是一个ListView右侧是一个自定义的View,中间是一个TextView点击的时候显示

                              

如下是自定义的View来实现快速索引

 1 package com.demo.sb.widget; 2  3 import android.content.Context; 4 import android.graphics.Canvas; 5 import android.graphics.Color; 6 import android.graphics.Paint; 7 import android.graphics.Rect; 8 import android.graphics.Typeface; 9 import android.util.AttributeSet; 10 import android.util.Log; 11 import android.view.MotionEvent; 12 import android.view.View; 13  14 /** 15  * 快速索引 用于根据字母快速定位联系人 也就是界面最右边的那个红色竖条 16  *  17  * @author Administrator 18  *  19 */ 20 public class QuickIndexBar extends View { 21  22   private static final String[] LETTERS = new String[] { "A", "B", "C", "D", 23       "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", 24       "R", "S", "T", "U", "V", "W", "X", "Y", "Z" }; 25  26   private Paint mPaint; 27  28   private float cellHeight; 29  30   private int cellWidth; 31  32   /** 33    * 暴露一个字母的监听 34   */ 35   public interface OnLetterUpdateListener { 36     void onLetterUpdate(String letter); 37   } 38  39   private OnLetterUpdateListener listener; 40  41   public OnLetterUpdateListener getListener() { 42     return listener; 43   } 44  45   /** 46    * 设置字母更新的监听 47   */ 48   public void setListener(OnLetterUpdateListener listener) { 49     this.listener = listener; 50   } 51  52   public QuickIndexBar(Context context) { 53     this(context, null); 54     // TODO Auto-generated constructor stub 55   } 56  57   public QuickIndexBar(Context context, AttributeSet attrs) { 58     this(context, attrs, 0); 59     // TODO Auto-generated constructor stub 60   } 61  62   public QuickIndexBar(Context context, AttributeSet attrs, int defStyleAttr) { 63     super(context, attrs, defStyleAttr); 64     mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 65     mPaint.setColor(Color.WHITE); 66     mPaint.setTypeface(Typeface.DEFAULT_BOLD); 67   } 68  69   @Override 70   protected void onSizeChanged(int w, int h, int oldw, int oldh) { 71     // TODO Auto-generated method stub 72     super.onSizeChanged(w, h, oldw, oldh); 73     cellWidth = getMeasuredWidth(); 74  75     int mHeight = getMeasuredHeight(); 76     cellHeight = mHeight * 1.0f / LETTERS.length; 77   } 78  79   /** 80    * 绘制自定义最重要的一步重写onDraw方法 画什么,由Canvas处理 怎么画,由Paint处理 81   */ 82   @Override 83   protected void onDraw(Canvas canvas) { 84     // TODO Auto-generated method stub 85     for (int i = 0; i < LETTERS.length; i++) { 86       String text = LETTERS[i]; 87       // 计算坐标 88       int x = (int) (cellWidth / 2.0f - mPaint.measureText(text) / 2.0f); 89       // 获取文本的高度 90       Rect bounds = new Rect();// 矩形 91       mPaint.getTextBounds(text, 0, text.length(), bounds); 92       int textHeight = bounds.height(); 93       int y = (int) (cellHeight / 2.0f + textHeight / 2.0f + i 94           * cellHeight); 95  96       // 根据按下的字母,设置画笔颜色 97       mPaint.setColor(touchIndex == i ? Color.GRAY : Color.WHITE); 98  99       // 绘制文本A-Z100       canvas.drawText(text, x, y, mPaint);101     }102   }103 104   int touchIndex = -1;105 106   @Override107   public boolean onTouchEvent(MotionEvent event) {108     // TODO Auto-generated method stub109     int index = -1;110     switch (event.getAction()) {111     case MotionEvent.ACTION_DOWN:112       // 获取当前触摸到的字母索引113       index = (int) (event.getY() / cellHeight);114       if (index >= 0 && index < LETTERS.length) {115         // 判断是否跟上一次触摸到的一样116         if (index != touchIndex) {117 118           if (listener != null) {119             listener.onLetterUpdate(LETTERS[index]);120           }121 122           Log.d("jiejie", "onTouchEvent: " + LETTERS[index]);123 124           touchIndex = index;125         }126       }127       break;128     case MotionEvent.ACTION_MOVE:129 130       index = (int) (event.getY() / cellHeight);131       if (index >= 0 && index < LETTERS.length) {132         // 判断是否跟上一次触摸到的一样133         if (index != touchIndex) {134 135           if (listener != null) {136             listener.onLetterUpdate(LETTERS[index]);137           }138 139           Log.d("jiejie", "onTouchEvent : " + LETTERS[index]);140           touchIndex = index;141         }142       }143       break;144     case MotionEvent.ACTION_UP:145       touchIndex = -1;146       break;147     default:148       break;149     }150     // 重新绘制151     invalidate();152     return true;153   }154 }

主代码和布局文件

 1 package com.demo.sb.main; 2  3 import java.util.ArrayList; 4 import java.util.Collections; 5 import com.demo.sb.entity.Cheeses; 6 import com.demo.sb.entity.HaoHanAdapter; 7 import com.demo.sb.entity.Person; 8 import com.demo.sb.utils.DensityUtil; 9 import com.demo.sb.widget.QuickIndexBar; 10 import com.demo.sb.widget.QuickIndexBar.OnLetterUpdateListener; 11 import com.demo.suibian.R; 12 import android.app.Activity; 13 import android.os.Bundle; 14 import android.os.Handler; 15 import android.text.TextUtils; 16 import android.view.View; 17 import android.widget.ListView; 18 import android.widget.TextView; 19  20 /** 21  * 快速索引 22  *  23  * @author Administrator 24  *  25 */ 26 public class Activity_Index extends Activity { 27    28   /**ListView用来展示数据的*/ 29   private ListView mListView; 30    31   /**贮存的数据*/ 32   private ArrayList<Person> persons; 33    34   /**展示所点的字母,相当于Toast*/ 35   private TextView tv_center; 36  37   @Override 38   protected void onCreate(Bundle savedInstanceState) { 39     // TODO Auto-generated method stub 40     super.onCreate(savedInstanceState); 41     setContentView(R.layout.mactivity_index); 42      43     QuickIndexBar bar = (QuickIndexBar) findViewById(R.id.bar); 44     bar.setListener(new OnLetterUpdateListener() { 45  46       @Override 47       public void onLetterUpdate(String letter) { 48         // TODO Auto-generated method stub 49         DensityUtil.showToast(Activity_Index.this, letter); 50         showLetter(letter); 51         // 根据字母定位ListView,找到集合中第一个以letter为拼音首字母的对象,得到索引 52         for (int i = 0; i < persons.size(); i++) { 53           Person p = persons.get(i); 54           String l = p.getPinyin().charAt(0) + ""; 55           if (TextUtils.equals(letter, l)) { 56             mListView.setSelection(i); 57             break; 58           } 59         } 60       } 61     }); 62  63     mListView = (ListView) findViewById(R.id.lv_index); 64     persons = new ArrayList<Person>(); 65     // 填充数据,排序 66     fillAndSortData(persons); 67  68     mListView.setAdapter(new HaoHanAdapter(Activity_Index.this, persons)); 69  70     tv_center = (TextView) findViewById(R.id.tv_center); 71  72   } 73  74   private Handler mHandler = new Handler(); 75  76   /** 77    * 显示字母 78    *  79    * @param letter 80   */ 81   protected void showLetter(String letter) { 82     // TODO Auto-generated method stub 83     tv_center.setVisibility(View.VISIBLE); 84     tv_center.setText(letter); 85  86     mHandler.removeCallbacksAndMessages(null); 87     mHandler.postDelayed(new Runnable() { 88  89       @Override 90       public void run() { 91         // TODO Auto-generated method stub 92         tv_center.setVisibility(View.GONE); 93       } 94     }, 2000); 95   } 96  97   private void fillAndSortData(ArrayList<Person> persons2) { 98     // TODO Auto-generated method stub 99     // 填充数据100     for (int i = 0; i < Cheeses.NAMES.length; i++) {101       String name = Cheeses.NAMES[i];102       persons2.add(new Person(name));103     }104 105     // 进行排序106     Collections.sort(persons2);107   }108 }

 1 <? 2 <RelativeLayout  3   android:layout_width="match_parent" 4   android:layout_height="match_parent" > 5  6   <ListView 7     android:id="@+id/lv_index" 8     android:layout_width="match_parent" 9     android:layout_height="match_parent" />10 11   <com.demo.sb.widget.QuickIndexBar12     android:id="@+id/bar"13     android:layout_width="30dp"14     android:layout_height="match_parent"15     android:layout_alignParentRight="true"16     android:background="#f00" />17 18   <TextView19     android:id="@+id/tv_center"20     android:layout_width="160dp"21     android:layout_height="100dp"22     android:layout_centerInParent="true"23     android:background="@drawable/bg_index"24     android:gravity="center"25     android:text=""26     android:textColor="#fff"27     android:textSize="32sp"28     android:visibility="gone" />29 30 </RelativeLayout>

适配器

 1 package com.demo.sb.entity; 2  3 import java.util.ArrayList; 4  5 import com.demo.sb.utils.DensityUtil; 6 import com.demo.suibian.R; 7  8 import android.content.Context; 9 import android.text.TextUtils;10 import android.view.View;11 import android.view.ViewGroup;12 import android.widget.BaseAdapter;13 import android.widget.TextView;14 15 public class HaoHanAdapter extends BaseAdapter {16 17   private Context mContext;18   private ArrayList<Person> persons;19 20   public HaoHanAdapter(Context mContext, ArrayList<Person> persons) {21     this.mContext = mContext;22     this.persons = persons;23   }24 25   @Override26   public int getCount() {27     // TODO Auto-generated method stub28     return persons.size();29   }30 31   @Override32   public Object getItem(int arg0) {33     // TODO Auto-generated method stub34     return persons.get(arg0);35   }36 37   @Override38   public long getItemId(int arg0) {39     // TODO Auto-generated method stub40     return arg0;41   }42 43   @Override44   public View getView(final int arg0, View arg1, ViewGroup arg2) {45     // TODO Auto-generated method stub46     ViewHolder holder = null;47     if (arg1 == null) {48       arg1 = View.inflate(mContext, R.layout.item_haohanadapter, null);49       holder = new ViewHolder();50       holder.mIndex = (TextView) arg1.findViewById(R.id.item_tv_index);51       holder.mName = (TextView) arg1.findViewById(R.id.item_tv_name);52       arg1.setTag(holder);53     } else {54       holder = (ViewHolder) arg1.getTag();55     }56     57     final Person p = persons.get(arg0);58     String string = null;59     String currentLetter = p.getPinyin().charAt(0) + "";60     // 根据上一个首字母,决定当前是否显示字母61     if (arg0 == 0) {62       string = currentLetter;63     } else {64       // 上一个人的拼音的首字母65       String preLetter = persons.get(arg0 - 1).getPinyin().charAt(0) + "";66       if (!TextUtils.equals(preLetter, currentLetter)) {67         string = currentLetter;68       }69     }70 71     // 根据string 是否为空,决定是否显示索引栏72     holder.mIndex.setVisibility(string == null ? View.GONE : View.VISIBLE);73     holder.mIndex.setText(currentLetter);74     holder.mName.setText(p.getName());75     76     holder.mName.setOnClickListener(new View.OnClickListener() {77       78       @Override79       public void onClick(View view) {80         // TODO Auto-generated method stub81         DensityUtil.showToast(mContext, arg0 + " "+p.getName());82       }83     });84     return arg1;85   }86 87   static class ViewHolder {88     TextView mIndex;89     TextView mName;90   }91 }

实体类

package com.demo.sb.entity;import com.demo.sb.utils.PinyinUtils;public class Person implements Comparable<Person>{  private String name;  private String pinyin;    public Person(String name){    super();    this.name = name;    this.pinyin = PinyinUtils.getPinyin(name);  }        public String getName() {    return name;  }  public void setName(String name) {    this.name = name;  }  public String getPinyin() {    return pinyin;  }  public void setPinyin(String pinyin) {    this.pinyin = pinyin;  }  @Override  public int compareTo(Person another) {    // TODO Auto-generated method stub    return this.pinyin.compareTo(another.getPinyin());  }  }

View Code

汉字转成拼音

package com.demo.sb.utils;import net.sourceforge.pinyin4j.PinyinHelper;import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType;import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;import net.sourceforge.pinyin4j.format.HanyuPinyinToneType;import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination;public class PinyinUtils {  public static String getPinyin(String str) {    HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat();    format.setCaseType(HanyuPinyinCaseType.UPPERCASE);    format.setToneType(HanyuPinyinToneType.WITHOUT_TONE);    StringBuilder sb = new StringBuilder();    char[] charArray = str.toCharArray();    for (int i = 0; i < charArray.length; i++) {      char c = charArray[i];      // 如果是空格, 跳过      if (Character.isWhitespace(c)) {        continue;      }      if (c >= -127 && c < 128) {        // 肯定不是汉字        sb.append(c);      } else {        String s = "";        try {          // 通过char得到拼音集合. 单 -> dan, shan          s = PinyinHelper.toHanyuPinyinStringArray(c, format)[0];          sb.append(s);        } catch (BadHanyuPinyinOutputFormatCombination e) {          e.printStackTrace();          sb.append(s);        }      }    }    return sb.toString();  }}

View Code