Android之帶group指示器的ExpandableListView(自寫)
更新時(shí)間:2013年06月14日 15:03:17 作者:
Android缺省的ExpandableListView的group header無(wú)法固定在界面上,在網(wǎng)上搜索了好多都不盡人意,于是乎在別人的基礎(chǔ)上改進(jìn)了一點(diǎn)點(diǎn),原理都差不多
我們都知道Android缺省的ExpandableListView的group header無(wú)法固定在界面上,當(dāng)向下滾動(dòng)后,不能對(duì)當(dāng)前顯示的那些child 指示出它們歸屬于哪個(gè)group,在網(wǎng)上搜了很多關(guān)于仿手機(jī)QQ好友分組效果的ExpandableListView,發(fā)現(xiàn)都不盡如意,于是乎在別人的基礎(chǔ)上改進(jìn)了一點(diǎn)點(diǎn),其實(shí)原理還是差不多的,只是增加了往上擠出去的動(dòng)畫效果,而且更加簡(jiǎn)單,只不過還是沒有完全到達(dá)跟QQ一樣的效果,希望有高手能實(shí)現(xiàn)更加逼真的效果,下面我們先看看效果圖:
我這里沒有把ExpandableListView獨(dú)立出來(lái)形成一個(gè)新的控件,跟網(wǎng)上很多朋友一樣,監(jiān)聽OnScrollListener事件,當(dāng)group不是在第一個(gè)位置時(shí),就把我們頭部的那個(gè)indicator顯示出來(lái),并且讓它的view跟當(dāng)前child所在group的view一樣的,然后再增加一個(gè)點(diǎn)擊關(guān)閉組的事件,即達(dá)到了簡(jiǎn)單的仿QQ好友分組的效果。
下面我們先來(lái)看看主要的布局文件:main.xml,下面那個(gè)topGroup的FrameLayout就是我們的指示器。
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ExpandableListView
android:id="@+id/expandableListView"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</ExpandableListView>
<FrameLayout
android:id="@+id/topGroup"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
</FrameLayout>
</FrameLayout>
其中最重要的是下面這部分:我們監(jiān)聽onSroll這個(gè)接口事件,當(dāng)ListView在滑動(dòng)時(shí),做相應(yīng)的處理,代碼中注釋比較多,我這里就不多作說明了。
/**
* here is very importance for indicator group
*/
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
final ExpandableListView listView = (ExpandableListView) view;
/**
* calculate point (0,0)
*/
int npos = view.pointToPosition(0, 0);// 其實(shí)就是firstVisibleItem
if (npos == AdapterView.INVALID_POSITION)// 如果第一個(gè)位置值無(wú)效
return;
long pos = listView.getExpandableListPosition(npos);
int childPos = ExpandableListView.getPackedPositionChild(pos);// 獲取第一行child的id
int groupPos = ExpandableListView.getPackedPositionGroup(pos);// 獲取第一行g(shù)roup的id
if (childPos == AdapterView.INVALID_POSITION) {// 第一行不是顯示child,就是group,此時(shí)沒必要顯示指示器
View groupView = listView.getChildAt(npos
- listView.getFirstVisiblePosition());// 第一行的view
indicatorGroupHeight = groupView.getHeight();// 獲取group的高度
indicatorGroup.setVisibility(View.GONE);// 隱藏指示器
} else {
indicatorGroup.setVisibility(View.VISIBLE);// 滾動(dòng)到第一行是child,就顯示指示器
}
// get an error data, so return now
if (indicatorGroupHeight == 0) {
return;
}
// update the data of indicator group view
if (groupPos != indicatorGroupId) {// 如果指示器顯示的不是當(dāng)前group
mAdapter.getGroupView(groupPos, listView.isGroupExpanded(groupPos),
indicatorGroup.getChildAt(0), null);// 將指示器更新為當(dāng)前group
indicatorGroupId = groupPos;
Log.e(TAG, PRE + "bind to new group,group position = " + groupPos);
// mAdapter.hideGroup(indicatorGroupId); // we set this group view
// to be hided
// 為此指示器增加點(diǎn)擊事件
indicatorGroup.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
listView.collapseGroup(indicatorGroupId);
}
});
}
if (indicatorGroupId == -1) // 如果此時(shí)grop的id無(wú)效,則返回
return;
/**
* calculate point (0,indicatorGroupHeight) 下面是形成往上推出的效果
*/
int showHeight = indicatorGroupHeight;
int nEndPos = listView.pointToPosition(0, indicatorGroupHeight);// 第二個(gè)item的位置
if (nEndPos == AdapterView.INVALID_POSITION)// 如果無(wú)效直接返回
return;
long pos2 = listView.getExpandableListPosition(nEndPos);
int groupPos2 = ExpandableListView.getPackedPositionGroup(pos2);// 獲取第二個(gè)group的id
if (groupPos2 != indicatorGroupId) {// 如果不等于指示器當(dāng)前的group
View viewNext = listView.getChildAt(nEndPos
- listView.getFirstVisiblePosition());
showHeight = viewNext.getTop();
Log.e(TAG, PRE + "update the show part height of indicator group:"
+ showHeight);
}
// update group position
MarginLayoutParams layoutParams = (MarginLayoutParams) indicatorGroup
.getLayoutParams();
layoutParams.topMargin = -(indicatorGroupHeight - showHeight);
indicatorGroup.setLayoutParams(layoutParams);
}
本文源碼下載
最后跟大家分享一下另外一個(gè)仿iPhone通訊錄效果的代碼。它是ListView的擴(kuò)展,效果最好。希望有高手能把ExpandableListView擴(kuò)展成一樣的效果。
源碼下載
我這里沒有把ExpandableListView獨(dú)立出來(lái)形成一個(gè)新的控件,跟網(wǎng)上很多朋友一樣,監(jiān)聽OnScrollListener事件,當(dāng)group不是在第一個(gè)位置時(shí),就把我們頭部的那個(gè)indicator顯示出來(lái),并且讓它的view跟當(dāng)前child所在group的view一樣的,然后再增加一個(gè)點(diǎn)擊關(guān)閉組的事件,即達(dá)到了簡(jiǎn)單的仿QQ好友分組的效果。
下面我們先來(lái)看看主要的布局文件:main.xml,下面那個(gè)topGroup的FrameLayout就是我們的指示器。
復(fù)制代碼 代碼如下:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ExpandableListView
android:id="@+id/expandableListView"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</ExpandableListView>
<FrameLayout
android:id="@+id/topGroup"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
</FrameLayout>
</FrameLayout>
其中最重要的是下面這部分:我們監(jiān)聽onSroll這個(gè)接口事件,當(dāng)ListView在滑動(dòng)時(shí),做相應(yīng)的處理,代碼中注釋比較多,我這里就不多作說明了。
復(fù)制代碼 代碼如下:
/**
* here is very importance for indicator group
*/
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
final ExpandableListView listView = (ExpandableListView) view;
/**
* calculate point (0,0)
*/
int npos = view.pointToPosition(0, 0);// 其實(shí)就是firstVisibleItem
if (npos == AdapterView.INVALID_POSITION)// 如果第一個(gè)位置值無(wú)效
return;
long pos = listView.getExpandableListPosition(npos);
int childPos = ExpandableListView.getPackedPositionChild(pos);// 獲取第一行child的id
int groupPos = ExpandableListView.getPackedPositionGroup(pos);// 獲取第一行g(shù)roup的id
if (childPos == AdapterView.INVALID_POSITION) {// 第一行不是顯示child,就是group,此時(shí)沒必要顯示指示器
View groupView = listView.getChildAt(npos
- listView.getFirstVisiblePosition());// 第一行的view
indicatorGroupHeight = groupView.getHeight();// 獲取group的高度
indicatorGroup.setVisibility(View.GONE);// 隱藏指示器
} else {
indicatorGroup.setVisibility(View.VISIBLE);// 滾動(dòng)到第一行是child,就顯示指示器
}
// get an error data, so return now
if (indicatorGroupHeight == 0) {
return;
}
// update the data of indicator group view
if (groupPos != indicatorGroupId) {// 如果指示器顯示的不是當(dāng)前group
mAdapter.getGroupView(groupPos, listView.isGroupExpanded(groupPos),
indicatorGroup.getChildAt(0), null);// 將指示器更新為當(dāng)前group
indicatorGroupId = groupPos;
Log.e(TAG, PRE + "bind to new group,group position = " + groupPos);
// mAdapter.hideGroup(indicatorGroupId); // we set this group view
// to be hided
// 為此指示器增加點(diǎn)擊事件
indicatorGroup.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
listView.collapseGroup(indicatorGroupId);
}
});
}
if (indicatorGroupId == -1) // 如果此時(shí)grop的id無(wú)效,則返回
return;
/**
* calculate point (0,indicatorGroupHeight) 下面是形成往上推出的效果
*/
int showHeight = indicatorGroupHeight;
int nEndPos = listView.pointToPosition(0, indicatorGroupHeight);// 第二個(gè)item的位置
if (nEndPos == AdapterView.INVALID_POSITION)// 如果無(wú)效直接返回
return;
long pos2 = listView.getExpandableListPosition(nEndPos);
int groupPos2 = ExpandableListView.getPackedPositionGroup(pos2);// 獲取第二個(gè)group的id
if (groupPos2 != indicatorGroupId) {// 如果不等于指示器當(dāng)前的group
View viewNext = listView.getChildAt(nEndPos
- listView.getFirstVisiblePosition());
showHeight = viewNext.getTop();
Log.e(TAG, PRE + "update the show part height of indicator group:"
+ showHeight);
}
// update group position
MarginLayoutParams layoutParams = (MarginLayoutParams) indicatorGroup
.getLayoutParams();
layoutParams.topMargin = -(indicatorGroupHeight - showHeight);
indicatorGroup.setLayoutParams(layoutParams);
}
本文源碼下載
最后跟大家分享一下另外一個(gè)仿iPhone通訊錄效果的代碼。它是ListView的擴(kuò)展,效果最好。希望有高手能把ExpandableListView擴(kuò)展成一樣的效果。
源碼下載
您可能感興趣的文章:
- Android ViewPager小圓點(diǎn)指示器
- Android實(shí)現(xiàn)引導(dǎo)頁(yè)的圓點(diǎn)指示器
- Android之IphoneTreeView帶組指示器的ExpandableListView效果
- Android TabLayout設(shè)置指示器寬度的方法
- Android實(shí)現(xiàn)仿網(wǎng)易新聞的頂部導(dǎo)航指示器
- Android自定義ViewPagerIndicator實(shí)現(xiàn)炫酷導(dǎo)航欄指示器(ViewPager+Fragment)
- Android實(shí)現(xiàn)基于ViewPager的無(wú)限循環(huán)自動(dòng)播放帶指示器的輪播圖CarouselFigureView控件
- Android開發(fā)實(shí)現(xiàn)的ViewPager引導(dǎo)頁(yè)功能(動(dòng)態(tài)加載指示器)詳解
- Android progressbar實(shí)現(xiàn)帶底部指示器和文字的進(jìn)度條
- Android自定義圓點(diǎn)指示器
相關(guān)文章
用xutils3.0進(jìn)行下載項(xiàng)目更新
這篇文章主要介紹了用xutils3.0進(jìn)行下載項(xiàng)目更新的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-08-08
Android 圖片處理避免出現(xiàn)oom的方法詳解
本篇文章主要介紹了Android 圖片處理避免出現(xiàn)oom的方法詳解,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-09-09
Android 仿微信自定義數(shù)字鍵盤的實(shí)現(xiàn)代碼
本篇文章主要介紹了Android 仿微信自定義數(shù)字鍵盤的實(shí)現(xiàn)代碼,具有一定的參考價(jià)值,有興趣的可以了解一下2017-07-07
Android自定義View實(shí)現(xiàn)拖動(dòng)自動(dòng)吸邊效果
這篇文章主要為大家詳細(xì)介紹了Android自定義View實(shí)現(xiàn)拖動(dòng)自動(dòng)吸邊效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-06-06
Android中毛玻璃效果的兩種實(shí)現(xiàn)代碼
這篇文章主要介紹了Android中毛玻璃效果的兩種實(shí)現(xiàn)代碼,第一種是使用JAVA算法FastBlur實(shí)現(xiàn),第二種是使用Android自帶類RenderScript 實(shí)現(xiàn),本文通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友參考下吧2024-08-08
Android中通過RxJava進(jìn)行響應(yīng)式程序設(shè)計(jì)的入門指南
響應(yīng)式編程在Android中的運(yùn)用是非常犀利的,比如在異常處理和調(diào)度器方面,這里我們將從生命周期等方面來(lái)講解Android中通過RxJava進(jìn)行響應(yīng)式程序設(shè)計(jì)的入門指南:2016-06-06
Android自定義View仿QQ等級(jí)天數(shù)進(jìn)度
這篇文章主要為大家詳細(xì)介紹了Android自定義View仿QQ等級(jí)天數(shù)進(jìn)度效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-07-07
Android開發(fā)之自定義view實(shí)現(xiàn)通訊錄列表A~Z字母提示效果【附demo源碼下載】
這篇文章主要介紹了Android開發(fā)之自定義view實(shí)現(xiàn)通訊錄列表A~Z字母提示效果,結(jié)合完整實(shí)例形式分析了Android獲取通訊錄列表及采用自定義view排列顯示的相關(guān)操作技巧,需要的朋友可以參考下2017-07-07

