ListView实现带标题栏效果(附源码)
我的实现思路是重写一个LinearLayout,在里面放一个标题栏,再在下面放一个ListView存放数据 , 目前实现了文字列宽自动适应, 自动排版内容等功能 。
我把整个功能写成了一个类,在需要用的时候只需要new出这个类就可以直接使用了
该类目前的所有方法:
/** 初始化带标题ListView. */
CListView(Context, String[], List<String[]>)
/** 整体有改变时,刷新显示. */
definedSetChanged()
/** 设置选中时的监听器. */
setOnItemClickListener(OnItemClickListener)
/** 设置行背景颜色, 多个颜色可以作为间隔色. */
setItemBackgroundColor(int...)
/** 数据总数. */
getCount()
/** 当前选中数据. */
getItem(int)
/** 设置当前选中位置. */
setSelectedPosition(int)
/** 当前选中位置. */
getSelectedPosition()
/** 设置被选中时的背景色. */
setSelectedBackgroundColor(int)
/** 设置标题背景色. */
setTitleBackgroundColor(int)
/** 设置标题文字颜色. */
setTitleTextColor(int)
/** 设置内容文字颜色. */
setContentTextColor(int)
/** 设置标题字体大小. */
setTitleTextSize(float)
/** 设置内容字体大小. */
setContentTextSize(float)
/** 设定哪列自动列宽 从0开始计算. */
setAutoColumnWidth(int)
这是我的代码,希望各位如果有什么好的建议都提出来,或者大家对其有修改也希望发给我一份:
1 package cn.title.list; 2 3 import java.util.ArrayList; 4 import java.util.List; 5 6 import android.app.Activity; 7 import android.graphics.Color; 8 import android.os.Bundle; 9 import android.view.Menu; 10 import android.view.MenuItem; 11 import android.view.View; 12 import android.widget.AdapterView; 13 14 public class TitleListActivity extends Activity { 15 16 TListView t_listView; 17 List<String[]> list = new ArrayList<String[]>(); 18 19 public void onCreate(Bundle savedInstanceState) { 20 super.onCreate(savedInstanceState); 21 //setContentView(R.layout.main); 22 23 makeData(); 24 25 String[] title = new String[] { "ID", "标题2", "标题3", "标题4", "标题5" }; 26 27 t_listView = new TListView(this, title, list); 28 t_listView.setTitleTextColor(Color.GREEN); 29 t_listView.setTitleBackgroundColor(Color.RED); 30 // listView.setAutoColumnWidth(3); 31 // listView.setItemBackgroundColor(Color.GREEN, Color.WHITE); 32 t_listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { 33 34 35 public void onItemClick(AdapterView<?> parent, View view, int position, long id) { 36 String[] item = t_listView.getItem(position); 37 item[2] = "12312312312"; 38 t_listView.definedSetChanged(); 39 } 40 }); 41 42 // listView.definedSetChanged(); 43 44 setContentView(t_listView); 45 } 46 47 /* 48 * (non-Javadoc) 49 * 50 * @see android.app.Activity#onCreateOptionsMenu(android.view.Menu) 51 */ 52 53 public boolean onCreateOptionsMenu(Menu menu) { 54 menu.add(0, 0, 0, "测试修改选中行"); 55 return true; 56 } 57 58 /* 59 * (non-Javadoc) 60 * 61 * @see android.app.Activity#onOptionsItemSelected(android.view.MenuItem) 62 */ 63 64 public boolean onOptionsItemSelected(MenuItem item) { 65 switch (item.getItemId()) { 66 case 0: 67 t_listView.setSelectedPosition(32); 68 break; 69 } 70 return true; 71 } 72 73 private void makeData() { 74 list.add(new String[] { "1", "数据1.2", "数据1.3", "数据1.4" }); 75 list.add(new String[] { "2", "数据2.2", "数据2.3", "数据2.4", "数据2.5" }); 76 list.add(new String[] { "3", "数据3.2", "数据3.3", "数据3.4" }); 77 list.add(new String[] { "4", "数据4.2", "数据4.3", "数据4.4" }); 78 list.add(new String[] { "5", "数据5.2", "数据5.3", "数据5.4", "数据5.5" }); 79 list.add(new String[] { "6", "数据6.2", "数据6.3", "数据6.4" }); 80 list.add(new String[] { "7", "数据7.2", "数据7.3", "数据7.4", "数据7.5", "数据7.6" }); 81 list.add(new String[] { "8", "数据8.2", "数据8.3", "数据8.4" }); 82 list.add(new String[] { "9", "数据9.2", "数据9.3", "数据9.4" }); 83 list.add(new String[] { "10", "数据10.2", "数据10.3", "数据10.4", "数据10.5", "数据10.6", "数据10.7" }); 84 list.add(new String[] { "11", "数据11.2", "数据11.3", "数据11.4", "数据11.5" }); 85 list.add(new String[] { "12", "数据12.2", "数据12.3", "数据12.4", "数据12.5" }); 86 list.add(new String[] { "13", "数据13.2", "数据13.3", "数据13.4", "数据13.5" }); 87 list.add(new String[] { "14", "数据14.2", "数据14.3", "数据14.4", "数据14.5" }); 88 list.add(new String[] { "15", "数据15.2", "数据15.3", "数据15.4", "数据15.5" }); 89 list.add(new String[] { "16", "数据16.2", "数据16.3", "数据16.4", "数据16.5" }); 90 list.add(new String[] { "17", "数据17.2", "数据17.3", "数据17.4", "数据17.5" }); 91 list.add(new String[] { "18", "数据18.2", "数据18.3", "数据18.4", "数据18.5" }); 92 list.add(new String[] { "19", "数据19.2", "数据19.3", "数据19.4", "数据19.5" }); 93 list.add(new String[] { "20", "数据20.2", "数据20.3", "数据20.4", "数据20.5" }); 94 list.add(new String[] { "21", "数据21.2", "数据21.3", "数据21.4", "数据21.5" }); 95 list.add(new String[] { "22", "数据22.2", "数据22.3", "数据22.4", "数据22.5" }); 96 list.add(new String[] { "23", "数据23.2", "数据23.3", "数据23.4", "数据23.5" }); 97 list.add(new String[] { "24", "数据24.2", "数据24.3", "数据24.4", "数据24.5" }); 98 list.add(new String[] { "25", "数据25.2", "数据25.3", "数据25.4", "数据25.5" }); 99 list.add(new String[] { "26", "数据26.2" }); 100 list.add(new String[] { "27", "数据27.2", "数据27.3", "数据27.4", "数据27.5" }); 101 list.add(new String[] { "28", "数据28.2", "数据28.3", "数据28.4", "数据28.5" }); 102 list.add(new String[] { "29", "数据29.2", "数据29.3", "数据29.4", "数据29.5" }); 103 list.add(new String[] { "30", "数据12.2", "数据12.3", "数据12.4", "数据12.5" }); 104 list.add(new String[] { "31", "数据13.2", "数据13.3", "数据13.4", "数据13.5" }); 105 list.add(new String[] { "32", "数据14.2", "数据14.3", "数据14.4", "数据14.5" }); 106 list.add(new String[] { "33", "数据15.2", "数据15.3", "数据15.4", "数据15.5" }); 107 list.add(new String[] { "34", "数据16.2", "数据16.3", "数据16.4", "数据16.5" }); 108 list.add(new String[] { "35", "数据17.2", "数据17.3", "数据17.4", "数据17.5" }); 109 list.add(new String[] { "36", "数据18.2", "数据18.3" }); 110 list.add(new String[] { "37", "数据19.2", "数据19.3", "数据19.4", "数据19.5" }); 111 list.add(new String[] { "38", "数据20.2", "数据20.3", "数据20.4", "数据20.5" }); 112 list.add(new String[] { "39", "数据21.2", "数据21.3", "数据21.4", "数据21.5" }); 113 list.add(new String[] { "40", "数据22.2", "数据22.3", "数据22.4", "数据22.5" }); 114 list.add(new String[] { "41", "数据23.2", "数据23.3", "数据23.4", "数据23.5" }); 115 list.add(new String[] { "42", "数据24.2", "数据24.3", "数据24.4", "数据24.5" }); 116 list.add(new String[] { "43", "数据25.2", "数据25.3", "数据25.4", "数据25.5" }); 117 list.add(new String[] { "44", "数据26.2", "数据26.3", "数据26.4", "数据26.5" }); 118 list.add(new String[] { "45", "数据27.2", "数据27.3", "数据27.4", "数据27.5" }); 119 list.add(new String[] { "46", "数据28.2", "数据28.3", "数据28.4", "数据28.5" }); 120 list.add(new String[] { "47", "数据29.2", "数据29.3", "数据29.4", "数据29.5" }); 121 } 122 123 }
1 package cn.title.list; 2 3 import java.util.List; 4 5 import android.content.Context; 6 import android.graphics.Canvas; 7 import android.graphics.Color; 8 import android.graphics.Paint; 9 import android.view.Gravity; 10 import android.view.View; 11 import android.view.ViewGroup; 12 import android.widget.AdapterView; 13 import android.widget.BaseAdapter; 14 import android.widget.LinearLayout; 15 import android.widget.ListView; 16 import android.widget.TextView; 17 18 /** 19 * 标题ListView TListView 20 * @author 21 * 22 */ 23 public class TListView extends LinearLayout { 24 25 private static LayoutParams FILL_FILL_LAYOUTPARAMS = new LayoutParams(LayoutParams.FILL_PARENT, 26 LayoutParams.FILL_PARENT, 1); 27 private static LayoutParams WAP_WAP_LAYOUTPARAMS = new LayoutParams(LayoutParams.WRAP_CONTENT, 28 LayoutParams.WRAP_CONTENT); 29 30 private static Paint BLACK_PAINT = new Paint(); 31 private static Paint WHITE_PAINT = new Paint(); 32 static { 33 WHITE_PAINT.setColor(Color.WHITE); 34 BLACK_PAINT.setColor(Color.BLACK); 35 } 36 37 private CAdapter cAdapter; 38 39 /** 标题空间. */ 40 private LinearLayout titleLayout; 41 private String[] title; 42 43 private ListView listView; 44 /** 数据. */ 45 private List<String[]> data; 46 47 /** 列宽数据. */ 48 private int[] itemWidth; 49 50 /** 当前选中行. */ 51 private int selectedPosition = -1; 52 /** 自动列宽列. */ 53 private int autoWidthIndex = -1; 54 55 private AdapterView.OnItemClickListener onItemClickListener; 56 57 /** 行背景颜色. */ 58 private int[] rowsBackgroundColor; 59 /** 选中行背景颜色. */ 60 private int selectedBackgroundColor = Color.argb(200, 224, 243, 250); 61 /** 标题背景颜色. */ 62 private int titleBackgroundColor; 63 /** 标题字体颜色. */ 64 private int titleTextColor = Color.argb(255, 100, 100, 100); 65 /** 内容字体颜色. */ 66 private int contentTextColor = Color.argb(255, 100, 100, 100); 67 /** 标题字体大小. */ 68 private float titleTextSize = 0; 69 /** 内容字体大小. */ 70 private float contentTextSize = 0; 71 72 /** 73 * 初始化带标题ListView 74 * 75 * @param context 76 * 父级上下文 77 * @param title 78 * 标题数组 79 * @param data 80 * 内容列表 81 */ 82 public TListView(Context context, String[] title, List<String[]> data) { 83 super(context); 84 85 this.title = title; 86 this.data = data; 87 88 // 设定纵向布局 89 setOrientation(VERTICAL); 90 // 设定背景为白色 91 setBackgroundColor(Color.WHITE); 92 93 // 预先设定好每列的宽 94 this.itemWidth = new int[title.length]; 95 autoWidthIndex = this.itemWidth.length - 1; 96 // 计算列宽 97 calcColumnWidth(); 98 99 // 添加title位置 100 titleLayout = new LinearLayout(getContext()); 101 titleLayout.setBackgroundColor(Color.parseColor("#CCCCCC")); 102 addView(titleLayout); 103 // 绘制标题面板 104 drawTitleLayout(); 105 106 // 添加listview 107 listView = new ListView(getContext()); 108 listView.setPadding(0, 2, 0, 0); 109 cAdapter = new CAdapter(); 110 listView.setAdapter(cAdapter); 111 listView.setCacheColorHint(0); 112 listView.setLayoutParams(FILL_FILL_LAYOUTPARAMS); 113 listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { 114 115 116 public void onItemClick(AdapterView<?> parent, View view, int position, long id) { 117 if (onItemClickListener != null) 118 onItemClickListener.onItemClick(parent, view, position, id); 119 setSelectedPosition(position); 120 selectedPosition = position; 121 cAdapter.notifyDataSetChanged(); 122 } 123 }); 124 addView(listView); 125 } 126 127 /** 128 * 整体有改变时,刷新显示 129 */ 130 public void definedSetChanged() { 131 calcColumnWidth(); 132 drawTitleLayout(); 133 cAdapter.notifyDataSetChanged(); 134 } 135 136 /** 137 * 设置选中时的监听器 138 * 139 * @param onItemClickListener 140 */ 141 public void setOnItemClickListener(AdapterView.OnItemClickListener onItemClickListener) { 142 this.onItemClickListener = onItemClickListener; 143 } 144 145 /** 146 * 设置行背景颜色, 多个颜色可以作为间隔色 147 * 148 * @param color 149 * 行背景颜色,可以为多个 150 */ 151 public void setItemBackgroundColor(int... color) { 152 rowsBackgroundColor = color; 153 } 154 155 /** 156 * 数据总数 157 */ 158 public int getCount() { 159 if (data == null) 160 return 0; 161 return data.size(); 162 } 163 164 /** 165 * 当前选中数据 166 * 167 * @param position 168 * @return 169 */ 170 public String[] getItem(int position) { 171 if (data == null) 172 return null; 173 return data.get(position); 174 } 175 176 /** 177 * 设置当前选中位置 178 * 179 * @return 180 */ 181 public void setSelectedPosition(int selectedPosition) { 182 this.selectedPosition = selectedPosition; 183 } 184 185 /** 186 * 当前选中位置 187 * 188 * @return 189 */ 190 public int getSelectedPosition() { 191 return selectedPosition; 192 } 193 194 /** 195 * 设置被选中时的背景色 196 * 197 * @param color 198 */ 199 public void setSelectedBackgroundColor(int color) { 200 selectedBackgroundColor = color; 201 } 202 203 /** 204 * 设置标题背景色. 205 * @param color 206 */ 207 public void setTitleBackgroundColor(int color) { 208 titleBackgroundColor = color; 209 titleLayout.setBackgroundColor(titleBackgroundColor); 210 } 211 212 /** 213 * 设置标题文字颜色 214 * 215 * @param color 216 */ 217 public void setTitleTextColor(int color) { 218 titleTextColor = color; 219 for (int i = 0; i < titleLayout.getChildCount(); i++) { 220 ((TextView) titleLayout.getChildAt(i)).setTextColor(titleTextColor); 221 } 222 } 223 224 /** 225 * 设置内容文字颜色 226 * 227 * @param color 228 */ 229 public void setContentTextColor(int color) { 230 contentTextColor = color; 231 } 232 233 /** 234 * 设置标题字体大小 235 * 236 * @param szie 237 */ 238 public void setTitleTextSize(float szie) { 239 titleTextSize = szie; 240 } 241 242 /** 243 * 设置内容字体大小 244 * 245 * @param szie 246 */ 247 public void setContentTextSize(float szie) { 248 contentTextSize = szie; 249 } 250 251 /** 252 * 253 * 设定哪列自动列宽 从0开始计算 254 * 255 * @param index 256 */ 257 public void setAutoColumnWidth(int index) { 258 autoWidthIndex = index; 259 for (int i = 0; i < titleLayout.getChildCount(); i++) { 260 TextView tv = ((TextView) titleLayout.getChildAt(i)); 261 if (i == autoWidthIndex) 262 tv.setLayoutParams(FILL_FILL_LAYOUTPARAMS); 263 else { 264 tv.setLayoutParams(WAP_WAP_LAYOUTPARAMS); 265 tv.setWidth(itemWidth[i]); 266 } 267 } 268 } 269 270 /** 271 * 绘制标题 272 */ 273 private void drawTitleLayout() { 274 titleLayout.removeAllViews(); 275 for (int i = 0; i < title.length; i++) { 276 TextView tv = new CTextView(titleLayout.getContext()); 277 tv.setTextColor(titleTextColor); 278 tv.setGravity(Gravity.CENTER); 279 tv.setText(title[i]); 280 if (titleTextSize > 0) { 281 tv.setTextSize(titleTextSize); 282 } 283 tv.setPadding(5, 0, 5, 0); 284 if (i == autoWidthIndex) 285 tv.setLayoutParams(TListView.FILL_FILL_LAYOUTPARAMS); 286 else { 287 tv.setWidth(itemWidth[i]); 288 } 289 titleLayout.addView(tv); 290 } 291 } 292 293 /** 294 * 计算列宽 295 * 296 * @return 是否有改动 297 */ 298 private boolean calcColumnWidth() { 299 boolean result = false; 300 301 float textSize = new TextView(getContext()).getTextSize(); 302 303 // 计算标题列宽 304 for (int i = 0; i < itemWidth.length; i++) { 305 int w = (int) TListView.GetPixelByText((titleTextSize > 0) ? titleTextSize : textSize, title[i]); 306 if (itemWidth[i] < w) { 307 itemWidth[i] = w; 308 result = true; 309 } 310 } 311 312 // 计算内容列宽 313 if (contentTextSize > 0) { 314 textSize = contentTextSize; 315 } 316 for (int i = 0; i < data.size(); i++) { 317 for (int j = 0; j < itemWidth.length && j < data.get(i).length; j++) { 318 int w = (int) TListView.GetPixelByText(textSize, data.get(i)[j]); 319 if (itemWidth[j] < w) { 320 itemWidth[j] = w; 321 result = true; 322 } 323 } 324 } 325 return result; 326 } 327 328 /** 329 * 计算字符串所占像素 330 * 331 * @param textSize 332 * 字体大小 333 * @param text 334 * 字符串 335 * @return 字符串所占像素 336 */ 337 private static int GetPixelByText(float textSize, String text) { 338 Paint mTextPaint = new Paint(); 339 mTextPaint.setTextSize(textSize); // 指定字体大小 340 mTextPaint.setFakeBoldText(true); // 粗体 341 mTextPaint.setAntiAlias(true); // 非锯齿效果 342 343 return (int) (mTextPaint.measureText(text) + textSize); 344 } 345 346 /** 347 * 主要用的Adapter 348 * 349 * @author Cdisk 350 * 351 */ 352 class CAdapter extends BaseAdapter { 353 354 /* 355 * (non-Javadoc) 356 * 357 * @see android.widget.Adapter#getCount() 358 */ 359 360 public int getCount() { 361 if (data == null) 362 return 0; 363 return data.size(); 364 } 365 366 /* 367 * (non-Javadoc) 368 * 369 * @see android.widget.Adapter#getItem(int) 370 */ 371 372 public Object getItem(int position) { 373 if (data == null) 374 return null; 375 return data.get(position); 376 } 377 378 /* 379 * (non-Javadoc) 380 * 381 * @see android.widget.Adapter#getItemId(int) 382 */ 383 384 public long getItemId(int position) { 385 return 0; 386 } 387 388 /* 389 * (non-Javadoc) 390 * 391 * @see android.widget.Adapter#getView(int, android.view.View, android.view.ViewGroup) 392 */ 393 394 public View getView(int position, View convertView, ViewGroup parent) { 395 396 // 初始化主layout 397 LinearLayout contextLayout = new LinearLayout(TListView.this.getContext()); 398 399 String[] dataItem = data.get(position); 400 401 if (getSelectedPosition() == position) { // 为当前选中行 402 contextLayout.setBackgroundColor(selectedBackgroundColor); 403 } else if (rowsBackgroundColor != null && rowsBackgroundColor.length > 0) { 404 contextLayout.setBackgroundColor(rowsBackgroundColor[position % rowsBackgroundColor.length]); 405 } 406 407 for (int i = 0; i < title.length; i++) { 408 TextView tv = new CTextView(contextLayout.getContext()); 409 tv.setTextColor(contentTextColor); 410 tv.setGravity(Gravity.CENTER); 411 if (i < dataItem.length) { 412 tv.setText(dataItem[i]); 413 } 414 if (i == autoWidthIndex) 415 tv.setLayoutParams(TListView.FILL_FILL_LAYOUTPARAMS); 416 else { 417 tv.setWidth(itemWidth[i]); 418 } 419 if (contentTextSize > 0) { 420 tv.setTextSize(contentTextSize); 421 } 422 contextLayout.addView(tv); 423 } 424 425 return contextLayout; 426 } 427 428 } 429 430 /** 431 * 重写的TextView 432 * 433 * @author Cdisk 434 */ 435 class CTextView extends TextView { 436 437 438 protected void onDraw(Canvas canvas) { 439 super.onDraw(canvas); 440 // Top 441 canvas.drawLine(0, 0, this.getWidth() - 1, 0, WHITE_PAINT); 442 // Left 443 canvas.drawLine(0, 0, 0, this.getHeight() - 1, WHITE_PAINT); 444 // Right 445 canvas.drawLine(this.getWidth() - 1, 0, this.getWidth() - 1, this.getHeight() - 1, BLACK_PAINT); 446 // Buttom 447 canvas.drawLine(0, this.getHeight() - 1, this.getWidth() - 1, this.getHeight() - 1, BLACK_PAINT); 448 } 449 450 public CTextView(Context context) { 451 super(context); 452 } 453 } 454 455 } 456 457
main.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" > <!-- <HorizontalScrollView android:id="@+id/HorizontalScrollView01" android:layout_height="fill_parent" android:layout_width="fill_parent" android:layout_weight="1" android:fillViewport="true"> <LinearLayout android:id="@+id/LinearLayout01" android:layout_height="fill_parent" android:layout_width="fill_parent"><ListView android:id="@+id/listView" android:layout_width="fill_parent" android:layout_height="fill_parent"> </ListView></LinearLayout> </HorizontalScrollView> --> <ListView android:id="@+id/listView" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="1" > </ListView> <Button android:id="@+id/btnImport" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_weight="0" android:text="导入" > </Button> </LinearLayout>
源码下载: