双向滚动ListView
因为最近一个项目的需求,写了一个双向的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 }
代码下载:https://files.cnblogs.com/group-06/BothwayListViewAPI.zip