在上一篇文章中,我和大家一起实现了类似于Android系统联系人的分组导航和挤压动画功能,不过既然文章名叫做《Android系统联系人全特效实现》,那么没有快速滚动功能显然是称不上"全"的。因此本篇文章我将带领大家在上篇文章的代码基础上改进,加入快速滚动功能。
如果还没有看过我上一篇文章,请抓紧去阅读一下Android系统联系人全特效实现(上),分组导航和挤压动画。
其实ListView本身是有一个快速滚动属性的,可以通过在XML中设置android:fastScrollEnabled="true"来启用。包括以前老版本的Android联系人中都是使用这种方式来进行快速滚动的。效果如下图所示:
不过这种快速滚动方式比较丑陋,到后来很多手机厂商在定制自己ROM的时候都将默认快速滚动改成了类似iPhone上A-Z字母表快速滚动的方式。这里我们怎么能落后于时代的潮流呢!我们的快速滚动也要使用A-Z字母表的方式!
下面就来开始实现,首先打开上次的ContactsDemo工程,修改activity_main.xml布局文件。由于我们要在界面上加入字母表,因此我们需要一个Button,将这个Button的背景设为一张A-Z排序的图片,然后居右对齐。另外还需要一个TextView,用于在弹出式分组布局上显示当前的分组,默认是gone掉的,只有手指在字母表上滑动时才让它显示出来。修改后的布局文件代码如下:
-
<RelativeLayoutxmlns:android="http://schemas.android.com/apk/res/android"
-
xmlns:tools="http://schemas.android.com/tools"
-
android:layout_width="match_parent"
-
android:layout_height="match_parent"
-
android:orientation="vertical">
-
-
<ListView
-
android:id="@+id/contacts_list_view"
-
android:layout_width="fill_parent"
-
android:layout_height="wrap_content"
-
android:layout_alignParentTop="true"
-
android:scrollbars="none"
-
android:fadingEdge="none">
-
</ListView>
-
-
<LinearLayout
-
android:id="@+id/title_layout"
-
android:layout_width="fill_parent"
-
android:layout_height="18dip"
-
android:layout_alignParentTop="true"
-
android:background="#303030">
-
-
<TextView
-
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"/>
-
</LinearLayout>
-
-
<Button
-
android:id="@+id/alphabetButton"
-
android:layout_width="wrap_content"
-
android:layout_height="fill_parent"
-
android:layout_alignParentRight="true"
-
android:background="@drawable/a_z"
-
/>
-
-
<RelativeLayout
-
android:id="@+id/section_toast_layout"
-
android:layout_width="70dip"
-
android:layout_height="70dip"
-
android:layout_centerInParent="true"
-
android:background="@drawable/section_toast"
-
android:visibility="gone"
-
>
-
<TextView
-
android:id="@+id/section_toast_text"
-
android:layout_width="wrap_content"
-
android:layout_height="wrap_content"
-
android:layout_centerInParent="true"
-
android:textColor="#fff"
-
android:textSize="30sp"
-
/>
-
</RelativeLayout>
-
-
</RelativeLayout>
然后打开MainActivity进行修改,毫无疑问,我们需要对字母表按钮的touch事件进行监听,于是在MainActivity中新增如下代码:
-
privatevoidsetAlpabetListener(){
-
alphabetButton.setOnTouchListener(newOnTouchListener(){
-
@Override
-
publicbooleanonTouch(Viewv,MotionEventevent){
-
floatalphabetHeight=alphabetButton.getHeight();
-
floaty=event.getY();
-
intsectionPosition=(int)((y/alphabetHeight)/(1f/27f));
-
if(sectionPosition<0){
-
sectionPosition=0;
-
}elseif(sectionPosition>26){
-
sectionPosition=26;
-
}
-
StringsectionLetter=String.valueOf(alphabet.charAt(sectionPosition));
-
intposition=indexer.getPositionForSection(sectionPosition);
-
switch(event.getAction()){
-
caseMotionEvent.ACTION_DOWN:
-
alphabetButton.setBackgroundResource(R.drawable.a_z_click);
-
sectionToastLayout.setVisibility(View.VISIBLE);
-
sectionToastText.setText(sectionLetter);
-
contactsListView.setSelection(position);
-
break;
-
caseMotionEvent.ACTION_MOVE:
-
sectionToastText.setText(sectionLetter);
-
contactsListView.setSelection(position);
-
break;
-
default:
-
alphabetButton.setBackgroundResource(R.drawable.a_z);
-
sectionToastLayout.setVisibility(View.GONE);
-
}
-
returntrue;
-
}
-
});
-
}
可以看到,在这个方法中我们注册了字母表按钮的onTouch事件,然后在onTouch方法里做了一些逻辑判断和处理,下面我来一一详细说明。首先通过字母表按钮的getHeight方法获取到字母表的总高度,然后用event.getY方法获取到目前手指在字母表上的纵坐标,用纵坐标除以总高度就可以得到一个用小数表示的当前手指所在位置(0表在#端,1表示在Z端)。由于我们的字母表中一共有27个字符,再用刚刚算出的小数再除以1/27就可以得到一个0到27范围内的浮点数,之后再把这个浮点数向下取整,就可以算出我们当前按在哪个字母上了。然后再对event的action进行判断,如果是ACTION_DOWN或ACTION_MOVE,就在弹出式分组上显示当前手指所按的字母,并调用ListView的setSelection方法把列表滚动到相应的分组。如果是其它的action,就将弹出式分组布局隐藏。MainActivity的完整代码如下:
-
publicclassMainActivityextendsActivity{
-
-
-
-
-
privateLinearLayouttitleLayout;
-
-
-
-
-
privateRelativeLayoutsectionToastLayout;
-
-
-
-
-
privateButtonalphabetButton;
-
-
-
-
-
privateTextViewtitle;
-
-
-
-
-
privateTextViewsectionToastText;
-
-
-
-
-
privateListViewcontactsListView;
-
-
-
-
-
privateContactAdapteradapter;
-
-
-
-
-
privateAlphabetIndexerindexer;
-
-
-
-
-
privateList<Contact>contacts=newArrayList<Contact>();
-
-
-
-
-
privateStringalphabet="#ABCDEFGHIJKLMNOPQRSTUVWXYZ";
-
-
-
-
-
privateintlastFirstVisibleItem=-1;
-
-
@Override
-
protectedvoidonCreate(BundlesavedInstanceState){
-
super.onCreate(savedInstanceState);
-
setContentView(R.layout.activity_main);
-
adapter=newContactAdapter(this,R.layout.contact_item,contacts);
-
titleLayout=(LinearLayout)findViewById(R.id.title_layout);
-
sectionToastLayout=(RelativeLayout)findViewById(R.id.section_toast_layout);
-
title=(TextView)findViewById(R.id.title);
-
sectionToastText=(TextView)findViewById(R.id.section_toast_text);
-
alphabetButton=(Button)findViewById(R.id.alphabetButton);
-
contactsListView=(ListView)findViewById(R.id.contacts_list_view);
-
Uriuri=ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
-
Cursorcursor=getContentResolver().query(uri,
-
newString[]{"display_name","sort_key"},null,null,"sort_key");
-
if(cursor.moveToFirst()){
-
do{
-
Stringname=cursor.getString(0);
-
StringsortKey=getSortKey(cursor.getString(1));
-
Contactcontact=newContact();
-
contact.setName(name);
-
contact.setSortKey(sortKey);
-
contacts.add(contact);
-
}while(cursor.moveToNext());
-
}
-
startManagingCursor(cursor);
-
indexer=newAlphabetIndexer(cursor,1,alphabet);
-
adapter.setIndexer(indexer);
-
if(contacts.size()>0){
-
setupContactsListView();
-
setAlpabetListener();
-
}
-
}
-
-
-
-
-
privatevoidsetupContactsListView(){
-
contactsListView.setAdapter(adapter);
-
contactsListView.setOnScrollListener(newOnScrollListener(){
-
@Override
-
publicvoidonScrollStateChanged(AbsListViewview,intscrollState){
-
}
-
-
@Override
-
publicvoidonScroll(AbsListViewview,intfirstVisibleItem,intvisibleItemCount,
-
inttotalItemCount){
-
intsection=indexer.getSectionForPosition(firstVisibleItem);
-
intnextSecPosition=indexer.getPositionForSection(section+1);
-
if(firstVisibleItem!=lastFirstVisibleItem){
-
MarginLayoutParamsparams=(MarginLayoutParams)titleLayout.getLayoutParams();
-
params.topMargin=0;
-
titleLayout.setLayoutParams(params);
-
title.setText(String.valueOf(alphabet.charAt(section)));
-
}
-
if(nextSecPosition==firstVisibleItem+1){
-
ViewchildView=view.getChildAt(0);
-
if(childView!=null){
-
inttitleHeight=titleLayout.getHeight();
-
intbottom=childView.getBottom();
-
MarginLayoutParamsparams=(MarginLayoutParams)titleLayout
-
.getLayoutParams();
-
if(bottom<titleHeight){
-
floatpushedDistance=bottom-titleHeight;
-
params.topMargin=(int)pushedDistance;
-
titleLayout.setLayoutParams(params);
-
}else{
-
if(params.topMargin!=0){
-
params.topMargin=0;
-
titleLayout.setLayoutParams(params);
-
}
-
}
-
}
-
}
-
lastFirstVisibleItem=firstVisibleItem;
-
}
-
});
-
-
}
-
-
-
-
-
-
privatevoidsetAlpabetListener(){
-
alphabetButton.setOnTouchListener(newOnTouchListener(){
-
@Override
-
publicbooleanonTouch(Viewv,MotionEventevent){
-
floatalphabetHeight=alphabetButton.getHeight();
-
floaty=event.getY();
-
intsectionPosition=(int)((y/alphabetHeight)/(1f/27f));
-
if(sectionPosition<0){
-
sectionPosition=0;
-
}elseif(sectionPosition>26){
-
sectionPosition=26;
-
}
-
StringsectionLetter=String.valueOf(alphabet.charAt(sectionPosition));
-
intposition=indexer.getPositionForSection(sectionPosition);
-
switch(event.getAction()){
-
caseMotionEvent.ACTION_DOWN:
-
alphabetButton.setBackgroundResource(R.drawable.a_z_click);
-
sectionToastLayout.setVisibility(View.VISIBLE);
-
sectionToastText.setText(sectionLetter);
-
contactsListView.setSelection(position);
-
break;
-
caseMotionEvent.ACTION_MOVE:
-
sectionToastText.setText(sectionLetter);
-
contactsListView.setSelection(position);
-
break;
-
default:
-
alphabetButton.setBackgroundResource(R.drawable.a_z);
-
sectionToastLayout.setVisibility(View.GONE);
-
}
-
returntrue;
-
}
-
});
-
}
-
-
-
-
-
-
-
-
-
privateStringgetSortKey(StringsortKeyString){
-
alphabetButton.getHeight();
-
Stringkey=sortKeyString.substring(0,1).toUpperCase();
-
if(key.matches("[A-Z]")){
-
returnkey;
-
}
-
return"#";
-
}
-
-
}
好了,就改动了以上两处,其它文件都保持不变,让我们来运行一下看看效果:
非常不错!当你的手指在右侧字母表上滑动时,联系人的列表也跟着相应的变动,并在屏幕中央显示一个当前的分组。
现在让我们回数一下,分组导航、挤压动画、字母表快速滚动,Android系统联系人全特效都实现了!
好了,今天的讲解到此结束,有疑问的朋友请在下面留言。
源码下载,请点击这里
分享到:
相关推荐
此为示例代码,详细讲解请参考 http://blog.csdn.net/sinyu890807/article/details/9050671
联系人分章节显示、ListView快速滑动显示联系人首字母、附带字母表快速查找的例子, 查阅网络资源,实现方式都是比较复杂,尤其有些还实现了SectionIndex接口,很多人不怎么能理解,研究后发现此种类型的例子没必要...
联系人_字母表快速滚动_分组导航_模糊查询
android 字母滚动条
应公司项目要求实现这个功能,Android仿联系人列表,实现ListView的A-Z字母排列、挤压效果。详细地址:http://www.apkdv.com/android-like-contact-list/
该Demo主要实现了读取手机中的联系人,并且以字母索引表的形式显示,类似于微信中的手机通讯一样的字母索引表。注意:此Demo是用AndroidStudio编写,请用eclipse开发的小伙伴注意了,别下下来用不了还的转,eclipse...
在APP中,只要有联系人,都肯定有通讯录页面,而且所有的通讯录以页面都很相似,一个列表,列表中的人员按字母排列,而且按字母分组显示,且右侧有快速索引。
实现Android联系人地名等索引可以通过字母快速查找
联系人分章节显示、ListView快速滑动显示联系人首字母、附带字母表快速查找的例子
实现ListView的A-Z字母排序和过滤搜索功能,是一个功能完整的demo
实现了android中Activity悬浮一个窗口并能使其字幕滚动显示
Android中ListView字母排序,实现字母挤压效果以及右侧快速选中字母,搜索关键字功能
android通讯录功能,实现了如下功能 1.检索手机存入联系人并显示 2.右侧导航条根据拼音字母检索联系人 3.通过搜索栏实时搜索联系人 4.vCard格式导出并发送分享功能 5.检测系统通讯录是否有变化,有变化在通知栏通知,并...
android实现ListView字母排序并调整字母位置
记得在我刚接触Android的时候对系统联系人中的特效很感兴趣,它会根据手机中联系人姓氏的首字母进行分组,并在界面的最顶端始终显示一个当前的分组。如下图所示: 最让我感兴趣的是,当后一个分组和前一个分组相碰时...
安卓仿通讯录及微信联系人侧边栏滑动及字母索引,自定义控件,仿手机联系人 右侧滑动快速查找菜单,列表使用recyclerView,使用第三方pinyin4j-2.5.0.jar获得对应数据的首字母索引
android快速滑动列表+首字母提示(仿通讯录,iphone)
Android 通讯录字母导航,Android之实现系统联系人软件的分组和字母表导航效果。
使用popupwindown 显示 中间字母
ListView实现A-Z字母排序和过滤搜索功能并且实现汉字转成拼音的功能,获取通讯录联系人和头像