1. 程式人生 > >ScrollView中巢狀ListView的技巧總結

ScrollView中巢狀ListView的技巧總結

前幾天因為專案的需要,要在一個ListView中放入另一個ListView,也即在一個ListView的每個ListItem中放入另外一個ListView。但剛開始的時候,會發現放入的小ListView會顯示不完全,它的高度始終有問題。上網查了下,發現別人也有遇到這樣的問題,而大多數人都不推薦這樣的設計,因為預設情況下Android是禁止在ScrollView中放入另外的ScrollView的,它的高度是無法計算的。

提出兩種解決方法:

第一種方案針對這種情況:在正螢幕中,螢幕的上方有些概要資訊需要顯示,下方有個列表資訊需要顯示,而因為概要資訊已經佔用了1/3的螢幕高度,而現在想在下面列表滾動的時候上面的概要資訊隨著滾動隱藏,就好像概要資訊和下面的列表資訊都是在一個列表裡面一樣,這個時候可以將概要資訊包裹在一個ViewGroup中,然後使用LIstView.addHead(View)方法新增到列表中即可。

---------------------------------------------------------------------------------------------------

另外一種網上找的的:

     發現有StackOverflow上的牛人已經解決了這個問題,經過試驗發現是可以解決問題的,它的思路就是在設定完ListView的Adapter後,根據ListView的子專案重新計算ListView的高度,然後把高度再作為LayoutParams設定給ListView,這樣它的高度就正確了,以下是別人的原始碼:

public class Utility { 

    public static void setListViewHeightBasedOnChildren(ListView listView) { 

        ListAdapter listAdapter = listView.getAdapter();  

        if (listAdapter == null) { 

            // pre-condition 

            return; 

        } 

        int totalHeight = 0; 

        for (int i = 0; i < listAdapter.getCount(); i++) { 

            View listItem = listAdapter.getView(i, null, listView); 

            listItem.measure(0, 0); 

            totalHeight += listItem.getMeasuredHeight(); 

        } 

        ViewGroup.LayoutParams params = listView.getLayoutParams(); 

        params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1)); 

        listView.setLayoutParams(params); 

    } 

只要在設定ListView的Adapter後呼叫此靜態方法即可讓ListView正確的顯示在其父ListView的ListItem中。但是要注意的是,子ListView的每個Item必須是LinearLayout,不能是其他的,因為其他的Layout(如RelativeLayout)沒有重寫onMeasure(),所以會在onMeasure()時丟擲異常。

      在ScrollView中巢狀ListView(或者ScrollView)的另外一個問題就是,子ScrollView中無法滑動的(如果它沒有顯示完全的話),因為滑動事件會被父ScrollView吃掉,如果想要讓子ScrollView也可以滑動,只能強行擷取滑動事件,有牛人在論壇中發過程式碼說可以。雖然我沒有親自試過,但估計是可行的。

      雖然在ScrollView中顯示ScrollView在技術上的難題可以攻破,但是這樣的設計卻是非常差的使用者體驗因為使用者會不容易看到和操作子ScrollView中的內容。比如好的設計是,父ListView的每個Item只顯示概括性的描述,然後點選其Item會進入另外一個頁面來詳細描述和展示以及對這個Item的操作

參考文章:

在android 的開發中,官方給出的建議是ScrollView中建議不要巢狀ListView,可是實際中可能會遇到一些迫不得已的情況,讓我們需要實現這樣的功能。
ScrollView巢狀ListView往往會初現顯示不全的問題,而且ScrollView可能會將ListView 的滑動事件覆蓋了,兩個控制元件的高度都是變動的,使得無法計算具體的高度。
解決的思路是在設定完listAdapter過後,再根據ListView 的單個item重新設定ListAdapter的高度。

public static void reSetListViewHeight(ListView listView) {
ListAdapter listAdapter = listView.getAdapter();
if (listAdapter == null) {
// pre-condition
return;
}

int totalHeight = 0;
for (int i = 0; i < listAdapter.getCount(); i++) {
View listItem = listAdapter.getView(i, null, listView);
listItem.measure(0, 0);
totalHeight += listItem.getMeasuredHeight();
}

ViewGroup.LayoutParams params = listView.getLayoutParams();
params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() – 1));
listView.setLayoutParams(params);
}