ScrollView與ListView衝突解決

正 常來講,在ScrollView添加一個ListView後在真機上只會顯示ListView的一行多一點,我也不理解爲何會這樣,後來我把 ListView的layout_height改爲400dip,而不是用match_parent和wrap_content,我發現這樣的話 ListView就顯示的多了不少。因此就產生了把ListView全部的item的高度算出來給ListView設置的想法。下面是代碼:html

源碼:http://www.jinhusns.com/Products/Download/?type=xcjjava

Java代碼  收藏代碼android

  1. public void setListViewHeightBasedOnChildren(ListView listView) {    編程

  2.         ListAdapter listAdapter = listView.getAdapter();     app

  3.         if (listAdapter == null) {    ide

  4.             return;    函數

  5.         }    佈局

  6.     

  7.         int totalHeight = 0;    測試

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

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

  10.             listItem.measure(0, 0);    

  11.             totalHeight += listItem.getMeasuredHeight();    

  12.         }    

  13.     

  14.         ViewGroup.LayoutParams params = listView.getLayoutParams();    

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

  16.         params.height += 5;//if without this statement,the listview will be a little short    

  17.         listView.setLayoutParams(params);    

  18.     }    

 


在代碼的倒數第二行二我又給加了5個像素,這是由於我在listview的屬性裏面添加了padding=5dip。 
而後每次ListView的數據一有變化就用這個函數設置一下就行了,不過這樣總感受效率很低,但願有達人給指點一下。 

簡單來講就是把layout_height寫死,這種辦法也很適用於GridView(若是能估計得出GridView的高度的話)。 


listview與ScrollView老問題的另類解法 
http://www.eoeandroid.com/thread-42893-1-1.html 
這 幾天一直被listview怎麼合理的放進scorllview中的問題困擾,嘗試過把listview放入scorllview中的朋友都知 道,被放入的listview顯示是有問題的,不管怎麼設置layout都只顯示大概2行的高度,看起來很鬱悶,更別說美觀了,後來上網查詢了一下,解決 方法有的是用linearlayout替換listview,還有修改onmeasure的,我比較懶我的感受很麻煩不喜歡,終於想出了一個還算和諧的解 決方法:xml中的textlist設置以下:

Java代碼  收藏代碼

  1. <?xml version="1.0" encoding="UTF-8"?>  

  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  

  3.     android:layout_width="fill_parent"  

  4.     android:layout_height="wrap_content"  

  5.     android:orientation="vertical"  

  6.     android:background="#44444444">  

  7. <ScrollView  

  8.      android:layout_width="fill_parent"  

  9.      android:layout_height="wrap_content">  

  10.     <LinearLayout  

  11.             android:id="@+id/ll1"  

  12.             android:layout_width="fill_parent"  

  13.             android:layout_height="wrap_content"  

  14.             android:scrollbars="vertical"  

  15.             android:orientation="vertical"  

  16.             android:paddingLeft="15dp"  

  17.             android:paddingRight="15dp"  

  18.             android:paddingTop="30dp"  

  19.             android:paddingBottom="30dp"  

  20.             android:background="#ff888888">  

  21.             <TextView  

  22.                     android:text="あ"  

  23.                     android:textColor="#ffeeeeee"  

  24.                     android:textSize="18sp"  

  25.                     android:layout_width="fill_parent"  

  26.                     android:layout_height="wrap_content"></TextView>  

  27.             <ListView  

  28.                     android:scrollbars="none"  

  29.                     android:stackFromBottom="true"  

  30.                     android:id="@+id/lv0"  

  31.                     android:layout_width="fill_parent"  

  32.                     android:layout_height="20dp"></ListView>  

  33.                     </LinearLayout>  

  34. </ScrollView>  

  35. </LinearLayout>   

 

其中的textview是我作的東西要用到的,和方法無關能夠不看,而後就是在java中從新設置listview的高度了,目的是把listview「撐」開: 
LinearLayout.LayoutParams  lp5 =new LinearLayout.LayoutParam(LayoutParams.FILL_PARENT, listItem.size()*51-1); 
其 中第一個屬性沒必要說了,第二個是爲了計算listview要設置的總高度用的,51是我事先設置好的一行的高度(50)+每行之間的間隔(1) 而得來的,listItem.size()是我要顯示的行數,用.setLayoutParams(lp5);來從新設置高度,其餘別的設置跟之前同樣, 想要源碼我整理完以後貼出來 


若是不想寫死 ,Android 解決ListView 和 ScrollView 共存衝突的問題 
http://labs.chinamobile.com/mblog/532767_72693?wralxianxrnx 
http://blog.liaoxiaoqi.com/?p=503

 

