因為最近一個項目的需求,寫了一個雙向的ListView.
主要的原因的需要顯示的數據量大,屏幕放不下,所以需要滾動來顯示.在這個基礎上還需要是ListView的上側和左側的部分保持相對的不滾動.其實上下的滾動系統的ListView自己就可以完成,但是橫向的滾動該如何實現呢,尤其是要在縱向的滾動的同時要兼顧左右的滾動.開始的時候沒有什么思路,后來也上網查了很多.其中一種的實現思路是在ListView中放置HorizontalScrollView,然后使用dispathTouchEvent方法來分發對滑動事件的響應.然后我也這樣做了,但是總不理想,可能是自己的考慮不周到,事件的響應經常會出問題,然后會導致ListView的每一個Item出現不同不的問題.
甚至還試過在左側放置ListView,右側放置HorizontalScrollView,然后在右側的ScrollView里面在放置一個ListView,然后通過事件分發,是左右兩側的ListView上下滾動的時候保持同步,但是總是會出現左右不同步的現象,這樣是不行的,即使出現一點的不同步,整個View看起來也會很怪,這樣是不能用的.
還有一種思路就是在ListView上層就屏蔽滑動事件,然后使ListView自動響應滾動事件,並同時手工的移動每一個ScrollView.也就是我這里使用的方法.經過測試,這個方法是可行的.並且達到了很好的同步效果.
想到一直以來都是從網上拿東西,也應該有貢獻精神.所以這里把代碼共享,本人盡量的屏蔽了實現的細節.以下提供API,希望對大家有幫助.
附圖:

以下代碼屬本人原創,轉載請注明出處.
API使用方法:
 
 
- 要使用雙向ListView需要拷貝以下類文件到項目中:
 
├─adapter
│ BothwayListViewAdapter.java(BothwayListView的Adapter)
│
└─widget
BothwayListView.java(要使用的ListView)
HeaderHorizontalScrollView.java(Header和Item中能夠滑動的部分的上層View)
InterceptLinearLayout.java(HeaderHorizontalScrollView的上層View)
- 建立相應的Layout文件.
 
雙向滾動的ListView需要有Header.應該與ListView在同一層次放置,並且其結構應該與Item的結構保持一致,即左側不可以滑動的位置的寬度,右側可以滾動的View的結構等.推薦直接在ListView上面直接include一個Item的View.這樣其結構就會和Item保持完全一致.
例:
(main:)
1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 xmlns:tools="http://schemas.android.com/tools" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent" 5 android:orientation="vertical" > 6 <!--這里是Header部分,就是在ListView上部不會隨ListView的Item上下滑動的部分. 7 這里直接導入一個Item使用--> 8 <include 9 android:id="@+id/top_header" 10 layout="@layout/item" > 11 </include> 12 <!—-這里是今天的重點,ListView--> 13 <com.group_06.bothwaylistviewapi.widget.BothwayListView 14 android:id="@+id/main_listview" 15 android:layout_width="match_parent" 16 android:layout_height="match_parent" > 17 </com.group_06.bothwaylistviewapi.widget.BothwayListView> 18 </LinearLayout>
(item:)
1 <?xml version="1.0" encoding="utf-8"?> 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 android:layout_width="match_parent" 4 android:layout_height="50dp" 5 android:gravity="center" 6 android:orientation="horizontal" > 7 <!--這個TextView就是每一個Item的左側不會左右滑動的部分.--> 8 <TextView 9 android:layout_width="100dp" 10 android:layout_height="match_parent" 11 android:gravity="center" 12 android:text="LEFT_SIDE" /> 13 <!--以下是Item中可以左右滑動的部分,外層的InterceptLinearLayout是用來 14 屏蔽滑動事件的,即下面的HorizontalScrollView不會自動的跟隨用戶的滑動事件 15 滾動,他們的滾動都是由代碼中手工移動的.--> 16 <com.group_06.bothwaylistviewapi.widget.InterceptLinearLayout 17 android:id="@+id/top_linearlayout" 18 android:layout_width="wrap_content" 19 android:layout_height="match_parent" > 20 <!--這是HorizontalScrollView,左右滾動全靠它.--> 21 <com.group_06.bothwaylistviewapi.widget.HeaderHorizontalScrollView 22 android:id="@+id/my_scrollview" 23 android:layout_width="wrap_content" 24 android:layout_height="match_parent" 25 android:scrollbars="none" > 26 <LinearLayout 27 android:layout_width="wrap_content" 28 android:layout_height="match_parent" 29 android:orientation="horizontal" > 30 <TextView 31 android:layout_width="50dp" 32 android:layout_height="match_parent" 33 android:text="AAAA" /> 34 <TextView 35 android:layout_width="50dp" 36 android:layout_height="match_parent" 37 android:text="BBBB" /> 38 39 .. .. .. .. .. .. .. .. 40 41 <TextView 42 android:layout_width="50dp" 43 android:layout_height="match_parent" 44 android:text="HHHH" /> 45 </LinearLayout> 46 </com.group_06.bothwaylistviewapi.widget.HeaderHorizontalScrollView> 47 </com.group_06.bothwaylistviewapi.widget.InterceptLinearLayout> 48 </LinearLayout>
- Java代碼:
 
1 public class MainActivity extends Activity 2 { 3 private View mTopParentLinearLayout; 4 private HeaderHorizontalScrollView mTopScrollView; 5 private BothwayListView mBothwayListView; 6 private BothwayListViewAdapter mBothwayListViewAdapter; 7 8 @Override 9 public void onCreate(Bundle savedInstanceState) 10 { 11 super.onCreate(savedInstanceState); 12 setContentView(R.layout.activity_main); 13 initViews(); 14 } 15 private void initViews() 16 { 17 mTopParentLinearLayout = (View) findViewById(R.id.top_header); 18 mTopScrollView = (HeaderHorizontalScrollView) mTopParentLinearLayout 19 .findViewById(R.id.my_scrollview); 20 mBothwayListView = (BothwayListView) findViewById(R.id.main_listview); 21 mBothwayListView.initListView(mTopParentLinearLayout, mTopScrollView); 22 mBothwayListViewAdapter = new MyAdapter(MainActivity.this, 23 mTopScrollView); 24 mBothwayListView.setAdapter(mBothwayListViewAdapter); 25 } 26 @Override 27 protected void onDestroy() 28 { 29 if (null != mBothwayListView) 30 { 31 mBothwayListView.unRegisterReceiver(); 32 } 33 super.onDestroy(); 34 } 35 }
- HorizontalScrollView的Adapter:
 
Adapter中只有這個方法不同,即需要多返回一個ScrollView,即每一個Item中的HorizontalScrollView.若ConvertView不為空時,即重用之前的Item時,可以將Item的ScrollView設為null傳回.
1 @Override 2 public ConvertViewAndScrollView getFullView(int position, View convertView, 3 ViewGroup parent) 4 { 5 if (convertView == null) 6 { 7 convertView = inflater.inflate(R.layout.item, null, false); 8 ...... 9 HorizontalScrollView scrollView = (HorizontalScrollView) convertView 10 .findViewById(R.id.my_scrollview); 11 return new ConvertViewAndScrollView(convertView, scrollView); 12 } 13 ...... 14 return new ConvertViewAndScrollView(convertView, null); 15 }
代碼下載:http://files.cnblogs.com/group-06/BothwayListViewAPI.zip
