在ListView中嵌套ListView的事件處理

前天在工做中遇到在ListView中的Item須要用ListView來展示處理後的內容,而後就遇到了一個很頭疼的問題,做爲Item的ListView無法進行滑動,並且顯示也不正常,只是顯示幾個子Item。不能將子Item所有顯示,緣由是在控件繪製出來以前要對ListView的大小進行計算,要解決將子ListView所有顯示出來的問題,就是從新計算一下其大小告知系統便可。後面這個問題比較好解決,網上已經給出解決方案: html

前輩們給出了一個方法,從新計算子ListView的大小,而後在設置本ListView的Adapter以後運行這個方法就行了,具體代碼以下: java

    

/** 

     * 設置Listview的高度 

     */  

    public void setListViewHeight(ListView listView) {   

        ListAdapter listAdapter = listView.getAdapter();    

        if (listAdapter == null) {   

            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);  

    }

可是這個方法設置的item的Layout必須是帶有onMeasure()方法的控件,不然在計算的時候會報錯,建議使用LinearLayout android

再一個思路相同,可是,不是額外作方法來實現onMeasure()方法的計算LIstView的大小,而是本身繼承ListView,重寫ListView的onMeasure()方法,來本身計算ListView的高度,而後再xml中直接使用這個自定義的ListView就能夠了。 ide

public class MyListView extends ListView { 

    public  MyListView  (Context context, AttributeSet attrs) { 

        super(context, attrs); 

    } 

    public  MyListView  (Context context) { 

        super(context); 

    } 

    public  MyListView  (Context context, AttributeSet attrs, int defStyle) { 

        super(context, attrs, defStyle); 

    } 

    @Override 

    public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 

        int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, 

                MeasureSpec.AT_MOST); 

        super.onMeasure(widthMeasureSpec, expandSpec); 

    } 

}

這是解決讓做爲Item的ListView顯示所有內容的方案,可是有些時候咱們是想讓做爲Item的ListView不用所有顯示,而是能夠進行滑動,要解決這個問題就須要瞭解一下android對事件的分發機制了 性能

個人解決方案是集成ListView,重寫interceptTouchEvent使其返回false來取消父ListView對觸摸事件的攔截,將觸摸事件分發到子View來處理。而後在使用的時候,將其做爲父ListView使用,就可使子ListView能夠滑動了。思想來源於下面連接的6樓 this

http://www.eoeandroid.com/thread-3597-1-1.html 編碼

 

具體自定義父ListView代碼

public class ParentListView extends ListView {

public ParentListView(Context context) {

super(context);

// TODO Auto-generated constructor stub

}

public ParentListView(Context context, AttributeSet attrs, int defStyle) {

super(context, attrs, defStyle);

// TODO Auto-generated constructor stub

}

public ParentListView(Context context, AttributeSet attrs) {

super(context, attrs);

// TODO Auto-generated constructor stub

}
//將 onInterceptTouchEvent的返回值設置爲false,取消其對觸摸事件的處理,將事件分發給子view

@Override

public boolean onInterceptTouchEvent(MotionEvent ev) {

// TODO Auto-generated method stub

return false;

}

}

xml文件:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >
<!-- 這裏作demo用,直接使用了android中的ListActivity-->
    <i.test.ParentListView android:id=" @android :id/list"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:dividerHeight="2dip"
        android:scrollbars="none"
        />

</LinearLayout>

activity代碼以下:
public class ListviewActivity extends ListActivity {
    /** Called when the activity is first created. */
private ListView mLv;//這個ListView就是自定義的View
private ParentAdapter adapter;
private final static String[] array = new String[]{"1","2","3","4","5","6","7","8","9","10","11","12","13","14"};
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        mLv = getListView();
        adapter = new ParentAdapter();
        mLv.setAdapter(adapter);
        
    }
    private class ParentAdapter extends BaseAdapter{

@Override
public int getCount() {
// TODO Auto-generated method stub
return Array.getLength(array);
}

@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return array[position];
}

@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
View view;
if(position == 5){
view = View.inflate(getApplicationContext(), R.layout.item, null);
ListView lv = (ListView) view.findViewById(R.id.lv);
ArrayAdapter<String> mAdapter = new ArrayAdapter<String>(ListviewActivity.this, android.R.layout.simple_list_item_1, new String[]{"a","b",
"c","d","e","f","g"});
lv.setAdapter(mAdapter);
}
else{
TextView  tv = new TextView(getApplicationContext());
tv.setText(array[position]);
tv.setTextSize(30);
view = tv;
}
return view;
}
   
    }
}

上面的方法一樣適合在ScrollView中嵌套能夠滑動View的狀況。 spa

後記:2013.04.10
今天登陸oschian看到有人提到我,打開消息一看,是對這篇文字的評論,很高興我寫的東西對別人有所幫助。評論人 @jimmy.zhao ,謝謝你讓我知道,我幫助了你,這是博客寫下去的動力。
.net

這篇文字是在我畢業以後剛入職次日解決的問題,話說這個問題困擾前面的人有兩個月了,我來了以後就把這個坑讓我填,前輩說在網上找的全部方案都是已經有牛人給出解決方案。都這麼說,可是沒有一我的說解決方案是什麼,因而讓我研究了下。不能說我這篇文字是最先解決這個嵌套滑動問題的,可是如你搜一下解決滑動嵌套問題的帖子基本都在我這篇以後,先本身小驕傲下。 code

下面說說我在使用這種方法解決了這個問題以後遇到的問題(好像有點繞。。但攻城獅不怕哈),但願能引發後來人的注意:
問題出在一個月以後,根據項目需求,外面的ListView,即父ListView中的條目展現文本數字時須要加入對電話號碼和HTTP連接的識別。即:若是是手機號碼,點擊以後進入撥號盤界面。你們知道,這個很簡單,只要在TextView中設置一個簡單的屬性就行了。而後個人問題就出現,由於父ListView的觸摸事件交給了子view,若是子view中的TextView帶有這種隱式的點擊事件,就會形成父ListView的卡頓現象。並且是至關卡頓。因而在項目中,仍是使用了固定子ListView大小,直接使用系統的ListView再也不重寫父ListView的onInterceptTouchEvent事件。將展現更多,做爲加載來處理。還有一個就是在使用TextView的時候,儘可能避免使用Html.from()來讓TextView支持簡單html標籤。這個太耗性能。用MAT一看便知,很少說。但願對有時間看本文一眼的人有所幫助。

生命不息,編碼不止

相關文章
相關標籤/搜索