下面是個人一個實現 步驟:

  • 一、繼承LinearLayout,既然會衝突那就不用ListView 改爲線性佈局作動態佈局效果

  • 二、繼承BaseAdapter ,能夠參照一下Android app源碼中 Widget 目錄下的SimpleAdapter 爲前面擴展的LinearLayout作數據。

  • 三、模擬數據填充擴展後的BaseAdapter 爲擴展後的LinearLayout 加載數據

第一步:新建LinearLayoutForListView 類使其擴展LinearLayout重寫如下兩個方法:

 

Java代碼  收藏代碼

  1. public LinearLayoutForListView(Context context) {  

  2.      super(context);  

  3.  }  

  4.  public LinearLayoutForListView(Context context, AttributeSet attrs) {  

  5.      super(context, attrs);  

  6.  }  

 

這兩個方法可選,不過建議都寫上,第一個方法可讓咱們經過 編程的方式 實例化出來,第二個方法能夠容許咱們經過 XML的方式註冊 控件,能夠在第二個方法裏面爲擴展的複合組件加屬性。爲其添加get / set 方法

Java代碼  收藏代碼

  1. /** 

  2.   * 獲取Adapter 

  3.   *  

  4.   * @return adapter 

  5.   */  

  6.  public AdapterForLinearLayout getAdpater() {  

  7.      return adapter;  

  8.  }  

  9.   

  10.  /** 

  11.   * 設置數據 

  12.   *  

  13.   * @param adpater 

  14.   */  

  15.  public void setAdapter(AdapterForLinearLayout adpater) {  

  16.      this.adapter = adpater;  

  17.      bindLinearLayout();  

  18.  }  

  19.   

  20.  /** 

  21.   * 獲取點擊事件 

  22.   *  

  23.   * @return 

  24.   */  

  25.  public OnClickListener getOnclickListner() {  

  26.      return onClickListener;  

  27.  }  

  28.   

  29.  /** 

  30.   * 設置點擊事件 

  31.   *  

  32.   * @param onClickListener 

  33.   */  

  34.  public void setOnclickLinstener(OnClickListener onClickListener) {  

  35.      this.onClickListener = onClickListener;  

  36.  }  

  37. sp;  

第二步:新建AdapterForLinearLayout 類繼承自BaseAdapter,併爲其添加構造函數

 

 

Java代碼  收藏代碼

  1. private LayoutInflater mInflater;  

  2.     private int resource;  

  3.     private List<? extends Map<String, ?>> data;  

  4.     private String[] from;  

  5.     private int[] to;  

  6.   

  7.     public AdapterForLinearLayout(Context context,  

  8.             List<? extends Map<String, ?>> data, int resouce, String[] from,  

  9.             int[] to) {  

  10.         this.data = data;  

  11.         this.resource = resouce;  

  12.         this.data = data;  

  13.         this.from = from;  

  14.         this.to = to;  

  15.         this.mInflater = (LayoutInflater) context  

  16.                 .getSystemService(Context.LAYOUT_INFLATER_SERVICE);  

  17.     }  

 

此 構造函數模仿 simpleAdapter 經過傳進來的resouce 爲佈局設置數據。經過繼承BaseAdapter 重要的實現方法在下面getView ,此方法判斷經過傳進來的 String[] from 與 int[] to 爲分別查找出View 併爲View 設置相應的Text,代碼以下:

 

 

Java代碼  收藏代碼

  1. @Override  

  2.  public View getView(int position, View convertView, ViewGroup parent) {  

  3.      // TODO Auto-generated method stub  

  4.   

  5.      convertView = mInflater.inflate(resource, null);  

  6.      Map<String, ?> item = data.get(position);  

  7.      int count = to.length;  

  8.      for (int i = 0; i < count; i++) {  

  9.          View v = convertView.findViewById(to[i]);  

  10.          bindView(v, item, from[i]);  

  11.      }  

  12.      convertView.setTag(position);  

  13.      return convertView;  

  14.  }  

  15.   

  16.  /** 

  17.   * 綁定視圖 

  18.   * @param view 

  19.   * @param item 

  20.   * @param from 

  21.   */  

  22.  private void bindView(View view, Map<String, ?> item, String from) {  

  23.      Object data = item.get(from);  

  24.      if (view instanceof TextView) {  

  25.          ((TextView) view).setText(data == null ? "" : data.toString());  

  26.      }  

  27.  }  

 

Tip:

  • BindView 方法是一個自定義方法,在方法體內能夠爲經過判斷使本類更具靈活性,如上,你不只能夠判斷是TextView 而且能夠傳入任何你想要的View 只要在方法體內加入相應判斷便可,數據能夠經過data 作相應處理,具體如何操做讀者可另行測試。

  • convertView.setTag(position); 此句代碼爲View 設置tag 在之後咱們能夠經過 getTag 找出下標,後文有介紹如何經過下標操做數據。

下面是兩個類的所有代碼,讀者能夠無須更改直接使用:

