创新源于模仿之四:增强的ExpandableListView

本文介绍了一种在Android中实现带有固定Group Header的ExpandableListView的方法。通过自定义GroupHeaderIndicator类,并结合OnScrollListener,可以在滚动列表时始终显示当前可见child项所属的Group标题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

继续讨论一下如何实现手机QQ里那个增强版的ExpandableListView效果,如下图:

 

 

Android缺省的ExpandableListView的group header无法固定在界面上,当向下滚动后,不能对当前显示的那些child 指示出它们归属于哪个group,而这一点,在iphone中的tableview就做的非常好。

 

所以,我们来做一个固定在列表上方的提示框,显示当前显示的展开的那些child归属的group信息。

 

思路:
1. 先弄一个TextView作为指示器放在ListView的上面,跟列表上缘平齐。
2. 处理列表的上下滚动回调:

  1. if(第一行是group){  
  2.  if(第二行也是group) 隐藏指示器;  
  3.  else if(第二行是第一行展开的第一个child) 显示指示器;  
  4. }  
  5. else {  
  6.  if(第二行是group 且第一行显示不完整时) 隐藏指示器;  
  7. }  

 

 

就这样了,是吧?

 

[java]  view plain copy
  1. public class GroupHeaderIndicator extends TextView   
  2.  implements OnScrollListener {  
  3.   
  4.   
  5. @Override  
  6.  public void onScroll(AbsListView view, int firstVisibleItem,  
  7.    int visibleItemCount, int totalItemCount) {  
  8.   // TODO Auto-generated method stub  
  9.     
  10.   ExpandableListView listView = (ExpandableListView)view;  
  11.   //当前第一行归属的组ID  
  12.   int gid = ExpandableListView.getPackedPositionGroup(listView.getExpandableListPosition(firstVisibleItem));  
  13.   //当前第一行的子ID  
  14.   int cid = ExpandableListView.getPackedPositionChild(listView.getExpandableListPosition(firstVisibleItem));  
  15.   //当前第二行的子ID  
  16.   int nid = ExpandableListView.getPackedPositionChild(listView.getExpandableListPosition(firstVisibleItem+1));  
  17.     
  18.   BuddiesListAdapter adapter=(BuddiesListAdapter)listView.getExpandableListAdapter();  
  19.     
  20.   String gtitle=(gid>-1)?adapter.getGroup(gid).toString():"";  
  21.   
  22.   //如果第一行和第二行都是组header,不需要显示  
  23.   if(cid==-1 && nid==-1){  
  24.    this.setVisibility(View.GONE);  
  25.   }  
  26.   else {  
  27.    //当前真的是一个child,而且下一行是group  
  28.    if(nid==-1 && cid>=0){  
  29.     this.setVisibility(View.GONE);  
  30.     return;   
  31.    }  
  32.    this.setVisibility(View.VISIBLE);  
  33.    this.setText(gtitle);  
  34.    this.postInvalidate();  
  35.   }  
  36.  }  
  37.   
  38. }  


 

一切就这么简单,然后看看它放的位置是:

 

[plain]  view plain copy
  1. <FrameLayout  
  2.   xmlns:android="http://schemas.android.com/apk/res/android"  
  3.   android:layout_width="fill_parent"  
  4.   android:layout_height="fill_parent"  
  5.    
  6.   android:padding="8.0dip"   
  7.   android:layout_weight="1.0">  
  8.   <ExpandableListView   
  9.    android:id="@id/buddies_list"  
  10.    android:scrollbars="vertical"  
  11.    android:layout_width="fill_parent"   
  12.    android:layout_height="fill_parent"  
  13.    android:layout_marginLeft="0.0dip"   
  14.    android:drawSelectorOnTop="false"  
  15.    android:scrollingCache="true"   
  16.    android:layout_weight="1.0"  
  17.    android:fastScrollEnabled="false"   
  18.    android:footerDividersEnabled="true"  
  19.    android:cacheColorHint="#00000000"  
  20.    android:groupIndicator="@drawable/expander_group"  
  21.    style="@style/Widget.ListViewGreen" mce_style="@style/Widget.ListViewGreen"  
  22.     />  
  23.    
  24.  <cn.sharetop.demo.ui.GroupHeaderIndicator  
  25.   android:id="@id/buddies_group_indicator"  
  26.      android:textColor="#333333"   
  27.   android:gravity="left|center"   
  28.   android:paddingLeft="32.0dip"  
  29.   android:layout_width="fill_parent"  
  30.   android:layout_height="44.0dip"  
  31.   android:background="@drawable/expand_group_bar"  
  32.      />     
  33.      
  34. </FrameLayout>  


 

[plain]  view plain copy
  1. <FrameLayout  
  2.   xmlns:android="http://schemas.android.com/apk/res/android"  
  3.   android:layout_width="fill_parent"  
  4.   android:layout_height="fill_parent"  
  5.    
  6.   android:padding="8.0dip"   
  7.   android:layout_weight="1.0">  
  8.   <ExpandableListView   
  9.    android:id="@id/buddies_list"  
  10.    android:scrollbars="vertical"  
  11.    android:layout_width="fill_parent"   
  12.    android:layout_height="fill_parent"  
  13.    android:layout_marginLeft="0.0dip"   
  14.    android:drawSelectorOnTop="false"  
  15.    android:scrollingCache="true"   
  16.    android:layout_weight="1.0"  
  17.    android:fastScrollEnabled="false"   
  18.    android:footerDividersEnabled="true"  
  19.    android:cacheColorHint="#00000000"  
  20.    android:groupIndicator="@drawable/expander_group"  
  21.    style="@style/Widget.ListViewGreen" mce_style="@style/Widget.ListViewGreen"  
  22.     />  
  23.    
  24.  <cn.sharetop.demo.ui.GroupHeaderIndicator  
  25.   android:id="@id/buddies_group_indicator"  
  26.      android:textColor="#333333"   
  27.   android:gravity="left|center"   
  28.   android:paddingLeft="32.0dip"  
  29.   android:layout_width="fill_parent"  
  30.   android:layout_height="44.0dip"  
  31.   android:background="@drawable/expand_group_bar"  
  32.      />     
  33.      
  34. </FrameLayout>  


 

我为了省事,直接从TextView中派生出这个指示器,其实你可以更复杂点,从一个ViewGroup之类的东西来做出更多的效果。

 

细心的朋友可以发现了,在QQ中,当上移列表时,有一个效果是下一个group header将指示器给推出屏幕的,图省事,我没这样做,留给兄弟你去扩展了。

 

此外,反编译QQ的代码可知,其实它的实现是自己做了一个叫 IphoneTreeView的类,继承了ExpandableListView,这样做更灵活也更好,同样,如果要实现更完美的效果,还有很多事情要做的。

 

最近想学习一下iphone的开发,有点没动力继续写这个题目了。所以,只是在这儿抛砖引玉罢了,如果你们做出了更好的效果,请拿出来共享。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值