字母索引实现方式主要是通过Adapter继承 SectionIndexer接口,如下
public class HeaderAdapter extends ArrayAdapter<String> implements SectionIndexer { private List<String> items=new ArrayList<String>(); private LayoutInflater mInflater; private int resource; private int textViewResourceId; private String[] sections; private HashMap<String,Integer> maps=new HashMap<String, Integer>(); public HeaderAdapter(Context context, int resource, int textViewResourceId, List<String> items) { super(context, resource, textViewResourceId, items); this.items=items; mInflater=LayoutInflater.from(context); this.resource=resource; this.textViewResourceId=textViewResourceId; //A-Z字母列表 sections=context.getResources().getStringArray(R.array.sections); initMaps(); // TODO Auto-generated constructor stub } private void initMaps(){
//遍历数据源,用来保存相应字母的position位置
for (int i=0;i<items.size();i++) { String start=items.get(i).substring(0,1).toUpperCase(); if(!maps.containsKey(start)){ maps.put(start, i); } } } @Override public int getCount() { // TODO Auto-generated method stub return items.size(); } @Override public String getItem(int position) { // TODO Auto-generated method stub return items.get(position); } @Override public long getItemId(int position) { // TODO Auto-generated method stub return super.getItemId(position); } @Override public int getPosition(String item) { // TODO Auto-generated method stub return super.getPosition(item); } @Override public View getView(int position, View convertView, ViewGroup parent) { // TODO Auto-generated method stub convertView =mInflater.inflate(resource, null); TextView textView=(TextView)convertView.findViewById(textViewResourceId); TextView header=(TextView)convertView.findViewById(R.id.header); String text=items.get(position); String start=text.substring(0, 1).toUpperCase(); if(maps.containsKey(start)&&maps.containsValue(position)){ header.setVisibility(View.VISIBLE); header.setText(start); } textView.setText(text); return convertView; } public int getPositionForSection(int sectionIndex) { // TODO Auto-generated method stub
//主要方法根据字母索引位置,获取需要滚动的position位置
if(maps.get(sections[position])==null){ return -1; } return maps.get(sections[sectionIndex]); } public int getSectionForPosition(int position) { // TODO Auto-generated method stub return 0; } public String[] getSections() { // TODO Auto-generated method stub return sections; } }
2.自定义SearchBar,实现字母索引
public class SearchBar extends View { private String[] section; private int height;
private int indexHeight;// private Paint textPaint; private int width; private int sectionLength; private int curSetion; private Rect mIndicatorRect = new Rect(); private Drawable mIndicatorDrawable; private SectionIndexer mIndexer; private ListView mList; private PopupWindow mPopupWindow; private TextView mPromptText; public SearchBar(Context context) { this(context,null); // TODO Auto-generated constructor stub } public SearchBar(Context context,AttributeSet attr) { this(context,attr,0); // TODO Auto-generated constructor stub } public SearchBar(Context context,AttributeSet attr,int def) { super(context,attr,0); // TODO Auto-generated constructor stub
//A-Z
section=getResources().getStringArray(R.array.sections); sectionLength=section.length; textPaint=new Paint(); textPaint.setColor(Color.BLACK); textPaint.setTextSize(14); mIndicatorDrawable = getResources().getDrawable(R.drawable.bladeview_indicator_normal); mPromptText=(TextView)LayoutInflater.from(context).inflate(R.layout.popup_text, null); } @Override protected void onDraw(Canvas canvas) { // TODO Auto-generated method stub super.onDraw(canvas); int offsetX=0; mIndicatorRect.set(offsetX, indexHeight*curSetion, width, indexHeight*(curSetion+1)); mIndicatorDrawable.setBounds(mIndicatorRect); mIndicatorDrawable.draw(canvas); for (int i=0;i<section.length;i++) { canvas.drawText(section[i], width/2, (i+1)*indexHeight, textPaint); } } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { // TODO Auto-generated method stub super.onMeasure(widthMeasureSpec, heightMeasureSpec); height=getHeight(); width=getWidth(); indexHeight=height/section.length; } @Override public boolean onTouchEvent(MotionEvent event) { // TODO Auto-generated method stub switch (event.getAction()) { case MotionEvent.ACTION_DOWN: float y=event.getY(); curSetion=getIndex(y); setPromptText(curSetion); showPopupWindows(); int position=0; if(mIndexer!=null){ position=mIndexer.getPositionForSection(curSetion); mList.setSelectionFromTop(position, 0); } break; case MotionEvent.ACTION_MOVE: y=event.getY(); curSetion=getIndex(y); setPromptText(curSetion); showPopupWindows(); position=0; if(mIndexer!=null){ position=mIndexer.getPositionForSection(curSetion); mList.setSelectionFromTop(position, 0); } invalidate(); break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: disMissPopupWindows(); break; default: break; } return true; } //根据触摸Y值获取字母Index
private int getIndex(float y){ for (int i = 1; i <sectionLength; i++) { if(y>i*indexHeight&&y<(i+1)*indexHeight){ return i; } } return 0; } public void setListView(ListView list){ Adapter adapter=list.getAdapter(); if(adapter instanceof SectionIndexer){ mIndexer=(SectionIndexer)adapter; mList=list; } } private void setPromptText(int sec){ mPromptText.setText(section[sec]); } private void createPopupWindows(){ if(mPopupWindow==null){ mPopupWindow=new PopupWindow(); mPopupWindow.setContentView(mPromptText); mPopupWindow.setHeight(LayoutParams.WRAP_CONTENT); mPopupWindow.setWidth(LayoutParams.WRAP_CONTENT); ColorDrawable d=new ColorDrawable(Color.TRANSPARENT); mPopupWindow.setBackgroundDrawable(d); } } private void showPopupWindows(){ createPopupWindows(); mPopupWindow.showAtLocation(this, Gravity.CENTER, -1, -1); } private void disMissPopupWindows(){ mPopupWindow.dismiss(); } }
3.测试Activity
public class MainActivity extends Activity { private List<String> items=new ArrayList<String>(); @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ListView list=(ListView)findViewById(R.id.listView1); SearchBar bar=(SearchBar)findViewById(R.id.searchbar); items.add("Action"); items.add("Adventure"); items.add("asg"); items.add("agf"); items.add("bdd"); items.add("ball"); items.add("call"); items.add("Documentary"); items.add("Foreign"); items.add("full"); items.add("History"); items.add("Independent"); items.add("Romance"); list.setAdapter(new HeaderAdapter(this, R.layout.listitem, R.id.items, items)); bar.setListView(list); } @Override public boolean onCreateOptionsMenu(Menu menu) { // getMenuInflater().inflate(R.menu.activity_main, menu); return true; } }
4.效果图