Android支持横行滚动的ListView控件
原帖地址:http://www.cnblogs.com/over140/archive/2011/12/07/2275207.html
聲明
歡迎轉載,但請保留文章原始出處:)?
博客園:http://www.cnblogs.com
農民伯伯: http://over140.cnblogs.com ?Android中文翻譯組:http://androidbox.sinaapp.com/
?
正文
一、本文目標
效果圖:
a). 支持ListView橫行滾動
b). 支持固定第一列
?
二、 實現代碼
2.1 Java類
自定義控件HVListView
/**?*?自定義支持橫向滾動的ListView
?*?@author?農民伯伯
?*
?*/
public?class?HVListView?extends?ListView?{
????/**?手勢?*/
????private?GestureDetector?mGesture;
????/**?列頭?*/
????public?LinearLayout?mListHead;
????/**?偏移坐標?*/
????private?int?mOffset?=?0;
????/**?屏幕寬度?*/
????private?int?screenWidth;
????/**?構造函數?*/
????public?HVListView(Context?context,?AttributeSet?attrs)?{
????????super(context,?attrs);
????????mGesture?=?new?GestureDetector(context,?mOnGesture);
????}
????/**?分發觸摸事件?*/
????@Override
????public?boolean?dispatchTouchEvent(MotionEvent?ev)?{
????????super.dispatchTouchEvent(ev);
????????return?mGesture.onTouchEvent(ev);
????}
????/**?手勢?*/
????private?OnGestureListener?mOnGesture?=?new?GestureDetector.SimpleOnGestureListener()?{
????????@Override
????????public?boolean?onDown(MotionEvent?e)?{
????????????return?true;
????????}
????????@Override
????????public?boolean?onFling(MotionEvent?e1,?MotionEvent?e2,?float?velocityX,
????????????????float?velocityY)?{
????????????return?false;
????????}
????????/**?滾動?*/
????????@Override
????????public?boolean?onScroll(MotionEvent?e1,?MotionEvent?e2,
????????????????float?distanceX,?float?distanceY)?{
????????????synchronized?(HVListView.this)?{
????????????????int?moveX?=?(int)?distanceX;
????????????????int?curX?=?mListHead.getScrollX();
????????????????int?scrollWidth?=?getWidth();
????????????????int?dx?=?moveX;
????????????????//控制越界問題
????????????????if?(curX?+?moveX?<?0)
????????????????????dx?=?0;
????????????????if?(curX?+?moveX?+?getScreenWidth()?>?scrollWidth)
????????????????????dx?=?scrollWidth?-?getScreenWidth()?-?curX;
????????????????mOffset?+=?dx;
????????????????//根據手勢滾動Item視圖
????????????????for?(int?i?=?0,?j?=?getChildCount();?i?<?j;?i++)?{
????????????????????View?child?=?((ViewGroup)?getChildAt(i)).getChildAt(1);
????????????????????if?(child.getScrollX()?!=?mOffset)
????????????????????????child.scrollTo(mOffset,?0);
????????????????}
????????????????mListHead.scrollBy(dx,?0);
????????????}
????????????requestLayout();
????????????return?true;
????????}
????};
????
????/**
?????*?獲取屏幕可見范圍內最大屏幕
?????*?@return
?????*/
????public?int?getScreenWidth()?{
????????if?(screenWidth?==?0)?{
????????????screenWidth?=?getContext().getResources().getDisplayMetrics().widthPixels;
????????????if?(getChildAt(0)?!=?null)?{
????????????????screenWidth?-=?((ViewGroup)?getChildAt(0)).getChildAt(0)
????????????????????????.getMeasuredWidth();
????????????}?else?if?(mListHead?!=?null)?{
????????????????//減去固定第一列
????????????????screenWidth?-=?mListHead.getChildAt(0).getMeasuredWidth();
????????????}
????????}
????????return?screenWidth;
????}
????/**?獲取列頭偏移量?*/
????public?int?getHeadScrollX()?{
????????return?mListHead.getScrollX();
????}
}
代碼說明:
自定義HVListView繼承自ListView,增加了橫向手勢監聽,并在橫向滾動時手動觸發Layout容器內的滾動。
Activity
public?class?TestHVListViewActivity?extends?Activity?{????private?LayoutInflater?mInflater;
????private?HVListView?mListView;
????/**?Called?when?the?activity?is?first?created.?*/
????@Override
????public?void?onCreate(Bundle?savedInstanceState)?{
????????super.onCreate(savedInstanceState);
????????setContentView(R.layout.main);
????????mListView?=?(HVListView)?findViewById(android.R.id.list);
????????//設置列頭
????????mListView.mListHead?=?(LinearLayout)?findViewById(R.id.head);
????????//設置數據
????????mListView.setAdapter(new?DataAdapter());
????????mInflater?=?(LayoutInflater)?getSystemService(LAYOUT_INFLATER_SERVICE);
????}
????private?class?DataAdapter?extends?BaseAdapter?{
????????@Override
????????public?int?getCount()?{
????????????return?50;//固定顯示50行數據
????????}
????????@Override
????????public?View?getView(int?position,?View?convertView,?ViewGroup?parent)?{
????????????if?(convertView?==?null)?{
????????????????convertView?=?mInflater.inflate(R.layout.item,?null);
????????????}
????????????for?(int?i?=?0;?i?<?8;?i++)?{
????????????????((TextView)?convertView.findViewById(R.id.item2?+?i)).setText("數據"?+?position?+?"行"?+?(i?+?2)?+?"列");
????????????}
????????????//校正(處理同時上下和左右滾動出現錯位情況)
????????????View?child?=?((ViewGroup)?convertView).getChildAt(1);
????????????int?head?=?mListView.getHeadScrollX();
????????????if?(child.getScrollX()?!=?head)?{
????????????????child.scrollTo(mListView.getHeadScrollX(),?0);
????????????}
????????????return?convertView;
????????}
????????@Override
????????public?Object?getItem(int?position)?{
????????????return?null;
????????}
????????@Override
????????public?long?getItemId(int?position)?{
????????????return?0;
????????}
????}
}
代碼說明:
為ListView提供了模擬數據。注意getView里面還有一段代碼是校驗,是專門處理同時橫向和縱向滾動出現錯位的情況。
2.2 XML文件
main.xml
<?xml?version="1.0"?encoding="utf-8"?><LinearLayout?xmlns:android="http://schemas.android.com/apk/res/android"
????android:orientation="vertical"?android:background="#eeffcc"
????android:layout_width="wrap_content"?android:layout_height="fill_parent">
????<include?layout="@layout/item"?/>
????<com.nmbb.HVListView?android:id="@android:id/list"
????????android:background="#FFB84D"?android:fastScrollEnabled="true"
????????android:fadingEdgeLength="0.0sp"?android:layout_width="1400.0dip"
????????android:layout_height="fill_parent"?android:drawSelectorOnTop="false"
????????android:cacheColorHint="@null"?android:dividerHeight="1.0dip">
????</com.nmbb.HVListView>
</LinearLayout>
代碼說明:
注意這里需要指定HVListView的layout_width為滑動范圍值,由item累加。
item.xml
<?xml?version="1.0"?encoding="utf-8"?><LinearLayout?xmlns:android="http://schemas.android.com/apk/res/android"
????android:orientation="horizontal"?android:layout_width="wrap_content"
????android:layout_height="wrap_content">
????<TextView?android:id="@+id/item1"?android:text="不動列頭1"
????????android:textSize="20.0sp"?android:gravity="center"
????????android:layout_width="100.0dip"?android:layout_height="wrap_content"></TextView>
????<LinearLayout?android:orientation="horizontal"?android:id="@+id/head"
????????android:layout_width="1200.0dip"?android:layout_height="wrap_content">
????????<TextView?android:id="@+id/item2"?android:text="不動列頭2"
????????????android:textColor="@android:color/black"?android:textSize="20.0sp"
????????????android:singleLine="true"?android:gravity="center"
????????????android:layout_width="150.0dip"?android:layout_height="wrap_content"></TextView>
????????<TextView?android:id="@+id/item3"?android:text="不動列頭3"
????????????android:textSize="20.0sp"?android:singleLine="true"?android:gravity="center"
????????????android:layout_width="150.0dip"?android:layout_height="wrap_content"></TextView>
????????<TextView?android:id="@+id/item4"?android:text="不動列頭4"
????????????android:textColor="@android:color/black"?android:textSize="20.0sp"
????????????android:singleLine="true"?android:gravity="center"
????????????android:layout_width="150.0dip"?android:layout_height="wrap_content"></TextView>
????????<TextView?android:id="@+id/item5"?android:text="不動列頭5"
????????????android:textSize="20.0sp"?android:singleLine="true"?android:gravity="center"
????????????android:layout_width="150.0dip"?android:layout_height="wrap_content"></TextView>
????????<TextView?android:id="@+id/item6"?android:text="不動列頭6"
????????????android:textColor="@android:color/black"?android:textSize="20.0sp"
????????????android:singleLine="true"?android:gravity="center"
????????????android:layout_width="150.0dip"?android:layout_height="wrap_content"></TextView>
????????<TextView?android:id="@+id/item7"?android:text="不動列頭7"
????????????android:textSize="20.0sp"?android:singleLine="true"?android:gravity="center"
????????????android:layout_width="150.0dip"?android:layout_height="wrap_content"></TextView>
????????<TextView?android:id="@+id/item8"?android:text="不動列頭8"
????????????android:textColor="@android:color/black"?android:textSize="20.0sp"
????????????android:singleLine="true"?android:gravity="center"
????????????android:layout_width="150.0dip"?android:layout_height="wrap_content"></TextView>
????????<TextView?android:id="@+id/item9"?android:text="不動列頭9"
????????????android:textSize="20.0sp"?android:singleLine="true"?android:gravity="center"
????????????android:layout_width="150.0dip"?android:layout_height="wrap_content"></TextView>
????</LinearLayout>
</LinearLayout>
?
代碼說明:
注意指定了每一個TextView的寬度為固定寬度,這樣表格看起來就比較整齊。
?
?
三、注意問題
從代碼看得出,本辦法只能算個笨辦法,能滿足基本需求,比較麻煩的是需要自己來指定固定寬度。在企業應用展示多行多列數據時還是非常有用的,比如炒股軟件也有這樣的需求。
特別提醒大家注意設置固定寬度,還需要把最外面的容器的寬度設置為warp_content,以便支持容器內能夠延伸。
當前不支持Fling操作,所以即使用力滑也不好滑太多,希望在后續版本改進。
?
四、代碼下載
TestHVListView2011-12-4.zip
?
五、擴展閱讀
Android提高第十五篇之ListView自適應實現表格
(不推薦這種做法,但有參考價值,里面網格也畫得很好)
Android Horizontal ListView
(實現較為復雜,但后續改進可以參考其實現,有很重要研究價值)
?
總結
以上是生活随笔為你收集整理的Android支持横行滚动的ListView控件的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Android中的Notificatio
- 下一篇: android抽屉实现不同之处