Java代碼  收藏代碼

  1. LinearLayoutForListView  

  2. package  com.terry.widget;  

  3.   

  4. import  android.content.Context;  

  5. import  android.util.AttributeSet;  

  6. import  android.util.Log;  

  7. import  android.view.View;  

  8. import  android.widget.LinearLayout;  

  9.   

  10. public   class  LinearLayoutForListView  extends  LinearLayout {  

  11.      private  AdapterForLinearLayout adapter;  

  12.      private  OnClickListener onClickListener  =   null ;  

  13.   

  14.      /** 

  15.      * 綁定佈局 

  16.       */  

  17.      public   void  bindLinearLayout() {  

  18.          int  count  =  adapter.getCount();  

  19.          for  ( int  i  =   0 ; i  <  count; i ++ ) {  

  20.             View v  =  adapter.getView(i,  null ,  null );  

  21.   

  22.             v.setOnClickListener( this .onClickListener);  

  23.              if  (i  ==  count  -   1 ) {  

  24.                 LinearLayout ly  =  (LinearLayout) v;  

  25.                 ly.removeViewAt( 2 );  

  26.             }  

  27.             addView(v, i);  

  28.         }  

  29.         Log.v( " countTAG " ,  ""   +  count);  

  30.     }  

  31.   

  32.      public  LinearLayoutForListView(Context context) {  

  33.          super (context);  

  34.     }  

  35.   

  36.      public  LinearLayoutForListView(Context context, AttributeSet attrs) {  

  37.          super (context, attrs);  

  38.     }  

  39.   

  40.      /** 

  41.      * 獲取Adapter 

  42.      *  

  43.      *  @ return  adapter 

  44.       */  

  45.      public  AdapterForLinearLayout getAdpater() {  

  46.          return  adapter;  

  47.     }  

  48.   

  49.      /** 

  50.      * 設置數據 

  51.      *  

  52.      *  @ param  adpater 

  53.       */  

  54.      public   void  setAdapter(AdapterForLinearLayout adpater) {  

  55.          this .adapter  =  adpater;  

  56.         bindLinearLayout();  

  57.     }  

  58.   

  59.      /** 

  60.      * 獲取點擊事件 

  61.      *  

  62.      *  @ return 

  63.       */  

  64.      public  OnClickListener getOnclickListner() {  

  65.          return  onClickListener;  

  66.     }  

  67.   

  68.      /** 

  69.      * 設置點擊事件 

  70.      *  

  71.      *  @ param  onClickListener 

  72.       */  

  73.      public   void  setOnclickLinstener(OnClickListener onClickListener) {  

  74.          this .onClickListener  =  onClickListener;  

  75.     }  

  76. }  

 

 

Java代碼  收藏代碼

  1. AdapterForLinearLayout  

  2. package  com.terry.widget;  

  3.   

  4. import  java.util.List;  

  5. import  java.util.Map;  

  6.   

  7. import  android.content.Context;  

  8. import  android.view.LayoutInflater;  

  9. import  android.view.View;  

  10. import  android.view.ViewGroup;  

  11. import  android.widget.BaseAdapter;  

  12. import  android.widget.TextView;  

  13.   

  14. public   class  AdapterForLinearLayout  extends  BaseAdapter {  

  15.   

  16.      private  LayoutInflater mInflater;  

  17.      private   int  resource;  

  18.      private  List <?   extends  Map < String,  ?>>  data;  

  19.      private  String[] from;  

  20.      private   int [] to;  

  21.   

  22.      public  AdapterForLinearLayout(Context context,  

  23.             List <?   extends  Map < String,  ?>>  data,  int  resouce, String[] from,  

  24.              int [] to) {  

  25.          this .data  =  data;  

  26.          this .resource  =  resouce;  

  27.          this .data  =  data;  

  28.          this .from  =  from;  

  29.          this .to  =  to;  

  30.          this .mInflater  =  (LayoutInflater) context  

  31.                 .getSystemService(Context.LAYOUT_INFLATER_SERVICE);  

  32.     }  

  33.   

  34.     @ Override  

  35.      public   int  getCount() {  

  36.          //  TODO Auto-generated method stub  

  37.          return  data.size();  

  38.     }  

  39.   

  40.     @ Override  

  41.      public  Object getItem( int  position) {  

  42.          //  TODO Auto-generated method stub  

  43.          return  data.get(position);  

  44.     }  

  45.   

  46.     @ SuppressWarnings( " unchecked " )  

  47.      public  String get( int  position, Object key) {  

  48.         Map < String,  ?>  map  =  (Map < String,  ?> ) getItem(position);  

  49.          return  map.get(key).toString();  

  50.     }  

  51.   

  52.     @ Override  

  53.      public   long  getItemId( int  position) {  

  54.          //  TODO Auto-generated method stub  

  55.          return  position;  

  56.     }  

  57.   

  58.     @ Override  

  59.      public  View getView( int  position, View convertView, ViewGroup parent) {  

  60.          //  TODO Auto-generated method stub  

  61.   

  62.         convertView  =  mInflater.inflate(resource,  null );  

  63.         Map < String,  ?>  item  =  data.get(position);  

  64.          int  count  =  to.length;  

  65.          for  ( int  i  =   0 ; i  <  count; i ++ ) {  

  66.             View v  =  convertView.findViewById(to[i]);  

  67.             bindView(v, item, from[i]);  

  68.         }  

  69.         convertView.setTag(position);  

  70.          return  convertView;  

  71.     }  

  72.   

  73.      /** 

  74.      * 綁定視圖 

  75.      *  @ param  view 

  76.      *  @ param  item 

  77.      *  @ param  from 

  78.       */  

  79.      private   void  bindView(View view, Map < String,  ?>  item, String from) {  

  80.         Object data  =  item.get(from);  

  81.          if  (view  instanceof  TextView) {  

  82.             ((TextView) view).setText(data  ==   null   ?   ""  : data.toString());  

  83.         }  

  84.     }  

  85. }  

 

