如何实现android刷新listview ListView快速查找功能,关于SectionIndexer接口

ListView分组实现方案(一) - 推酷
ListView分组实现方案(一)
分组的效果如下表格item列所示:
listView分组思路:在item.xml配置文件里面定义一个显示组名的TextView,该TextView只在当前分组的第一个时显示,其它的默认不显示(即View.GONE);
上面其余列的说明:
position列:对应getView方法里面的position参数;
groupIndex:当然position对应的item属于第几个分组,或者说当前分组的索引号。
group_position:当前分组组名所在的item在listView中所处的位置position,比如分组A在listView中的position位置为0,分组B在listView中对应的position为4
item.xml类似如下效果:
//上下布局的linearLayout
&LinearLayout&
//用来显示组名比如A
id=&group_name&/ &
//用来显示item的具体信息比如a1
&TextView id=&item_info&/&
&/LinearLayout&
具体实现思路以及伪代码(getView里面进行处理判断:
1.判断当前position对应的item属于哪一个或者第几个分组;并获取该分组的索引groupIndex
2.根据groupIndex来获取group_position的值,如果group_position==position那么就让group_name对应的textView 显示否则设置为View.GONE;
综上所述整体上getView的伪代码如下:
假设用一个String[] &group_names = {&A&,&B&,&C&,...}来保存分组的名称
int[] &group_positions = {0,4}用来保存当前分组在listView中的位置
Int groupIndex = getGroupIndex(position);
Int group_position = getGroup_Position(groupIndex);
If(group_position==position){
group_name.setVisiable(true);
group_name.setText(group_names(groupIndex));
group_name.setVisiable(false);
获取当前item属于哪一个分组getGroupIndex(position)的伪代码如下
//获取当前position 对应的item
Item item = getItem(position);
//获取groupIndex
Int groupIndex = Arrays.binarySearch(group_names,item.getXXX())
return groupIndex&=0? index:-index-2;
item.getXXX()是获取item中显示字符串第一个首字母的大写字母
//那么获取当前分组在ListView中对应位置的getGroupPosition(groupIndex)的代码就如下所
return group_positions.get(groupIndex)
关于ListView分组,Android提供了SectionIndexer接口,该接口提供了三个方法,实现分组的思路大体上跟上面讲的差不多,就不在赘述(吐槽,个人感觉SectionIndexer的名字不如GroupIndexer好)
下面贴上自己的测试代码:
&?xml version=&1.0& encoding=&utf-8&?&
&RelativeLayout xmlns:android=&/apk/res/android&
android:layout_width=&fill_parent&
android:layout_height=&fill_parent& &
android:id=&@+id/myListView&
android:layout_width=&fill_parent&
android:layout_height=&fill_parent& /&
&/RelativeLayout&
item.xml:
&?xml version=&1.0& encoding=&utf-8&?&
&LinearLayout xmlns:android=&/apk/res/android&
android:layout_width=&fill_parent&
android:layout_height=&wrap_content&
android:orientation=&vertical& &
&!-- 分组名 --&
android:id=&@+id/group_name&
android:layout_width=&fill_parent&
android:layout_height=&wrap_content&
android:background=&@android:color/darker_gray&/&
&!-- 显示信息 --&
android:id=&@+id/item_info&
android:layout_width=&wrap_content&
android:layout_height=&80sp&
android:textSize=&45sp& /&
&/LinearLayout&
public class MainActivity extends Activity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ListView list = (ListView) findViewById(R.id.myListView);
ArrayList&String& stringList = InitListData();
MyAdapter adapter = new MyAdapter(this, stringList);
list.setAdapter(adapter);
private ArrayList&String& InitListData() {
ArrayList&String& stringList = new ArrayList&String&();
stringList.add(&aenegli&);
stringList.add(&abddaf&);
stringList.add(&are&);
stringList.add(&care&);
stringList.add(&ahow&);
stringList.add(&abide&);
stringList.add(&bandidate&);
stringList.add(&bapture&);
stringList.add(&catch&);
stringList.add(&call&);
stringList.add(&abuse&);
stringList.add(&cow&);
Collections.sort(stringList);
return stringL
public class MyAdapter extends BaseAdapter {
private char groupNames[] = {
'A','B','C'
private List&Integer& groupP
private List&String& stringA
//初始化groupPositions
private void initGroupPositions(){
groupPositions = new ArrayList&Integer&();
for (int i = 0; i & stringArray.size(); i++) {
if(i==0){//第一条数据
groupPositions.add(0);
if(i != groupPositions.size()){
String currentStr = stringArray.get(i);
String preStr = stringArray.get(i-1);
char firstCharOfCurrentStr = currentStr.charAt(0);
char firstCharOfPreStr = preStr.charAt(0);
if(firstCharOfCurrentStr!=firstCharOfPreStr){
groupPositions.add(i);
public MyAdapter(Context context, ArrayList&String& arr) {
stringArray =
this.context =
initGroupPositions();
Log.e(&groupPositions== &,groupPositions.size()+&&);
public int getCount() {
return stringArray.size();
public String getItem(int position) {
return stringArray.get(position);
public long getItemId(int position) {
public View getView(int position, View view, ViewGroup parent) {
LayoutInflater inflate = ((Activity) context).getLayoutInflater();
view = (View) inflate.inflate(R.layout.item, null);
TextView groupNameView = (TextView) view.findViewById(R.id.group_name);
String itemStr = stringArray.get(position);
//分组处理
int groupIndex = getGroupIndex(position);
int groupPosition = getGroupPosition(groupIndex);
if(position==groupPosition){
groupNameView.setText(groupNames[groupIndex]+&&);
groupNameView.setVisibility(View.VISIBLE);
groupNameView.setVisibility(View.GONE);
TextView textView = (TextView) view.findViewById(R.id.item_info);
textView.setText(itemStr);
//根据position获取当前item属于第几个group,也就是获取group的索引
public int getGroupIndex(int position) {
String itemStr = getItem(position);
char firstChar = itemStr.toUpperCase().charAt(0);
int groupIndex = Arrays.binarySearch(groupNames, firstChar);
Log.e(&firstChar--groupIndex&,firstChar+&---&+groupIndex);
return groupIndex&=0?groupIndex:-groupIndex-2;
//根据groupIndex来获取当前分组对应于ListView中的position
public int getGroupPosition(int groupIndex){
return groupPositions.get(groupIndex);
已发表评论数()
&&登&&&陆&&
已收藏到推刊!
请填写推刊名
描述不能大于100个字符!
权限设置: 公开
仅自己可见记得在我刚接触Android的时候对系统联系人中的特效很感兴趣,它会根据手机中联系人姓氏的首字母进行分组,并在界面的最顶端始终显示一个当前的分组。如下图所示:
& & & & & & & & & & & & & & & & & & & & & & &
最让我感兴趣的是,当后一个分组和前一个分组相碰时,会产生一个上顶的挤压动画。那个时候我思考了各种方法想去实现这种特效,可是限于功夫不到家,都未能成功。如今两年多过去了,自己也成长了很多,再回头去想想这个功能,突然发现已经有了思路,于是立刻记录下来与大家分享。
首先讲一下需要提前了解的知识点,这里我们最需要用到的就是SectionIndexer,它能够有效地帮助我们对分组进行控制。由于SectionIndexer是一个接口,你可以自定义一个子类来实现SectionIndexer,不过自己再写一个SectionIndexer的实现太麻烦了,这里我们直接使用Android提供好的实现AlphabetIndexer,用它来实现联系人分组功能已经足够了。
AlphabetIndexer的构造函数需要传入三个参数,第一个参数是cursor,第二个参数是sortedColumnIndex整型,第三个参数是alphabet字符串。其中cursor就是把我们从数据库中查出的游标传进去,sortedColumnIndex就是指明我们是使用哪一列进行排序的,而alphabet则是指定字母表排序规则,比如:&ABCDEFGHIJKLMNOPQRSTUVWXYZ&。有了AlphabetIndexer,我们就可以通过它的getPositionForSection和getSectionForPosition方法,找出当前位置所在的分组,和当前分组所在的位置,从而实现类似于系统联系人的分组导航和挤压动画效果,关于AlphabetIndexer更详细的详解,请参考官方文档。
那么我们应该怎样对联系人进行排序呢?前面也提到过,有一个sortedColumnIndex参数,这个sortedColumn到底在哪里呢?我们来看一下系统联系人的raw_contacts这张表(/data/data/com.android.providers.contacts/databases/contacts2.db),这个表结构比较复杂,里面有二十多个列,其中有一列名叫sort_key,这就是我们要找的了!如下图所示:
& & & & & & & & & & & & & & & & & & & & & & &&
可以看到,这一列非常人性化地帮我们记录了汉字所对应的拼音,这样我们就可以通过这一列的值轻松为联系人进行排序了。
下面我们就来开始实现,新建一个Android项目,命名为ContactsDemo。首先我们还是先来完成布局文件,打开或新建activity_main.xml作为程序的主布局文件,在里面加入如下代码:
&xmlns:android=&/apk/res/android&&&&&&&xmlns:tools=&/tools&&&&&&&android:layout_width=&match_parent&&&&&&&android:layout_height=&match_parent&&&&&&&android:orientation=&vertical&&&&&&&&&&&&&&&&&&&&android:id=&@+id/contacts_list_view&&&&&&&&&&&android:layout_width=&fill_parent&&&&&&&&&&&android:layout_height=&wrap_content&&&&&&&&&&&android:layout_alignParentTop=&true&&&&&&&&&&&android:fadingEdge=&none&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&android:id=&@+id/title_layout&&&&&&&&&&&android:layout_width=&fill_parent&&&&&&&&&&&android:layout_height=&18dip&&&&&&&&&&&android:layout_alignParentTop=&true&&&&&&&&&&&android:background=&#303030&&&&&&&&&&&&&&&&&&&&&&&&&&&&android:id=&@+id/title&&&&&&&&&&&&&&&android:layout_width=&wrap_content&&&&&&&&&&&&&&&android:layout_height=&wrap_content&&&&&&&&&&&&&&&android:layout_gravity=&center_horizontal&&&&&&&&&&&&&&&android:layout_marginLeft=&10dip&&&&&&&&&&&&&&&android:textColor=&#ffffff&&&&&&&&&&&&&&&android:textSize=&13sp&&&&&&&&&&&&&&
布局文件很简单,里面放入了一个ListView,用于展示联系人信息。另外还在头部放了一个LinearLayout,里面包含了一个TextView,它的作用是在界面头部始终显示一个当前分组。
然后新建一个contact_item.xml的布局,这个布局用于在ListView中的每一行进行填充,代码如下:
&xmlns:android=&/apk/res/android&&&&&&&android:layout_width=&match_parent&&&&&&&android:layout_height=&match_parent&&&&&&&android:orientation=&vertical&&&&&&&&&&&&&&&&&&&&android:id=&@+id/sort_key_layout&&&&&&&&&&&android:layout_width=&fill_parent&&&&&&&&&&&android:layout_height=&18dip&&&&&&&&&&&android:background=&#303030&&&&&&&&&&&&&&&&&&&&&&&&&&&&android:id=&@+id/sort_key&&&&&&&&&&&&&&&android:layout_width=&wrap_content&&&&&&&&&&&&&&&android:layout_height=&wrap_content&&&&&&&&&&&&&&&android:layout_gravity=&center_horizontal&&&&&&&&&&&&&&&android:layout_marginLeft=&10dip&&&&&&&&&&&&&&&android:textColor=&#ffffff&&&&&&&&&&&&&&&android:textSize=&13sp&&&&&&&&&&&&&&&&&&&&&&&&&&android:id=&@+id/name_layout&&&&&&&&&&&android:layout_width=&fill_parent&&&&&&&&&&&android:layout_height=&50dip&&&&&&&&&&&&&&&&&&&&&&&&&&&&android:layout_width=&wrap_content&&&&&&&&&&&&&&&android:layout_height=&wrap_content&&&&&&&&&&&&&&&android:layout_gravity=&center_vertical&&&&&&&&&&&&&&&android:layout_marginLeft=&10dip&&&&&&&&&&&&&&&android:layout_marginRight=&10dip&&&&&&&&&&&&&&&android:src=&@drawable/icon&&&&&&&&&&&&&&&&&&&&&&&&&&&&android:id=&@+id/name&&&&&&&&&&&&&&&android:layout_width=&wrap_content&&&&&&&&&&&&&&&android:layout_height=&wrap_content&&&&&&&&&&&&&&&android:layout_gravity=&center_vertical&&&&&&&&&&&&&&&android:textColor=&#ffffff&&&&&&&&&&&&&&&android:textSize=&22sp&&&&&&&&&&&&&&
在这个布局文件中,首先是放入了一个和前面完成一样的分组布局,因为不仅界面头部需要展示分组,在每个分组内的第一个无素之前都需要展示分组布局。然后是加入一个简单的LinearLayout,里面包含了一个ImageView用于显示联系人头像,还包含一个TextView用于显示联系人姓名。
这样我们的布局文件就全部写完了,下面开始来真正地实现功能。
先从简单的开始,新建一个Contact实体类:
public&class&Contact&{&&&&&&&&&&&&&&&&private&String&&&&&&&&&&&&&&&&&private&String&sortK&&&&&&&&public&String&getName()&{&&&&&&&&&&return&&&&&&&}&&&&&&&&public&void&setName(String&name)&{&&&&&&&&&&this.name&=&&&&&&&}&&&&&&&&public&String&getSortKey()&{&&&&&&&&&&return&sortK&&&&&&}&&&&&&&&public&void&setSortKey(String&sortKey)&{&&&&&&&&&&this.sortKey&=&sortK&&&&&&}&&&&}&&
这个实体类很简单,只包含了联系人姓名和排序键。
接下来完成联系人列表适配器的编写,新建一个ContactAdapter类继承自ArrayAdapter,加入如下代码:
public&class&ContactAdapter&extends&ArrayAdapter&Contact&&{&&&&&&&&&&&&&&&&private&int&&&&&&&&&&&&&&&&&private&SectionIndexer&mI&&&&&&&&public&ContactAdapter(Context&context,&int&textViewResourceId,&List&Contact&&objects)&{&&&&&&&&&&super(context,&textViewResourceId,&objects);&&&&&&&&&&resource&=&textViewResourceId;&&&&&&}&&&&&&&&@Override&&&&&&public&View&getView(int&position,&View&convertView,&ViewGroup&parent)&{&&&&&&&&&&Contact&contact&=&getItem(position);&&&&&&&&&&LinearLayout&layout&=&null;&&&&&&&&&&if&(convertView&==&null)&{&&&&&&&&&&&&&&layout&=&(LinearLayout)&LayoutInflater.from(getContext()).inflate(resource,&null);&&&&&&&&&&}&else&{&&&&&&&&&&&&&&layout&=&(LinearLayout)&convertV&&&&&&&&&&}&&&&&&&&&&TextView&name&=&(TextView)&layout.findViewById(R.id.name);&&&&&&&&&&LinearLayout&sortKeyLayout&=&(LinearLayout)&layout.findViewById(R.id.sort_key_layout);&&&&&&&&&&TextView&sortKey&=&(TextView)&layout.findViewById(R.id.sort_key);&&&&&&&&&&name.setText(contact.getName());&&&&&&&&&&int&section&=&mIndexer.getSectionForPosition(position);&&&&&&&&&&if&(position&==&mIndexer.getPositionForSection(section))&{&&&&&&&&&&&&&&sortKey.setText(contact.getSortKey());&&&&&&&&&&&&&&sortKeyLayout.setVisibility(View.VISIBLE);&&&&&&&&&&}&else&{&&&&&&&&&&&&&&sortKeyLayout.setVisibility(View.GONE);&&&&&&&&&&}&&&&&&&&&&return&&&&&&&}&&&&&&&&&&&&&&&&&&public&void&setIndexer(SectionIndexer&indexer)&{&&&&&&&&&&mIndexer&=&&&&&&&}&&&&}&&
上面的代码中,最重要的就是getView方法,在这个方法中,我们使用SectionIndexer的getSectionForPosition方法,通过当前的position值拿到了对应的section值,然后再反向通过刚刚拿到的section值,调用getPositionForSection方法,取回新的position值。如果当前的position值和新的position值是相等的,那么我们就可以认为当前position的项是某个分组下的第一个元素,我们应该将分组布局显示出来,而其它的情况就应该将分组布局隐藏。
最后我们来编写程序的主界面,打开或新建MainActivity作为程序的主界面,代码如下所示:
public&class&MainActivity&extends&Activity&{&&&&&&&&&&&&&&&&private&LinearLayout&titleL&&&&&&&&&&&&&&&&private&TextView&&&&&&&&&&&&&&&&&private&ListView&contactsListV&&&&&&&&&&&&&&&&private&ContactAdapter&&&&&&&&&&&&&&&&&private&AlphabetIndexer&&&&&&&&&&&&&&&&&private&List&Contact&&contacts&=&new&ArrayList&Contact&();&&&&&&&&&&&&&&&&private&String&alphabet&=&&#ABCDEFGHIJKLMNOPQRSTUVWXYZ&;&&&&&&&&&&&&&&&&private&int&lastFirstVisibleItem&=&-1;&&&&&&&&@Override&&&&&&protected&void&onCreate(Bundle&savedInstanceState)&{&&&&&&&&&&super.onCreate(savedInstanceState);&&&&&&&&&&setContentView(R.layout.activity_main);&&&&&&&&&&adapter&=&new&ContactAdapter(this,&R.layout.contact_item,&contacts);&&&&&&&&&&titleLayout&=&(LinearLayout)&findViewById(R.id.title_layout);&&&&&&&&&&title&=&(TextView)&findViewById(R.id.title);&&&&&&&&&&contactsListView&=&(ListView)&findViewById(R.id.contacts_list_view);&&&&&&&&&&Uri&uri&=&monDataKinds.Phone.CONTENT_URI;&&&&&&&&&&Cursor&cursor&=&getContentResolver().query(uri,&&&&&&&&&&&&&&&&&&new&String[]&{&&display_name&,&&sort_key&&},&null,&null,&&sort_key&);&&&&&&&&&&if&(cursor.moveToFirst())&{&&&&&&&&&&&&&&do&{&&&&&&&&&&&&&&&&&&String&name&=&cursor.getString(0);&&&&&&&&&&&&&&&&&&String&sortKey&=&getSortKey(cursor.getString(1));&&&&&&&&&&&&&&&&&&Contact&contact&=&new&Contact();&&&&&&&&&&&&&&&&&&contact.setName(name);&&&&&&&&&&&&&&&&&&contact.setSortKey(sortKey);&&&&&&&&&&&&&&&&&&contacts.add(contact);&&&&&&&&&&&&&&}&while&(cursor.moveToNext());&&&&&&&&&&}&&&&&&&&&&startManagingCursor(cursor);&&&&&&&&&&indexer&=&new&AlphabetIndexer(cursor,&1,&alphabet);&&&&&&&&&&adapter.setIndexer(indexer);&&&&&&&&&&if&(contacts.size()&&&0)&{&&&&&&&&&&&&&&setupContactsListView();&&&&&&&&&&}&&&&&&}&&&&&&&&&&&&&&&&private&void&setupContactsListView()&{&&&&&&&&&&contactsListView.setAdapter(adapter);&&&&&&&&&&contactsListView.setOnScrollListener(new&OnScrollListener()&{&&&&&&&&&&&&&&@Override&&&&&&&&&&&&&&public&void&onScrollStateChanged(AbsListView&view,&int&scrollState)&{&&&&&&&&&&&&&&}&&&&&&&&&&&&&&&&@Override&&&&&&&&&&&&&&public&void&onScroll(AbsListView&view,&int&firstVisibleItem,&int&visibleItemCount,&&&&&&&&&&&&&&&&&&&&&&int&totalItemCount)&{&&&&&&&&&&&&&&&&&&int&section&=&indexer.getSectionForPosition(firstVisibleItem);&&&&&&&&&&&&&&&&&&int&nextSecPosition&=&indexer.getPositionForSection(section&+&1);&&&&&&&&&&&&&&&&&&if&(firstVisibleItem&!=&lastFirstVisibleItem)&{&&&&&&&&&&&&&&&&&&&&&&MarginLayoutParams&params&=&(MarginLayoutParams)&titleLayout.getLayoutParams();&&&&&&&&&&&&&&&&&&&&&&params.topMargin&=&0;&&&&&&&&&&&&&&&&&&&&&&titleLayout.setLayoutParams(params);&&&&&&&&&&&&&&&&&&&&&&title.setText(String.valueOf(alphabet.charAt(section)));&&&&&&&&&&&&&&&&&&}&&&&&&&&&&&&&&&&&&if&(nextSecPosition&==&firstVisibleItem&+&1)&{&&&&&&&&&&&&&&&&&&&&&&View&childView&=&view.getChildAt(0);&&&&&&&&&&&&&&&&&&&&&&if&(childView&!=&null)&{&&&&&&&&&&&&&&&&&&&&&&&&&&int&titleHeight&=&titleLayout.getHeight();&&&&&&&&&&&&&&&&&&&&&&&&&&int&bottom&=&childView.getBottom();&&&&&&&&&&&&&&&&&&&&&&&&&&MarginLayoutParams&params&=&(MarginLayoutParams)&titleLayout&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&.getLayoutParams();&&&&&&&&&&&&&&&&&&&&&&&&&&if&(bottom&&&titleHeight)&{&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&float&pushedDistance&=&bottom&-&titleH&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&params.topMargin&=&(int)&pushedD&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&titleLayout.setLayoutParams(params);&&&&&&&&&&&&&&&&&&&&&&&&&&}&else&{&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&if&(params.topMargin&!=&0)&{&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&params.topMargin&=&0;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&titleLayout.setLayoutParams(params);&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&}&&&&&&&&&&&&&&&&&&&&&&&&&&}&&&&&&&&&&&&&&&&&&&&&&}&&&&&&&&&&&&&&&&&&}&&&&&&&&&&&&&&&&&&lastFirstVisibleItem&=&firstVisibleI&&&&&&&&&&&&&&}&&&&&&&&&&});&&&&&&&&}&&&&&&&&&&&&&&&&&&&&private&String&getSortKey(String&sortKeyString)&{&&&&&&&&&&String&key&=&sortKeyString.substring(0,&1).toUpperCase();&&&&&&&&&&if&(key.matches(&[A-Z]&))&{&&&&&&&&&&&&&&return&&&&&&&&&&&}&&&&&&&&&&return&&#&;&&&&&&}&&&&}&&
可以看到,在onCreate方法中,我们从系统联系人数据库中去查询联系人的姓名和排序键,之后将查询返回的cursor直接传入AlphabetIndexer作为第一个参数。由于我们一共就查了两列,排序键在第二列,所以我们第二个sortedColumnIndex参数传入1。第三个alphabet参数这里传入了&#ABCDEFGHIJKLMNOPQRSTUVWXYZ&字符串,因为可能有些联系人的姓名不在字母表范围内,我们统一用#来表示这部分联系人。
然后我们在setupContactsListView方法中监听了ListView的滚动,在onScroll方法中通过getSectionForPosition方法获取第一个可见元素的分组值,然后给该分组值加1,再通过getPositionForSection方法或者到下一个分组中的第一个元素,如果下个分组的第一个元素值等于第一个可见元素的值加1,那就说明下个分组的布局要和界面顶部分组布局相碰了。之后再通过ListView的getChildAt(0)方法,获取到界面上显示的第一个子View,再用view.getBottom获取底部距离父窗口的位置,对比分组布局的高度来对顶部分组布局进行纵向偏移,就可以实现挤压动画的效果了。
最后给出AndroidManifest.xml的代码,由于要读取手机联系人,因此需要加上android.permission.READ_CONTACTS的声明:
&xmlns:android=&/apk/res/android&&&&&&&package=&com.example.contactsdemo&&&&&&&android:versionCode=&1&&&&&&&android:versionName=&1.0&&&&&&&&&&&&&&&&&&&&android:minSdkVersion=&8&&&&&&&&&&&android:targetSdkVersion=&8&&&&&&&&&&&&&&&android:name=&android.permission.READ_CONTACTS&&&&&&&&&&&&&&&&&&&android:allowBackup=&true&&&&&&&&&&&android:icon=&@drawable/ic_launcher&&&&&&&&&&&android:label=&@string/app_name&&&&&&&&&&&android:theme=&@android:style/Theme.NoTitleBar&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&android:name=&com.example.contactsdemo.MainActivity&&&&&&&&&&&&&&&android:label=&@string/app_name&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&android:name=&android.intent.action.MAIN&&&&&&&&&&&&&&&&&&&&&&&android:name=&android.intent.category.LAUNCHER&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
现在我们来运行一下程序,效果如下图所示:
& & & & & & & & & & & & & & & & & & & & & & & &
目前的话,分组导航和挤压动画效果都已经完成了,看起来感觉还是挺不错的,下一篇文章我会带领大家继续完善这个程序,加入字母表快速滚动功能,感兴趣的朋友请继续阅读&。
好了,今天的讲解到此结束,有疑问的朋友请在下面留言。
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:12096次
积分:1067
积分:1067
排名:第18249名
原创:89篇
转载:47篇
(28)(86)(6)(17)转载请注明出处:
前 段时间因为换工作的缘故又恰巧碰到国庆节,所以有段时间自己没有更新博客了,过完国庆到新公司报道,感觉还不错,就是现在住的地方离新公司有点远,地铁 20站,伤不起啊,我每天早上7点多就要起床,然后屁颠屁颠的去挤地铁上班,晚上下班还要挤地铁,先不说路程远,车费一天就要10几块,我的银子啊,有坐 龙华线去上班的深圳程序员不?听说那条线上班高峰期很挤?我没在上班高峰期坐过那趟车,我在民治那边找了个房子,离华强北也不远,关键房租便宜,哈哈,乐 开花了,下个礼拜就要搬过去啦
不 扯了,回到主题,今天给大家带来ListView的A-Z字母排序和过滤搜索功能并且实现汉字转成拼音的功能,我们知道一般我们对联系人,城市列表等实现 A-Z的排序,因为联系人和城市列表我们可以直接从数据库中获取他的汉字拼音,而对于一般的数据,我们怎么实现A-Z的排序,我们需要将汉字转换成拼音就 行了,接下来就带大家实现一般数据的A-Z排序功能,首先先看下效果图
上 面是一个带删除按钮的EditText,我们在输入框中输入可以自动过滤出我们想要的东西,当输入框中没有数据自动替换到原来的数据列表,然后下面一个 ListView用来显示数据列表,右侧是一个字母索引表,当我们点击不同的字母,ListView会定位到该字母地方,了解了布局之后,我们先看下项目 结构吧
我按照项目中类的顺序来一一介绍其功能
1.SortModel 一个实体类,里面一个是ListView的name,另一个就是显示的name拼音的首字母
package&com.example.&&
public&class&SortModel&{&&
&&&&private&String&&&&
&&&&private&String&sortL&&
&&&&public&String&getName()&{&&
&&&&&&&&return&&&
&&&&public&void&setName(String&name)&{&&
&&&&&&&&this.name&=&&&
&&&&public&String&getSortLetters()&{&&
&&&&&&&&return&sortL&&
&&&&public&void&setSortLetters(String&sortLetters)&{&&
&&&&&&&&this.sortLetters&=&sortL&&
类就是ListView右侧的字母索引View,我们需要使用setTextView(TextView
mTextDialog)来设置用来显示当前按下的字母的TextView,以及使用
setOnTouchingLetterChangedListener方法来设置回调接口,在回调方法
onTouchingLetterChanged(String s)中来处理不同的操作
package&com.example.&&
import&android.content.C&&
import&android.graphics.C&&
import&android.graphics.C&&
import&android.graphics.P&&
import&android.graphics.T&&
import&android.graphics.drawable.ColorD&&
import&android.util.AttributeS&&
import&android.view.MotionE&&
import&android.view.V&&
import&android.widget.TextV&&
public&class&SideBar&extends&View&{&&
&&&&private&OnTouchingLetterChangedListener&onTouchingLetterChangedL&&
&&&&public&static&String[]&b&=&{&"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",&"#"&};&&
&&&&private&int&choose&=&-1;
&&&&private&Paint&paint&=&new&Paint();&&
&&&&private&TextView&mTextD&&
&&&&public&void&setTextView(TextView&mTextDialog)&{&&
&&&&&&&&this.mTextDialog&=&mTextD&&
&&&&public&SideBar(Context&context,&AttributeSet&attrs,&int&defStyle)&{&&
&&&&&&&&super(context,&attrs,&defStyle);&&
&&&&public&SideBar(Context&context,&AttributeSet&attrs)&{&&
&&&&&&&&super(context,&attrs);&&
&&&&public&SideBar(Context&context)&{&&
&&&&&&&&super(context);&&
&&&&protected&void&onDraw(Canvas&canvas)&{&&
&&&&&&&&super.onDraw(canvas);&&
&&&&&&&&int&height&=&getHeight();
&&&&&&&&int&width&=&getWidth();&
&&&&&&&&int&singleHeight&=&height&/&b.
&&&&&&&&for&(int&i&=&0;&i&&&b.&i++)&{&&
&&&&&&&&&&&&paint.setColor(Color.rgb(33,&65,&98));&&
&&&&&&&&&&&&
&&&&&&&&&&&&paint.setTypeface(Typeface.DEFAULT_BOLD);&&
&&&&&&&&&&&&paint.setAntiAlias(true);&&
&&&&&&&&&&&&paint.setTextSize(20);&&
&&&&&&&&&&&&
&&&&&&&&&&&&if&(i&==&choose)&{&&
&&&&&&&&&&&&&&&&paint.setColor(Color.parseColor("#3399ff"));&&
&&&&&&&&&&&&&&&&paint.setFakeBoldText(true);&&
&&&&&&&&&&&&}&&
&&&&&&&&&&&&
&&&&&&&&&&&&float&xPos&=&width&/&2&-&paint.measureText(b[i])&/&2;&&
&&&&&&&&&&&&float&yPos&=&singleHeight&*&i&+&singleH&&
&&&&&&&&&&&&canvas.drawText(b[i],&xPos,&yPos,&paint);&&
&&&&&&&&&&&&paint.reset();
&&&&&&&&}&&
&&&&@Override&&
&&&&public&boolean&dispatchTouchEvent(MotionEvent&event)&{&&
&&&&&&&&final&int&action&=&event.getAction();&&
&&&&&&&&final&float&y&=&event.getY();
&&&&&&&&final&int&oldChoose&=&&&
&&&&&&&&final&OnTouchingLetterChangedListener&listener&=&onTouchingLetterChangedL&&
&&&&&&&&final&int&c&=&(int)&(y&/&getHeight()&*&b.length);
&&&&&&&&switch&(action)&{&&
&&&&&&&&case&MotionEvent.ACTION_UP:&&
&&&&&&&&&&&&setBackgroundDrawable(new&ColorDrawable(0x));&&
&&&&&&&&&&&&choose&=&-1;
&&&&&&&&&&&&invalidate();&&
&&&&&&&&&&&&if&(mTextDialog&!=&null)&{&&
&&&&&&&&&&&&&&&&mTextDialog.setVisibility(View.INVISIBLE);&&
&&&&&&&&&&&&}&&
&&&&&&&&&&&&&&
&&&&&&&&default:&&
&&&&&&&&&&&&setBackgroundResource(R.drawable.sidebar_background);&&
&&&&&&&&&&&&if&(oldChoose&!=&c)&{&&
&&&&&&&&&&&&&&&&if&(c&&=&0&&&&c&&&b.length)&{&&
&&&&&&&&&&&&&&&&&&&&if&(listener&!=&null)&{&&
&&&&&&&&&&&&&&&&&&&&&&&&listener.onTouchingLetterChanged(b[c]);&&
&&&&&&&&&&&&&&&&&&&&}&&
&&&&&&&&&&&&&&&&&&&&if&(mTextDialog&!=&null)&{&&
&&&&&&&&&&&&&&&&&&&&&&&&mTextDialog.setText(b[c]);&&
&&&&&&&&&&&&&&&&&&&&&&&&mTextDialog.setVisibility(View.VISIBLE);&&
&&&&&&&&&&&&&&&&&&&&}&&
&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&choose&=&c;&&
&&&&&&&&&&&&&&&&&&&&invalidate();&&
&&&&&&&&&&&&&&&&}&&
&&&&&&&&&&&&}&&
&&&&&&&&&&&&&&
&&&&&&&&}&&
&&&&&&&&return&&&
&&&&public&void&setOnTouchingLetterChangedListener(&&
&&&&&&&&&&&&OnTouchingLetterChangedListener&onTouchingLetterChangedListener)&{&&
&&&&&&&&this.onTouchingLetterChangedListener&=&onTouchingLetterChangedL&&
&&&&public&interface&OnTouchingLetterChangedListener&{&&
&&&&&&&&public&void&onTouchingLetterChanged(String&s);&&
3.CharacterParser&这个类是将汉字转换成拼音的类,该拼音没有声调的,该类是单例类,其中定义了三个方法,在这个demo中用到的是getSelling(String chs)方法,将词组转换成拼音
package&com.example.&&
public&class&CharacterParser&{&&
&&&&private&static&int[]&pyvalue&=&new&int[]&{-20319,&-20317,&-20304,&-20295,&-20292,&-20283,&-20265,&-20257,&-20242,&-20230,&-20051,&-20036,&-20032,&&
&&&&&&&&&&&&-20026,&-20002,&-19990,&-19986,&-19982,&-19976,&-19805,&-19784,&-19775,&-19774,&-19763,&-19756,&-19751,&-19746,&-19741,&-19739,&-19728,&&
&&&&&&&&&&&&-19725,&-19715,&-19540,&-19531,&-19525,&-19515,&-19500,&-19484,&-19479,&-19467,&-19289,&-19288,&-19281,&-19275,&-19270,&-19263,&-19261,&&
&&&&&&&&&&&&-19249,&-19243,&-19242,&-19238,&-19235,&-19227,&-19224,&-19218,&-19212,&-19038,&-19023,&-19018,&-19006,&-19003,&-18996,&-18977,&-18961,&&
&&&&&&&&&&&&-18952,&-18783,&-18774,&-18773,&-18763,&-18756,&-18741,&-18735,&-18731,&-18722,&-18710,&-18697,&-18696,&-18526,&-18518,&-18501,&-18490,&&
&&&&&&&&&&&&-18478,&-18463,&-18448,&-18447,&-18446,&-18239,&-18237,&-18231,&-18220,&-18211,&-18201,&-18184,&-18183,&-18181,&-18012,&-17997,&-17988,&&
&&&&&&&&&&&&-17970,&-17964,&-17961,&-17950,&-17947,&-17931,&-17928,&-17922,&-17759,&-17752,&-17733,&-17730,&-17721,&-17703,&-17701,&-17697,&-17692,&&
&&&&&&&&&&&&-17683,&-17676,&-17496,&-17487,&-17482,&-17468,&-17454,&-17433,&-17427,&-17417,&-17202,&-17185,&-16983,&-16970,&-16942,&-16915,&-16733,&&
&&&&&&&&&&&&-16708,&-16706,&-16689,&-16664,&-16657,&-16647,&-16474,&-16470,&-16465,&-16459,&-16452,&-16448,&-16433,&-16429,&-16427,&-16423,&-16419,&&
&&&&&&&&&&&&-16412,&-16407,&-16403,&-16401,&-16393,&-16220,&-16216,&-16212,&-16205,&-16202,&-16187,&-16180,&-16171,&-16169,&-16158,&-16155,&-15959,&&
&&&&&&&&&&&&-15958,&-15944,&-15933,&-15920,&-15915,&-15903,&-15889,&-15878,&-15707,&-15701,&-15681,&-15667,&-15661,&-15659,&-15652,&-15640,&-15631,&&
&&&&&&&&&&&&-15625,&-15454,&-15448,&-15436,&-15435,&-15419,&-15416,&-15408,&-15394,&-15385,&-15377,&-15375,&-15369,&-15363,&-15362,&-15183,&-15180,&&
&&&&&&&&&&&&-15165,&-15158,&-15153,&-15150,&-15149,&-15144,&-15143,&-15141,&-15140,&-15139,&-15128,&-15121,&-15119,&-15117,&-15110,&-15109,&-14941,&&
&&&&&&&&&&&&-14937,&-14933,&-14930,&-14929,&-14928,&-14926,&-14922,&-14921,&-14914,&-14908,&-14902,&-14894,&-14889,&-14882,&-14873,&-14871,&-14857,&&
&&&&&&&&&&&&-14678,&-14674,&-14670,&-14668,&-14663,&-14654,&-14645,&-14630,&-14594,&-14429,&-14407,&-14399,&-14384,&-14379,&-14368,&-14355,&-14353,&&
&&&&&&&&&&&&-14345,&-14170,&-14159,&-14151,&-14149,&-14145,&-14140,&-14137,&-14135,&-14125,&-14123,&-14122,&-14112,&-14109,&-14099,&-14097,&-14094,&&
&&&&&&&&&&&&-14092,&-14090,&-14087,&-14083,&-13917,&-13914,&-13910,&-13907,&-13906,&-13905,&-13896,&-13894,&-13878,&-13870,&-13859,&-13847,&-13831,&&
&&&&&&&&&&&&-13658,&-13611,&-13601,&-13406,&-13404,&-13400,&-13398,&-13395,&-13391,&-13387,&-13383,&-13367,&-13359,&-13356,&-13343,&-13340,&-13329,&&
&&&&&&&&&&&&-13326,&-13318,&-13147,&-13138,&-13120,&-13107,&-13096,&-13095,&-13091,&-13076,&-13068,&-13063,&-13060,&-12888,&-12875,&-12871,&-12860,&&
&&&&&&&&&&&&-12858,&-12852,&-12849,&-12838,&-12831,&-12829,&-12812,&-12802,&-12607,&-12597,&-12594,&-12585,&-12556,&-12359,&-12346,&-12320,&-12300,&&
&&&&&&&&&&&&-12120,&-12099,&-12089,&-12074,&-12067,&-12058,&-12039,&-11867,&-11861,&-11847,&-11831,&-11798,&-11781,&-11604,&-11589,&-11536,&-11358,&&
&&&&&&&&&&&&-11340,&-11339,&-11324,&-11303,&-11097,&-11077,&-11067,&-11055,&-11052,&-11045,&-11041,&-11038,&-11024,&-11020,&-11019,&-11018,&-11014,&&
&&&&&&&&&&&&-10838,&-10832,&-10815,&-10800,&-10790,&-10780,&-10764,&-10587,&-10544,&-10533,&-10519,&-10331,&-10329,&-10328,&-10322,&-10315,&-10309,&&
&&&&&&&&&&&&-10307,&-10296,&-10281,&-10274,&-10270,&-10262,&-10260,&-10256,&-10254};&&
&&&&public&static&String[]&pystr&=&new&String[]&{"a",&"ai",&"an",&"ang",&"ao",&"ba",&"bai",&"ban",&"bang",&"bao",&"bei",&"ben",&"beng",&"bi",&"bian",&&
&&&&&&&&&&&&"biao",&"bie",&"bin",&"bing",&"bo",&"bu",&"ca",&"cai",&"can",&"cang",&"cao",&"ce",&"ceng",&"cha",&"chai",&"chan",&"chang",&"chao",&"che",&&
&&&&&&&&&&&&"chen",&"cheng",&"chi",&"chong",&"chou",&"chu",&"chuai",&"chuan",&"chuang",&"chui",&"chun",&"chuo",&"ci",&"cong",&"cou",&"cu",&"cuan",&&
&&&&&&&&&&&&"cui",&"cun",&"cuo",&"da",&"dai",&"dan",&"dang",&"dao",&"de",&"deng",&"di",&"dian",&"diao",&"die",&"ding",&"diu",&"dong",&"dou",&"du",&&
&&&&&&&&&&&&"duan",&"dui",&"dun",&"duo",&"e",&"en",&"er",&"fa",&"fan",&"fang",&"fei",&"fen",&"feng",&"fo",&"fou",&"fu",&"ga",&"gai",&"gan",&"gang",&&
&&&&&&&&&&&&"gao",&"ge",&"gei",&"gen",&"geng",&"gong",&"gou",&"gu",&"gua",&"guai",&"guan",&"guang",&"gui",&"gun",&"guo",&"ha",&"hai",&"han",&"hang",&&
&&&&&&&&&&&&"hao",&"he",&"hei",&"hen",&"heng",&"hong",&"hou",&"hu",&"hua",&"huai",&"huan",&"huang",&"hui",&"hun",&"huo",&"ji",&"jia",&"jian",&&
&&&&&&&&&&&&"jiang",&"jiao",&"jie",&"jin",&"jing",&"jiong",&"jiu",&"ju",&"juan",&"jue",&"jun",&"ka",&"kai",&"kan",&"kang",&"kao",&"ke",&"ken",&&
&&&&&&&&&&&&"keng",&"kong",&"kou",&"ku",&"kua",&"kuai",&"kuan",&"kuang",&"kui",&"kun",&"kuo",&"la",&"lai",&"lan",&"lang",&"lao",&"le",&"lei",&"leng",&&
&&&&&&&&&&&&"li",&"lia",&"lian",&"liang",&"liao",&"lie",&"lin",&"ling",&"liu",&"long",&"lou",&"lu",&"lv",&"luan",&"lue",&"lun",&"luo",&"ma",&"mai",&&
&&&&&&&&&&&&"man",&"mang",&"mao",&"me",&"mei",&"men",&"meng",&"mi",&"mian",&"miao",&"mie",&"min",&"ming",&"miu",&"mo",&"mou",&"mu",&"na",&"nai",&&
&&&&&&&&&&&&"nan",&"nang",&"nao",&"ne",&"nei",&"nen",&"neng",&"ni",&"nian",&"niang",&"niao",&"nie",&"nin",&"ning",&"niu",&"nong",&"nu",&"nv",&"nuan",&&
&&&&&&&&&&&&"nue",&"nuo",&"o",&"ou",&"pa",&"pai",&"pan",&"pang",&"pao",&"pei",&"pen",&"peng",&"pi",&"pian",&"piao",&"pie",&"pin",&"ping",&"po",&"pu",&&
&&&&&&&&&&&&"qi",&"qia",&"qian",&"qiang",&"qiao",&"qie",&"qin",&"qing",&"qiong",&"qiu",&"qu",&"quan",&"que",&"qun",&"ran",&"rang",&"rao",&"re",&&
&&&&&&&&&&&&"ren",&"reng",&"ri",&"rong",&"rou",&"ru",&"ruan",&"rui",&"run",&"ruo",&"sa",&"sai",&"san",&"sang",&"sao",&"se",&"sen",&"seng",&"sha",&&
&&&&&&&&&&&&"shai",&"shan",&"shang",&"shao",&"she",&"shen",&"sheng",&"shi",&"shou",&"shu",&"shua",&"shuai",&"shuan",&"shuang",&"shui",&"shun",&&
&&&&&&&&&&&&"shuo",&"si",&"song",&"sou",&"su",&"suan",&"sui",&"sun",&"suo",&"ta",&"tai",&"tan",&"tang",&"tao",&"te",&"teng",&"ti",&"tian",&"tiao",&&
&&&&&&&&&&&&"tie",&"ting",&"tong",&"tou",&"tu",&"tuan",&"tui",&"tun",&"tuo",&"wa",&"wai",&"wan",&"wang",&"wei",&"wen",&"weng",&"wo",&"wu",&"xi",&&
&&&&&&&&&&&&"xia",&"xian",&"xiang",&"xiao",&"xie",&"xin",&"xing",&"xiong",&"xiu",&"xu",&"xuan",&"xue",&"xun",&"ya",&"yan",&"yang",&"yao",&"ye",&"yi",&&
&&&&&&&&&&&&"yin",&"ying",&"yo",&"yong",&"you",&"yu",&"yuan",&"yue",&"yun",&"za",&"zai",&"zan",&"zang",&"zao",&"ze",&"zei",&"zen",&"zeng",&"zha",&&
&&&&&&&&&&&&"zhai",&"zhan",&"zhang",&"zhao",&"zhe",&"zhen",&"zheng",&"zhi",&"zhong",&"zhou",&"zhu",&"zhua",&"zhuai",&"zhuan",&"zhuang",&"zhui",&&
&&&&&&&&&&&&"zhun",&"zhuo",&"zi",&"zong",&"zou",&"zu",&"zuan",&"zui",&"zun",&"zuo"};&&
&&&&private&StringBuilder&&&
&&&&private&String&&&
&&&&private&static&CharacterParser&characterParser&=&new&CharacterParser();&&
&&&&public&static&CharacterParser&getInstance()&{&&
&&&&&&&&return&characterP&&
&&&&public&String&getResource()&{&&
&&&&&&&&return&&&
&&&&public&void&setResource(String&resource)&{&&
&&&&&&&&this.resource&=&&&
&&&&private&int&getChsAscii(String&chs)&{&&
&&&&&&&&int&asc&=&0;&&
&&&&&&&&try&{&&
&&&&&&&&&&&&byte[]&bytes&=&chs.getBytes("gb2312");&&
&&&&&&&&&&&&if&(bytes&==&null&||&bytes.length&&&2&||&bytes.length&&=&0)&{&&
&&&&&&&&&&&&&&&&throw&new&RuntimeException("illegal&resource&string");&&
&&&&&&&&&&&&}&&
&&&&&&&&&&&&if&(bytes.length&==&1)&{&&
&&&&&&&&&&&&&&&&asc&=&bytes[0];&&
&&&&&&&&&&&&}&&
&&&&&&&&&&&&if&(bytes.length&==&2)&{&&
&&&&&&&&&&&&&&&&int&hightByte&=&256&+&bytes[0];&&
&&&&&&&&&&&&&&&&int&lowByte&=&256&+&bytes[1];&&
&&&&&&&&&&&&&&&&asc&=&(256&*&hightByte&+&lowByte)&-&256&*&256;&&
&&&&&&&&&&&&}&&
&&&&&&&&}&catch&(Exception&e)&{&&
&&&&&&&&&&&&System.out.println("ERROR:ChineseSpelling.class-getChsAscii(String&chs)"&+&e);&&
&&&&&&&&}&&
&&&&&&&&return&&&
&&&&public&String&convert(String&str)&{&&
&&&&&&&&String&result&=&&&
&&&&&&&&int&ascii&=&getChsAscii(str);&&
&&&&&&&&if&(ascii&&&0&&&&ascii&&&160)&{&&
&&&&&&&&&&&&result&=&String.valueOf((char)&ascii);&&
&&&&&&&&}&else&{&&
&&&&&&&&&&&&for&(int&i&=&(pyvalue.length&-&1);&i&&=&0;&i--)&{&&
&&&&&&&&&&&&&&&&if&(pyvalue[i]&&=&ascii)&{&&
&&&&&&&&&&&&&&&&&&&&result&=&pystr[i];&&
&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&}&&
&&&&&&&&&&&&}&&
&&&&&&&&}&&
&&&&&&&&return&&&
&&&&public&String&getSelling(String&chs)&{&&
&&&&&&&&String&key,&&&
&&&&&&&&buffer&=&new&StringBuilder();&&
&&&&&&&&for&(int&i&=&0;&i&&&chs.length();&i++)&{&&
&&&&&&&&&&&&key&=&chs.substring(i,&i&+&1);&&
&&&&&&&&&&&&if&(key.getBytes().length&&=&2)&{&&
&&&&&&&&&&&&&&&&value&=&(String)&convert(key);&&
&&&&&&&&&&&&&&&&if&(value&==&null)&{&&
&&&&&&&&&&&&&&&&&&&&value&=&"unknown";&&
&&&&&&&&&&&&&&&&}&&
&&&&&&&&&&&&}&else&{&&
&&&&&&&&&&&&&&&&value&=&&&
&&&&&&&&&&&&}&&
&&&&&&&&&&&&buffer.append(value);&&
&&&&&&&&}&&
&&&&&&&&return&buffer.toString();&&
&&&&public&String&getSpelling()&{&&
&&&&&&&&return&this.getSelling(this.getResource());&&
4.ClearEditText类是自定义的一个在右侧有删除图片的EditText,当然你也可以用Android原生的EditText,该类我之前有介绍,我这里就不贴上代码了
5.SortAdapter
数据的适配器类,该类需要实现SectionIndexer接口,该接口是用来控制ListView分组的,该接口有三个方法
getSectionForPosition(int position),getPositionForSection(int
section),getSections(),我们只需要自行实现前面两个方法
getSectionForPosition(int position)是根据ListView的position来获取该位置上面的name的首字母char的ascii值,例如: 如果该position上面的name是阿妹,首字母就是A,那么此方法返回的就是'A'字母的ascii值,也就是65, 'B'是66,依次类推
getPositionForSection(int section)就是根据首字母的ascii值来获取在该ListView中第一次出现该首字母的位置,例如:从上面的效果图1中,如果section是66 ,也就是&B&的ascii值,那么该方法返回的position就是2
后就是getView()方法,首先我们根据ListView的position调用getSectionForPosition(int
position)来获取该位置上面name的首字母的ascii值,然后根据这个ascii值调用getPositionForSection(int
section)来获取第一次出现该首字母的position,如果ListView的position
等于&根据这个ascii值调用getPositionForSection(int
section)来获取第一次出现该首字母的position,则显示分类字母 否则隐藏
package&com.example.&&
import&java.util.L&&
import&android.content.C&&
import&android.view.LayoutI&&
import&android.view.V&&
import&android.view.ViewG&&
import&android.widget.BaseA&&
import&android.widget.SectionI&&
import&android.widget.TextV&&
public&class&SortAdapter&extends&BaseAdapter&implements&SectionIndexer{&&
&&&&private&List&SortModel&&list&=&&&
&&&&private&Context&mC&&
&&&&public&SortAdapter(Context&mContext,&List&SortModel&&list)&{&&
&&&&&&&&this.mContext&=&mC&&
&&&&&&&&this.list&=&&&
&&&&public&void&updateListView(List&SortModel&&list){&&
&&&&&&&&this.list&=&&&
&&&&&&&&notifyDataSetChanged();&&
&&&&public&int&getCount()&{&&
&&&&&&&&return&this.list.size();&&
&&&&public&Object&getItem(int&position)&{&&
&&&&&&&&return&list.get(position);&&
&&&&public&long&getItemId(int&position)&{&&
&&&&&&&&return&&&
&&&&public&View&getView(final&int&position,&View&view,&ViewGroup&arg2)&{&&
&&&&&&&&ViewHolder&viewHolder&=&&&
&&&&&&&&final&SortModel&mContent&=&list.get(position);&&
&&&&&&&&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();&&
&&&&&&&&}&&
&&&&&&&&&&
&&&&&&&&int&section&=&getSectionForPosition(position);&&
&&&&&&&&&&
&&&&&&&&if(position&==&getPositionForSection(section)){&&
&&&&&&&&&&&&viewHolder.tvLetter.setVisibility(View.VISIBLE);&&
&&&&&&&&&&&&viewHolder.tvLetter.setText(mContent.getSortLetters());&&
&&&&&&&&}else{&&
&&&&&&&&&&&&viewHolder.tvLetter.setVisibility(View.GONE);&&
&&&&&&&&}&&
&&&&&&&&viewHolder.tvTitle.setText(this.list.get(position).getName());&&
&&&&&&&&&&
&&&&&&&&return&&&
&&&&final&static&class&ViewHolder&{&&
&&&&&&&&TextView&tvL&&
&&&&&&&&TextView&tvT&&
&&&&public&int&getSectionForPosition(int&position)&{&&
&&&&&&&&return&list.get(position).getSortLetters().charAt(0);&&
&&&&public&int&getPositionForSection(int&section)&{&&
&&&&&&&&for&(int&i&=&0;&i&&&getCount();&i++)&{&&
&&&&&&&&&&&&String&sortStr&=&list.get(i).getSortLetters();&&
&&&&&&&&&&&&char&firstChar&=&sortStr.toUpperCase().charAt(0);&&
&&&&&&&&&&&&if&(firstChar&==&section)&{&&
&&&&&&&&&&&&&&&&return&i;&&
&&&&&&&&&&&&}&&
&&&&&&&&}&&
&&&&&&&&&&
&&&&&&&&return&-1;&&
&&&&@Override&&
&&&&public&Object[]&getSections()&{&&
&&&&&&&&return&&&
6.MainActivity&这
里面的代码比较简单,我们对ClearEditText设置addTextChangedListener监听,当输入框内容发生变化根据里面的值过滤
ListView,里面的值为空显示原来的列表,里面对列表数据进行排序用到PinyinComparator接口,该接口主要是用来比较对象的
package&com.example.&&
import&java.util.ArrayL&&
import&java.util.C&&
import&java.util.L&&
import&android.app.A&&
import&android.os.B&&
import&android.text.E&&
import&android.text.TextU&&
import&android.text.TextW&&
import&android.view.V&&
import&android.widget.AdapterV&&
import&android.widget.AdapterView.OnItemClickL&&
import&android.widget.ListV&&
import&android.widget.TextV&&
import&android.widget.T&&
import&com.example.sortlistview.SideBar.OnTouchingLetterChangedL&&
public&class&MainActivity&extends&Activity&{&&
&&&&private&ListView&sortListV&&
&&&&private&SideBar&sideB&&
&&&&private&TextView&&&
&&&&private&SortAdapter&&&
&&&&private&ClearEditText&mClearEditT&&
&&&&private&CharacterParser&characterP&&
&&&&private&List&SortModel&&SourceDateL&&
&&&&private&PinyinComparator&pinyinC&&
&&&&@Override&&
&&&&protected&void&onCreate(Bundle&savedInstanceState)&{&&
&&&&&&&&super.onCreate(savedInstanceState);&&
&&&&&&&&setContentView(R.layout.activity_main);&&
&&&&&&&&initViews();&&
&&&&private&void&initViews()&{&&
&&&&&&&&characterParser&=&CharacterParser.getInstance();&&
&&&&&&&&&&
&&&&&&&&pinyinComparator&=&new&PinyinComparator();&&
&&&&&&&&&&
&&&&&&&&sideBar&=&(SideBar)&findViewById(R.id.sidrbar);&&
&&&&&&&&dialog&=&(TextView)&findViewById(R.id.dialog);&&
&&&&&&&&sideBar.setTextView(dialog);&&
&&&&&&&&&&
&&&&&&&&sideBar.setOnTouchingLetterChangedListener(new&OnTouchingLetterChangedListener()&{&&
&&&&&&&&&&&&&&
&&&&&&&&&&&&@Override&&
&&&&&&&&&&&&public&void&onTouchingLetterChanged(String&s)&{&&
&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&int&position&=&adapter.getPositionForSection(s.charAt(0));&&
&&&&&&&&&&&&&&&&if(position&!=&-1){&&
&&&&&&&&&&&&&&&&&&&&sortListView.setSelection(position);&&
&&&&&&&&&&&&&&&&}&&
&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&}&&
&&&&&&&&});&&
&&&&&&&&&&
&&&&&&&&sortListView&=&(ListView)&findViewById(R.id.country_lvcountry);&&
&&&&&&&&sortListView.setOnItemClickListener(new&OnItemClickListener()&{&&
&&&&&&&&&&&&@Override&&
&&&&&&&&&&&&public&void&onItemClick(AdapterView&?&&parent,&View&view,&&
&&&&&&&&&&&&&&&&&&&&int&position,&long&id)&{&&
&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&Toast.makeText(getApplication(),&((SortModel)adapter.getItem(position)).getName(),&Toast.LENGTH_SHORT).show();&&
&&&&&&&&&&&&}&&
&&&&&&&&});&&
&&&&&&&&&&
&&&&&&&&SourceDateList&=&filledData(getResources().getStringArray(R.array.date));&&
&&&&&&&&&&
&&&&&&&&Collections.sort(SourceDateList,&pinyinComparator);&&
&&&&&&&&adapter&=&new&SortAdapter(this,&SourceDateList);&&
&&&&&&&&sortListView.setAdapter(adapter);&&
&&&&&&&&&&
&&&&&&&&&&
&&&&&&&&mClearEditText&=&(ClearEditText)&findViewById(R.id.filter_edit);&&
&&&&&&&&&&
&&&&&&&&mClearEditText.addTextChangedListener(new&TextWatcher()&{&&
&&&&&&&&&&&&&&
&&&&&&&&&&&&@Override&&
&&&&&&&&&&&&public&void&onTextChanged(CharSequence&s,&int&start,&int&before,&int&count)&{&&
&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&filterData(s.toString());&&
&&&&&&&&&&&&}&&
&&&&&&&&&&&&&&
&&&&&&&&&&&&@Override&&
&&&&&&&&&&&&public&void&beforeTextChanged(CharSequence&s,&int&start,&int&count,&&
&&&&&&&&&&&&&&&&&&&&int&after)&{&&
&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&}&&
&&&&&&&&&&&&&&
&&&&&&&&&&&&@Override&&
&&&&&&&&&&&&public&void&afterTextChanged(Editable&s)&{&&
&&&&&&&&&&&&}&&
&&&&&&&&});&&
&&&&private&List&SortModel&&filledData(String&[]&date){&&
&&&&&&&&List&SortModel&&mSortList&=&new&ArrayList&SortModel&();&&
&&&&&&&&&&
&&&&&&&&for(int&i=0;&i&date.&i++){&&
&&&&&&&&&&&&SortModel&sortModel&=&new&SortModel();&&
&&&&&&&&&&&&sortModel.setName(date[i]);&&
&&&&&&&&&&&&
&&&&&&&&&&&&String&pinyin&=&characterParser.getSelling(date[i]);&&
&&&&&&&&&&&&String&sortString&=&pinyin.substring(0,&1).toUpperCase();&&
&&&&&&&&&&&&&&
&&&&&&&&&&&&
&&&&&&&&&&&&if(sortString.matches("[A-Z]")){&&
&&&&&&&&&&&&&&&&sortModel.setSortLetters(sortString.toUpperCase());&&
&&&&&&&&&&&&}else{&&
&&&&&&&&&&&&&&&&sortModel.setSortLetters("#");&&
&&&&&&&&&&&&}&&
&&&&&&&&&&&&&&
&&&&&&&&&&&&mSortList.add(sortModel);&&
&&&&&&&&}&&
&&&&&&&&return&mSortL&&
&&&&&&&&&&
&&&&private&void&filterData(String&filterStr)&{&&
&&&&&&&&List&SortModel&&filterDateList&=&new&ArrayList&SortModel&();&&
&&&&&&&&if&(TextUtils.isEmpty(filterStr))&{&&
&&&&&&&&&&&&filterDateList&=&SourceDateL&&
&&&&&&&&}&else&{&&
&&&&&&&&&&&&filterDateList.clear();&&
&&&&&&&&&&&&for&(SortModel&sortModel&:&SourceDateList)&{&&
&&&&&&&&&&&&&&&&String&name&=&sortModel.getName();&&
&&&&&&&&&&&&&&&&if&(name.toUpperCase().indexOf(&&
&&&&&&&&&&&&&&&&&&&&&&&&filterStr.toString().toUpperCase())&!=&-1&&
&&&&&&&&&&&&&&&&&&&&&&&&||&characterParser.getSelling(name).toUpperCase()&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&.startsWith(filterStr.toString().toUpperCase()))&{&&
&&&&&&&&&&&&&&&&&&&&filterDateList.add(sortModel);&&
&&&&&&&&&&&&&&&&}&&
&&&&&&&&&&&&}&&
&&&&&&&&}&&
&&&&&&&&&&
&&&&&&&&Collections.sort(filterDateList,&pinyinComparator);&&
&&&&&&&&adapter.updateListView(filterDateList);&&
7.PinyinComparator接口用来对ListView中的数据根据A-Z进行排序,前面两个if判断主要是将不是以汉字开头的数据放在后面
package&com.example.&&
public&class&PinyinComparator&implements&Comparator&SortModel&&{&&
&&&&public&int&compare(SortModel&o1,&SortModel&o2)&{&&
&&&&&&&&if&(o2.getSortLetters().equals("#"))&{&&
&&&&&&&&&&&&return&-1;&&
&&&&&&&&}&else&if&(o1.getSortLetters().equals("#"))&{&&
&&&&&&&&&&&&return&1;&&
&&&&&&&&}&else&{&&
&&&&&&&&&&&&return&o1.getSortLetters().compareTo(o2.getSortLetters());&&
&&&&&&&&}&&
这样我们以后使用A-Z排序就没要局限性了,想加这个效果随时都行,其他的布局和图片之类的文件就不贴出来了,如果大家有兴趣的自行去下载代码吧,如果大家有什么疑问,请在下面留言,我会为大家解答的!
阅读(...) 评论()}

我要回帖

更多关于 android 横向listview 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信