创新源于模仿之二:美化ListView的尝试

来源:互联网 发布:nginx log 切割 编辑:程序博客网 时间:2024/05/21 10:10

今天继续,模仿MIUI做那个Contacts的ListView,如下图:

 

 

其实可以这样归纳一下我们要做的事情:

 

1. 按首字母分组,显示一个分组的标签头。

2. 在右边做一个全字母表,可以用手指上下滑动快速选择字母分组。

3. 再做一个当前选中的那个字母的显示。

 

 

先说第一件事。我们已经了解ListView/ListAdapter组合做出一个列表界面。那么,怎么在列表中显示一些不可选且模样不同的行,在SDK提供的例子其实是有相关代码可供参考的。

 

相关的代码是在ListAdapter中这两个方法:

[java] view plain copy
print?
  1. @Override  
  2. public boolean areAllItemsEnabled() {  
  3.    return false//不是所有项都可选  
  4. }  
  5. @Override  
  6. public boolean isEnabled(int position) {  
  7.    return !getItem(position).name.startsWith("@section"); //如果名字以@section开头,则该项不可选  
  8. }  
 

 

简言之,在position这个项是否可选完全可以由你来控制的。

模样的问题也容易解决,只是这样做的效率会降低:

[java] view plain copy
print?
  1. public View getView(int position, View convertView, ViewGroup parent) {  
  2. // 如果每一项都一样,就可以这样。  
  3. //   if(convertView==null){  
  4. //   convertView=mInflater.inflate(R.layout.friends_list_row, null);  
  5. //   }  
  6.   
  7. //但我们每一项的模样都可能不一样,只能这样了  
  8. FriendInfo item = (FriendInfo)getItem(position);  
  9. if(item!=null){  
  10. if(!item.name.startsWith("@section")){  
  11. convertView=mInflater.inflate(R.layout.friends_list_row, null);  
  12. //... ...  
  13. convertView.setTag(item);  
  14. }  
  15. else {  
  16. convertView=mInflater.inflate(R.layout.friends_list_section, null);  
  17. // ... ...  
  18. }  
  19. }  
  20. return convertView;  
  21. }  
 

 

可以运行看看,第一个问题解决了。

第二个问题的处理就是找一张图,放在ListView的右边即可。先看看我们的Layout文件片断:

 

注意这个QuickAlphabeticBar是我们自定义的一个View,extends ImageButton,所以你可以先试试用ImageButton放这儿也能很快看到效果。

 

[xhtml] view plain copy
print?
  1. <FrameLayout  
  2.             android:layout_width="fill_parent"   
  3.             android:layout_height="0.0dip"   
  4.             android:layout_weight="1.0">  
  5.          
  6.        <ListView   
  7. android:id="@id/friends_list"  
  8. android:scrollbars="vertical"  
  9. android:layout_width="fill_parent"   
  10. android:layout_height="fill_parent"  
  11. android:layout_marginLeft="0.0dip"   
  12. android:drawSelectorOnTop="false"  
  13. android:scrollingCache="true"   
  14. android:layout_weight="1.0"  
  15. android:fastScrollEnabled="false"   
  16. android:footerDividersEnabled="true"  
  17. android:cacheColorHint="#00000000"  
  18. style="@style/Widget.ListViewGreen"  
  19. />  
  20.    
  21. <cn.sharetop.xmessenger.ui.QuickAlphabeticBar  
  22. android:layout_gravity="top|right|center"   
  23. android:id="@id/fast_scroller"   
  24. android:background="@null"   
  25. android:layout_width="wrap_content"   
  26. android:layout_height="wrap_content"   
  27. android:layout_marginTop="10.0px"   
  28. android:scaleType="centerInside"  
  29. android:src="@drawable/contact_list_scroll_long" />  
  30.    
  31.   <TextView  
  32.   android:id="@id/fast_position"  
  33.      android:textSize="48dip"  
  34.      android:textColor="#99FFFFFF"  
  35.      android:background="@drawable/fast_scroller_overlay"  
  36.      android:layout_gravity="center_horizontal|top"  
  37.      android:padding="2dip"  
  38.      android:layout_margin="24dip"  
  39.      android:layout_width="@dimen/header_width"  
  40.      android:layout_height="@dimen/header_width"  
  41.      android:gravity="center"/>  
  42.       
  43. </FrameLayout>  
 

 

很好,这个字母表有了,因为我们需要对手指在上面滑动时的事件进行处理,所以我们自定义它,无非就是要处理这个onTouchEvent(MotionEvent event) 事件罢了,怎么处理?大家应该都想到了,就是根据手指所在位置算一下是哪个字母。

 

所以呢,我们先处理一下那个ListAdapter,让它implements SectionIndexer。

 