對應的XML 以下:

Java代碼  收藏代碼

  1. <? xml version="1.0" encoding="UTF-8" ?>  

  2. < LinearLayout  xmlns:android ="http://schemas.android.com/apk/res/android"  

  3.     android:orientation ="vertical"  android:layout_width ="fill_parent"  

  4.     android:layout_height ="fill_parent" >  

  5.      < TextView  android:id ="@ +id/TextView01"  

  6.         android:layout_marginLeft ="10px"  android:textAppearance ="?android:attr/textAppearanceLarge"  

  7.         android:layout_width ="wrap_content"  android:layout_height ="wrap_content" >  

  8.      </ TextView >  

  9.      < TextView  android:id ="@ +id/TextView02"  android:layout_width ="wrap_content"  

  10.         android:textAppearance ="?android:attr/textAppearanceSmall"  

  11.         android:layout_marginLeft ="10px"  android:layout_height ="wrap_content" >  

  12.      </ TextView >  

  13.      < View  android:layout_height ="1px"  android:background ="#FFFFFF"  

  14.         android:layout_width ="fill_parent" ></ View >  

  15. </ LinearLayout >  

 

第三步:主頁面使用控件併爲其設置數據

  • XML以下:

        

    Java代碼  收藏代碼

    1. < com.terry.widget.LinearLayoutForListView  

    2.           android:orientation ="vertical"  android:layout_width ="450px"  

    3.            android:layout_height ="fill_parent"  android:id ="@ +id/ListView01" >  

    4. </ com.terry.widget.LinearLayoutForListView >   

  • 加載數據以下:

    Java代碼  收藏代碼

    1. lv  =  (LinearLayoutForListView) findViewById(R.id.ListView01);  

    2.          for  ( int  i  =   0 ; i  <   10 ; i ++ ) {  

    3.             HashMap < String, Object >  map  =   new  HashMap < String, Object > ();  

    4.             map.put( " key_name " ,  " name "   +  i);  

    5.             map.put( " value_name " ,  " value "   +  i);  

    6.             list.add(map);  

    7.         }  

    8.   

    9.          final  AdapterForLinearLayout Layoutadpater  =   new  AdapterForLinearLayout(  

    10.                  this , list, R.layout.test,  new  String[] {  " key_name " ,  

    11.                          " value_name "  },  new   int [] { R.id.TextView01,  

    12.                         R.id.TextView02 });  

  • 事件操做,並經過下標獲得數據源:

    Java代碼  收藏代碼

    Tip:get方法是在Layoutadpater 封裝的一個經過下標獲取相應數據的方法請參考上文。

    1. lv.setOnclickLinstener( new  OnClickListener() {  

    2.   

    3.             @ Override  

    4.              public   void  onClick(View v) {  

    5.                  //  TODO Auto-generated method stub  

    6.                 Toast.makeText(  

    7.                         BlueToothActivity. this ,  

    8.                         Layoutadpater.get(Integer.parseInt(v.getTag()  

    9.                                 .toString()),  " key_name " ),  1000 ).show();  

    10.             }  

    11.         });  

    12. lv.setAdapter(Layoutadpater);  

至此完成。有碰到這個問題的朋友能夠試試。

 

有人的總結以下:
      只要在設置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的操做。
 源碼:http://www.jinhusns.com/Products/Download/?type=xcj
因而找到另外兩種比較簡單的方法,並且又沒有影響的:
1.在ScrollView中添加一屬性 android:fillViewport="true" ,這樣就可讓ListView全屏顯示了2.指定ListView的高度 android:layout_height="420dp" ;

相關文章
相關標籤/搜索