轉載請注明出處:
http://www.goteny.com/articles/2013/11/8.html
http://www.cnblogs.com/zjjne/p/3428480.html
當同一個頁面布局中的ScrollView中包含有ListView時,兩個布局由於都有滑動而導致沖突,最明顯的特征就是當ListView中有多個子項時,會出現顯示不全的情況,只會顯示一兩個子項。
以前查到一個簡單的解決辦法setListViewHeightBasedOnChildren(ListView listView)的那個辦法,是測出ListView中每一個子項視圖的高度,然后再相加起來,以這個值來設定整個ListView的高度。這種方法的優點是比較簡單,能解決子項視圖布局比較簡單且文字較少的情況;但不足之處是每次刷新ListView時都要調用這個函數來重新設定ListView的高度,重點是:若子項視圖中文字過多,出現文字自動換行的時候,此時測出來的高度就不准確了,難以做到准確設置ListView的高度。
這次要介紹的方法雖說有點麻煩,但是相對來說比較治本的方法,其思想是繼承並擴展線性布局LinearLayout,用LinearLayout替代ListView來實現ListView的功能和效果。
下面是效果示例:
這是修改前的沖突情況(ListView顯示只能顯示第一行)
這是修改后的效果
本文的實現思想和代碼是在
【Android 解決ListView 和 ScrollView 共存沖突的問題http://terryblog.blog.51cto.com/1764499/373509 】
這篇文章的基礎上作了少許修改和“添加子項間分隔線、子項點擊事件監聽”而成的。
主要思想是:
給LinearLayout添加BaseAdapter、OnItemClickListener成員,
然后在綁定布局時調用BaseAdapter的getView方法取得子項的視圖View,
將此View用addView方法添加進LinearLayout中;
並設置每一個子項視圖View的監聽點擊事件OnClickListener,
在OnClickListener的onClick方法中調用OnItemClickListener的
onItemClick方法,即在將子項的點擊事件轉發到LinearLayout的onItemClick事件中。
下面是用來替代ListView的LinearLayout代碼,此LinearLayoutForListView作為自定義控件來替代ListView,
用法和ListView的用法一樣,使用BaseAdapter來做適配器
1 package com.and.mine; 2 3 import android.content.Context; 4 import android.util.AttributeSet; 5 import android.util.Log; 6 import android.util.TypedValue; 7 import android.view.View; 8 import android.widget.AdapterView.OnItemClickListener; 9 import android.widget.BaseAdapter; 10 import android.widget.LinearLayout; 11 12 public class LinearLayoutForListView extends LinearLayout 13 { 14 private BaseAdapter adapter; 15 private OnItemClickListener onItemClickListener; 16 17 18 /** 19 * 通過 Java代碼 實例化 20 * @param context 21 */ 22 public LinearLayoutForListView(Context context) 23 { 24 super(context); 25 //設置LinearLayoutForListView為垂直布局,否者默認為水平布局,容易疏忽導致子項顯示不全 26 LinearLayoutForListView.this.setOrientation(LinearLayout.VERTICAL); 27 } 28 29 30 /** 31 * 此構造函數可以允許我們通過 XML的方式注冊 控件 32 * @param context 33 * @param attrs 34 */ 35 public LinearLayoutForListView(Context context, AttributeSet attrs) 36 { 37 super(context, attrs); 38 LinearLayoutForListView.this.setOrientation(LinearLayout.VERTICAL); 39 } 40 41 42 43 /** 44 * 設置適配器 45 * 46 * @param adpater 47 */ 48 public void setAdapter(BaseAdapter adpater) 49 { 50 this.adapter = adpater; 51 bindLinearLayout(); 52 } 53 54 /** 55 * 獲取適配器Adapter 56 * 57 * @return adapter 58 */ 59 public BaseAdapter getAdpater() 60 { 61 return adapter; 62 } 63 64 65 66 /** 67 * 綁定布局:將每個子項的視圖view添加進此線性布局LinearLayout中 68 */ 69 public void bindLinearLayout() 70 { 71 int count = adapter.getCount(); 72 for (int i = 0; i < count; i++) 73 { 74 View v = adapter.getView(i, null, null); 75 76 if (i != count - 1) 77 { //添加每項item之間的分割線 78 v = addLine(v); 79 } 80 addView(v, i); 81 } 82 setItemClickListener(); 83 Log.v("countTAG", "" + count); 84 } 85 86 /** 87 * 添加每項item之間的分割線 88 * 89 * @param view 90 * @return 91 */ 92 public View addLine(View view) 93 { 94 //分割線view 95 View lineView = new View(view.getContext()); 96 97 // 將數據從dip(即dp)轉換到px,第一參數為數據原單位(此為DIP),第二參數為要轉換的數據值 98 float fPx = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 99 (float) 0.5, view.getResources().getDisplayMetrics()); 100 int iPx = Math.round(fPx); 101 102 LayoutParams layoutParams = new LayoutParams( 103 LinearLayout.LayoutParams.MATCH_PARENT, iPx); 104 lineView.setLayoutParams(layoutParams); 105 lineView.setBackgroundColor(view.getSolidColor()); 106 107 LinearLayout ly = new LinearLayout(view.getContext()); 108 ly.setOrientation(LinearLayout.VERTICAL); 109 110 ly.addView(view); 111 ly.addView(lineView); 112 113 return ly; 114 } 115 116 117 /** 118 * 設置點擊子項事件監聽對象 119 * @param onItemClickListener 120 */ 121 public void setOnItemClickListener(OnItemClickListener onItemClickListener) 122 { 123 this.onItemClickListener = onItemClickListener; 124 setItemClickListener(); 125 } 126 127 /** 128 * 獲取點擊子項事件監聽對象 129 * @return 130 */ 131 public OnItemClickListener getOnItemClickListener() 132 { 133 return onItemClickListener; 134 } 135 136 137 /** 138 * 設置子項點擊事件 139 */ 140 private void setItemClickListener() 141 { 142 if (adapter != null) 143 { 144 for (int i = 0; i < LinearLayoutForListView.this.getChildCount(); i++) 145 { 146 View view = LinearLayoutForListView.this.getChildAt(i); 147 if (onItemClickListener != null) 148 { 149 //設置子項點擊事件 150 view.setOnClickListener(new ItemClickListener(view, i, adapter.getItemId(i))); 151 } 152 } 153 } 154 } 155 156 class ItemClickListener implements OnClickListener 157 { 158 View view; 159 int position; 160 long id; 161 162 public ItemClickListener(View view, int position, long id) 163 { 164 this.view = view; 165 this.position = position; 166 this.id = id; 167 } 168 169 @Override 170 public void onClick(View v) 171 { 172 //將子項視圖的點擊事件轉發到整個listview的OnItemClick事件中 173 //此方法有局限性,第一個參數 AdapterView<?> parent(即當前listView的視圖)沒傳入onItemClick()中 174 onItemClickListener.onItemClick(null, view, position, id); 175 } 176 } 177 }
在XML中使用自定義控件來調用LinearLayoutForListView
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" > <com.and.mine.LinearLayoutForListView android:id="@+id/list" android:layout_width="match_parent" android:layout_height="wrap_content" > </com.and.mine.LinearLayoutForListView> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="使用方法" /> </LinearLayout>
當然這種這種方法也是存在不足之處的,歡迎各位指正
轉載請注明出處:
http://www.goteny.com/articles/2013/11/8.html
http://www.cnblogs.com/zjjne/p/3428480.html
THE END