[java] view plain copy
print?
  1. public class FriendsListAdapter extends ArrayAdapter<FriendInfo> implements SectionIndexer{  
  2. private Context mContext;  
  3. private LayoutInflater mInflater;  
  4. private HashMap<String, Integer> alphaIndexer;   
  5. private String[] sections = new String[0];   
  6. public FriendsListAdapter(Context context, int textViewResourceId,  
  7. List<BuddyInfo> objects) {  
  8. super(context, textViewResourceId, objects);  
  9. mContext=context;  
  10. mInflater=LayoutInflater.from(mContext);  
  11. initSections(objects);  
  12. }  
  13. //......  
  14. @Override  
  15. public int getPositionForSection(int section)   {   
  16.           String letter = sections[section];   
  17.           return alphaIndexer.get(letter);   
  18.     }   
  19.    
  20. @Override  
  21. public int getSectionForPosition(int position)  {   
  22.         int prevIndex = 0;   
  23.         for(int i = 0; i < sections.length; i++)         {   
  24.             if(getPositionForSection(i) > position && prevIndex <= position) {   
  25.                 prevIndex = i;   
  26.                 break;   
  27.             }   
  28.             prevIndex = i;   
  29.         }   
  30.         return prevIndex;   
  31.     }   
  32. @Override  
  33. public Object[] getSections() {  
  34. return sections;   
  35. }  
  36. private void initSections(List<BuddyInfo> items){  
  37. alphaIndexer = new HashMap<String, Integer>();   
  38.         for(int i = items.size() - 1; i >= 0; i--) {   
  39.             BuddyInfo element = items.get(i);   
  40.             String firstChar = element.sortKey;//.substring(0, 1).toUpperCase();   
  41.             if(firstChar.charAt(0) > 'Z' || firstChar.charAt(0) < 'A')   
  42.                 firstChar = "#";   
  43.             alphaIndexer.put(firstChar, i);   
  44.         }   
  45.         Set<String> keys = alphaIndexer.keySet();   
  46.         Iterator<String> it = keys.iterator();   
  47.         ArrayList<String> keyList = new ArrayList<String>();   
  48.         while(it.hasNext())   
  49.             keyList.add(it.next());   
  50.         Collections.sort(keyList);   
  51.         sections = new String[keyList.size()];   
  52.         keyList.toArray(sections);   
  53. }  
  54. }  
 

 

然后,在QuickAlphabeticBar里的onTouchEvent里,我们可以快速定位到相应的段上:

 

[java] view plain copy
print?
  1. @Override  
  2. public boolean onTouchEvent(MotionEvent event) {  
  3. int act=event.getAction();  
  4. //......  
  5. float y = event.getY();  
  6. //算手指位置,找到对应的段,让mList移动段开头的位置上  
  7. if(mListAdapter!=null){  
  8. int x=getAlphabeticPostion(y);  
  9. if(x<0)x=0;  
  10. if(x>=mSections.length) x=mSections.length-1;  
  11. int pos=((SectionIndexer)mListAdapter).getPositionForSection(x);  
  12. this.mList.setSelectionFromTop(pos, 0);  
  13. }  
  14. else{  
  15. this.mList.setSelectionFromTop(getAlphabeticPostion(y),0);  
  16. }  
  17. return super.onTouchEvent(event);  
  18. }  
 

 

OK了,现在我们已经解决两个问题了,但是如何显示一个小的浮动窗口提示当前选中的段的首字母呢,也不复杂,大家注意到文章开头那个Layout中的ID为fast_position的TextView了吧?就是它了。

 

[java] view plain copy
print?
  1. public class QuickAlphabeticBar extends ImageButton implements OnScrollListener {  
  2. //... ...  
  3. public void init(Context ctx){  
  4. mDialogText=(TextView)((FriendsActivity)ctx).findViewById(R.id.fast_position);  
  5. mDialogText.setVisibility(View.INVISIBLE);  
  6.          
  7. mReady = true;  
  8. //... ...         
  9. }  
  10. //... ...  
  11. @Override  
  12. public void onScroll(AbsListView view, int firstVisibleItem,int visibleItemCount, int totalItemCount) {  
  13. if (mReady) {  
  14.           
  15.             if(mListAdapter!=null && mListAdapter.getCount()>0){  
  16.              BuddyInfo item = (BuddyInfo)mListAdapter.getItem(firstVisibleItem);  
  17.          
  18.            char firstLetter = (item.sortKey!=null && item.sortKey.trim().length()>0)?item.sortKey.toUpperCase().charAt(0):' ';  
  19.              
  20.           
  21.            if (!mShowing && firstLetter != mPrevLetter) {  
  22.                mShowing = true;  
  23.                mDialogText.setVisibility(View.VISIBLE);  
  24.                 
  25.            }  
  26.            mDialogText.setText(((Character)firstLetter).toString());  
  27.            mHandler.removeCallbacks(mRemoveWindow);  
  28.            mHandler.postDelayed(mRemoveWindow, 1000);  
  29.            mPrevLetter = firstLetter;  
  30.             }  
  31.         }  
  32. }  
  33. //... ...  
  34. }  
 

 

这段代码就是ListView滚动时,让mDialogText显示出来,并且设置它的内容为首字母即可。关键是那个mHandler,即1秒后要记得让它隐藏起来。

 

 

就是这么多事情了,大家可以试试。


http://blog.csdn.net/sharetop/article/details/6246629

阅读全文
0 0
原创粉丝点击