自定义类似微信联系人列表姓名首字母边栏索引列表效果
2013-08-05 15:24
555 查看
声明:部分代码和资源并非原创,而是从互联网上下载。资源和代码经过本人的一些优化,逻辑更清晰易读,加强了使用性,嵌入项目时更容易。
效果类似于
先来看一下右边的SideBar字母索引列表效果如何实现:
package org.initialltouchlist; import com.example.listsildedel.R; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Paint.Style; import android.graphics.drawable.ColorDrawable; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; import android.widget.HeaderViewListAdapter; import android.widget.ListView; import android.widget.SectionIndexer; import android.widget.TextView; public class SideBar extends View { private char[] l; private SectionIndexer sectionIndexter = null; private ListView list; private TextView mDialogText; Bitmap mbitmap; private int type = 1; private int color = 0xff858c94; public SideBar(Context context) { super(context); init(); } public SideBar(Context context, AttributeSet attrs) { super(context, attrs); init(); } private void init() { l = new char[] { '!', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '#' }; mbitmap = BitmapFactory.decodeResource(getResources(), R.drawable.scroll_bar_search_icon); } public SideBar(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(); } public void setListView(ListView _list) { list = _list; HeaderViewListAdapter ha = (HeaderViewListAdapter) _list.getAdapter(); NameAdapter ad = (NameAdapter) ha.getWrappedAdapter(); sectionIndexter = (SectionIndexer) ad; } public void setTextView(TextView mDialogText) { this.mDialogText = mDialogText; } public boolean onTouchEvent(MotionEvent event) { super.onTouchEvent(event); int i = (int) event.getY(); int idx = i / (getMeasuredHeight() / l.length); if (idx >= l.length) { idx = l.length - 1; } else if (idx < 0) { idx = 0; } if (event.getAction() == MotionEvent.ACTION_DOWN || event.getAction() == MotionEvent.ACTION_MOVE) { setBackgroundResource(R.drawable.scrollbar_bg); mDialogText.setVisibility(View.VISIBLE); /** * 中央显示的提示首字符 */ if (idx == 0) { mDialogText.setText("Search"); mDialogText.setTextSize(16); } else { mDialogText.setText(String.valueOf(l[idx])); mDialogText.setTextSize(34); } if (sectionIndexter == null) { sectionIndexter = (SectionIndexer) list.getAdapter(); } int position = sectionIndexter.getPositionForSection(l[idx]); if (position == -1) { return true; } list.setSelection(position); } else { mDialogText.setVisibility(View.INVISIBLE); } if (event.getAction() == MotionEvent.ACTION_UP) { setBackgroundDrawable(new ColorDrawable(0x00000000)); } return true; } Paint paint = new Paint(); protected void onDraw(Canvas canvas) { paint.setColor(color); paint.setTextSize(12); paint.setStyle(Style.FILL); paint.setAntiAlias(true); paint.setTextAlign(Paint.Align.CENTER); float widthCenter = getMeasuredWidth() / 2; if (l.length > 0) { float height = getMeasuredHeight() / l.length; for (int i = 0; i < l.length; i++) { if (i == 0 && type != 2) { canvas.drawBitmap(mbitmap, widthCenter - 7, (i + 1) * height - height / 2, paint); } else canvas.drawText(String.valueOf(l[i]), widthCenter, (i + 1) * height, paint); } } this.invalidate(); super.onDraw(canvas); } }
onTouchEvent方法里面,实现了让屏幕中央的TextView显示正在触摸到的字母索引,并让ListView对象找到选定字母的分段位置,直接弹到列表的该字母的位置。
onDraw不用说了,绘制右边栏条。
再看下适配器类实现:NameAdapter.java
package org.initialltouchlist; import java.util.List; import com.example.listsildedel.R; import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.SectionIndexer; import android.widget.TextView; public class NameAdapter extends BaseAdapter implements SectionIndexer { private List<Content> list = null; private Context mContext; public NameAdapter(Context mContext, List<Content> list) { this.mContext = mContext; this.list = list; } public int getCount() { return this.list.size(); } public Object getItem(int position) { return null; } public long getItemId(int position) { return position; } public View getView(final int position, View view, ViewGroup arg2) { ViewHolder viewHolder = null; if (view == null) { viewHolder = new ViewHolder(); view = LayoutInflater.from(mContext).inflate(R.layout.item, null); viewHolder.tvTitle = (TextView) view.findViewById(R.id.title); viewHolder.tvLetter = (TextView) view.findViewById(R.id.catalog); view.setTag(viewHolder); } else { viewHolder = (ViewHolder) view.getTag(); } final Content mContent = list.get(position); if (position == 0) { viewHolder.tvLetter.setVisibility(View.VISIBLE); viewHolder.tvLetter.setText(mContent.getLetter()); } else { String lastCatalog = list.get(position - 1).getLetter(); if (mContent.getLetter().equals(lastCatalog)) { viewHolder.tvLetter.setVisibility(View.GONE); } else { viewHolder.tvLetter.setVisibility(View.VISIBLE); viewHolder.tvLetter.setText(mContent.getLetter()); } } viewHolder.tvTitle.setText(this.list.get(position).getName()); return view; } final static class ViewHolder { TextView tvTitle; TextView tvLetter; } public Object[] getSections() { return null; } public int getSectionForPosition(int position) { return 0; } public int getPositionForSection(int section) { Content mContent; String l; if (section == '!') { return 0; } else { for (int i = 0; i < getCount(); i++) { mContent = (Content) list.get(i); l = mContent.getLetter(); char firstChar = l.toUpperCase().charAt(0); if (firstChar == section) { return i + 1; } } } mContent = null; l = null; return -1; } }
请关注一下上述代码的getPositionForSection方法的实现。
上述代码需要实体类Content.java:
package org.initialltouchlist; public class Content { private String letter;//存放首字母属性,我们需要使用这个属性进行对比来对列表进行排序 private String name; public Content(String letter, String name) { super(); this.letter = letter; this.name = name; } public String getLetter() { return letter; } public void setLetter(String letter) { this.letter = letter; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
现在我们要实现Comparator接口来进行首字母对比
package org.initialltouchlist; import java.util.Comparator; public class PinyinComparator implements Comparator<Content> { public int compare(Content o1, Content o2) { if (o1.getLetter().equals("@") || o2.getLetter().equals("#")) { return -1; } else if (o1.getLetter().equals("#") || o2.getLetter().equals("@")) { return 1; } else { return o1.getLetter().compareTo(o2.getLetter()); } } }
如果需要排序的数组当中都是汉字怎么办?我们需要取首个汉字的拼音首字母来进行比较。那我们可以通过以下代码来实现获取汉字的首个汉字的拼音。
注意,这需要需要第三方类库Pinyin4j 下载:
package org.initialltouchlist; import net.sourceforge.pinyin4j.PinyinHelper; public class PinyinLetterHelper { /** * 获取人名的拼音首字母并且大写化 * * @param name * 人名字符串,允许开头包含英文数字和下划线 * @return */ public static String getPinyinFirstLetter(String name) { String firstletter = "#"; if (name != null) { // 转换前不管是中文还是英文直接取开头字符 char initial = name.charAt(0); //System.out.print(initial + " ---From: " + name); if (!((initial >= 'A' && initial <= 'Z') || (initial >= 'a' && initial <= 'z') || (initial >= '0' && initial <= '9') || initial == '_')) { firstletter = (PinyinHelper.toHanyuPinyinStringArray(initial))[0]; } else { firstletter = initial + ""; } firstletter = firstletter.toUpperCase(); //System.out.print(" -- " + firstletter); char[] firstChar = new char[1]; firstChar[0] = firstletter.charAt(0); firstletter = new String(firstChar); //System.out.println(" --" + firstletter); } return firstletter; } }
以下是使用Demo:
package org.initialltouchlist; import java.util.ArrayList; import java.util.Collections; import java.util.List; import com.example.listsildedel.R; import android.app.Activity; import android.content.Context; import android.graphics.PixelFormat; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.WindowManager; import android.widget.LinearLayout.LayoutParams; import android.widget.ListView; import android.widget.TextView; public class MainActivity extends Activity { private ListView mListView; private SideBar indexBar; private WindowManager mWindowManager; private TextView mDialogText; private View head; @Override public void onCreate(Bundle savedInstanceState) { // 启动activity时不自动弹出软键盘 getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN); super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mListView = (ListView) this.findViewById(R.id.list); indexBar = (SideBar) findViewById(R.id.sideBar); mDialogText = (TextView) LayoutInflater.from(this).inflate(R.layout.list_position, null); head = LayoutInflater.from(this).inflate(R.layout.head, null); mListView.addHeaderView(head); mDialogText.setVisibility(View.INVISIBLE); mWindowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE); WindowManager.LayoutParams lp = new WindowManager.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.TYPE_APPLICATION, WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, PixelFormat.TRANSLUCENT); mWindowManager.addView(mDialogText, lp); indexBar.setTextView(mDialogText); // 初始化数据 List<Content> list = new ArrayList<Content>(); getDataIntoList(list); // 根据a-z进行排序 Collections.sort(list, new PinyinComparator()); // 实例化自定义内容适配类 NameAdapter adapter = new NameAdapter(this, list); // 为listView设置适配 mListView.setAdapter(adapter); // 设置SideBar的ListView内容实现点击a-z中任意一个进行定位 indexBar.setListView(mListView); } /** * 将内容填充到list中 * * @param list */ public void getDataIntoList(List<Content> list) { String[] array = getResources().getStringArray(R.array.default_smiley_texts); for (int i = 0; i < array.length; i++) { String string = PinyinLetterHelper.getPinyinFirstLetter(array[i]); list.add(new Content(string, array[i])); } } }
本项目所有代码和资源zip包,可以直接导入Eclipse:
http://download.csdn.net/detail/lp8800/5872481
相关文章推荐
- Android自定义View——实现联系人列表字母索引
- 微信联系人列表点击侧边栏首字母定位到相应联系人列表的实现方法
- JavaScript仿微信(电话)联系人列表滑动字母索引实例讲解(推荐)
- 仿微信联系人列表滑动字母索引
- 微信联系人列表点击侧边栏首字母定位到相应联系人列表的实现方法
- Android自定义类似联系人列表的 快速索引控件
- 类似微信的联系人根据字母排列查询
- Android自定义View实现通讯录字母索引(仿微信通讯录)
- Android 仿联系人列表 实现ListView的A-Z字母排序和过滤搜索功能,并挤压效果(一)
- Andorid学习笔记 :实现对ListView列表数据添加字母索引效果
- android仿微信联系人索引列表
- Android仿微信实现通讯录字母列表索引
- 仿微信联系人列表字母侧滑控件
- Android仿微信通讯录列表侧边栏效果
- 仿微信联系人索引列表ListView
- Android开发之自定义view实现通讯录列表A~Z字母提示效果【附demo源码下载】
- (字母排序搜索)类似微信通讯录效果
- 微信联系人右侧字母滑动索引
- Android进阶学习-使用Canvas自定义ListView的字母索引列表(6)
- iOS仿微信联系人界面中联系人按姓名首字母分类UILocalizedIndexedCollation