閱讀147 返回首頁    go 阿裏雲 go 技術社區[雲棲]


創新源於模仿之四:增強的ExpandableListView

 

繼續討論一下如何實現手機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. }  

 

 

就這樣了,是吧?

 

public class GroupHeaderIndicator extends TextView 
 implements OnScrollListener {


@Override
 public void onScroll(AbsListView view, int firstVisibleItem,
   int visibleItemCount, int totalItemCount) {
  // TODO Auto-generated method stub
  
  ExpandableListView listView = (ExpandableListView)view;
  //當前第一行歸屬的組ID
  int gid = ExpandableListView.getPackedPositionGroup(listView.getExpandableListPosition(firstVisibleItem));
  //當前第一行的子ID
  int cid = ExpandableListView.getPackedPositionChild(listView.getExpandableListPosition(firstVisibleItem));
  //當前第二行的子ID
  int nid = ExpandableListView.getPackedPositionChild(listView.getExpandableListPosition(firstVisibleItem+1));
  
  BuddiesListAdapter adapter=(BuddiesListAdapter)listView.getExpandableListAdapter();
  
  String gtitle=(gid>-1)?adapter.getGroup(gid).toString():"";

  //如果第一行和第二行都是組header,不需要顯示
  if(cid==-1 && nid==-1){
   this.setVisibility(View.GONE);
  }
  else {
   //當前真的是一個child,而且下一行是group
   if(nid==-1 && cid>=0){
    this.setVisibility(View.GONE);
    return; 
   }
   this.setVisibility(View.VISIBLE);
   this.setText(gtitle);
   this.postInvalidate();
  }
 }

}


 

一切就這麼簡單,然後看看它放的位置是:

 

<FrameLayout
  xmlns:andro
  android:layout_width="fill_parent"
  android:layout_height="fill_parent"
 
  android:padding="8.0dip" 
  android:layout_weight="1.0">
  <ExpandableListView 
   android:
   android:scrollbars="vertical"
   android:layout_width="fill_parent" 
   android:layout_height="fill_parent"
   android:layout_marginLeft="0.0dip" 
   android:drawSelectorOnTop="false"
   android:scrollingCache="true" 
   android:layout_weight="1.0"
   android:fastScrollEnabled="false" 
   android:footerDividersEnabled="true"
   android:cacheColorHint="#00000000"
   android:groupIndicator="@drawable/expander_group"
    mce_
    />
 
 <cn.sharetop.demo.ui.GroupHeaderIndicator
  android:
     android:textColor="#333333" 
  android:gravity="left|center" 
  android:paddingLeft="32.0dip"
  android:layout_width="fill_parent"
  android:layout_height="44.0dip"
  android:background="@drawable/expand_group_bar"
     />   
   
</FrameLayout>


 

<FrameLayout
  xmlns:andro
  android:layout_width="fill_parent"
  android:layout_height="fill_parent"
 
  android:padding="8.0dip" 
  android:layout_weight="1.0">
  <ExpandableListView 
   android:
   android:scrollbars="vertical"
   android:layout_width="fill_parent" 
   android:layout_height="fill_parent"
   android:layout_marginLeft="0.0dip" 
   android:drawSelectorOnTop="false"
   android:scrollingCache="true" 
   android:layout_weight="1.0"
   android:fastScrollEnabled="false" 
   android:footerDividersEnabled="true"
   android:cacheColorHint="#00000000"
   android:groupIndicator="@drawable/expander_group"
    mce_
    />
 
 <cn.sharetop.demo.ui.GroupHeaderIndicator
  android:
     android:textColor="#333333" 
  android:gravity="left|center" 
  android:paddingLeft="32.0dip"
  android:layout_width="fill_parent"
  android:layout_height="44.0dip"
  android:background="@drawable/expand_group_bar"
     />   
   
</FrameLayout>


 

我為了省事,直接從TextView中派生出這個指示器,其實你可以更複雜點,從一個ViewGroup之類的東西來做出更多的效果。

 

細心的朋友可以發現了,在QQ中,當上移列表時,有一個效果是下一個group header將指示器給推出屏幕的,圖省事,我沒這樣做,留給兄弟你去擴展了。

 

此外,反編譯QQ的代碼可知,其實它的實現是自己做了一個叫 IphoneTreeView的類,繼承了ExpandableListView,這樣做更靈活也更好,同樣,如果要實現更完美的效果,還有很多事情要做的。

 

最近想學習一下iphone的開發,有點沒動力繼續寫這個題目了。所以,隻是在這兒拋磚引玉罷了,如果你們做出了更好的效果,請拿出來共享。

 

先謝謝了!

最後更新:2017-04-02 06:51:59

  上一篇:go Android-非常棒的HTTP通訊總結
  下一篇:go 創新源於模仿之一:TabActivity的美化