在实际项目中发现一个界面中需要两个listview,同时当第一个listview1滚动完成后需要自然的滚动到listview2中,看上去就像一个listview一样,于是自己想到的就是一个scrollview中嵌套连个listview
<ScrollView
android:id="@+id/scroller"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ListView
android:id="@+id/listview1"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<ListView
android:id="@+id/listview2"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
</ScrollView>
当然你知道的,listview显示不全,同时和scrollview造成滑动冲突!
经过思考总结下面的解决方案:
- 因为scrollview的问题,所以需要手动设定listview的高度。
- 在listview1滑动到底部时需要屏蔽listview1的滑动,让scrollview滑动。
- 在listview2滑动到顶部时屏蔽listview2的滑动,让scrollview滑动。
- 在scrollview滚动中,屏蔽listview的滚动。
这里定义了连个view,MyScrollview和MyListView。先看整体布局
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.xuzong.imdemo.MainActivity">
<com.example.xuzong.imdemo.MyScrollView
android:id="@+id/scroller"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.example.xuzong.imdemo.MyListView
android:id="@+id/listview1"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<com.example.xuzong.imdemo.MyListView
android:id="@+id/listview2"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
</com.example.xuzong.imdemo.MyScrollView>
</RelativeLayout>
Mylistview代码
public class MyListView extends ListView {
private ScrollView scrollView;
private boolean notAllowParentScroll = true;
public void setNotAllowParentScroll(boolean notAllowParentScroll) {
this.notAllowParentScroll = notAllowParentScroll;
}
public void setScrollView(ScrollView scrollView) {
this.scrollView = scrollView;
}
public MyListView(Context context) {
super(context);
}
public MyListView(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
if(notAllowParentScroll){
switch(event.getAction()){
case MotionEvent.ACTION_DOWN:
scrollView.requestDisallowInterceptTouchEvent(true);
break;
case MotionEvent.ACTION_UP:
scrollView.requestDisallowInterceptTouchEvent(false);
break;
}
}
return super.dispatchTouchEvent(event);
}
}
MyAdapter代码
public class MyAdapter extends BaseAdapter {
private List<String> list;
private LayoutInflater inflater;
private Context ctx;
public MyAdapter(List<String> list, Context ctx) {
this.list = list;
this.ctx = ctx;
inflater =LayoutInflater.from(ctx);
}
@Override
public int getCount() {
return list.size();
}
@Override
public Object getItem(int position) {
return list.get(position);
}
@Override
public long getItemId(int position) {
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if(convertView==null){
convertView = inflater.inflate(R.layout.item_view,parent,false);
holder = new ViewHolder();
holder.tv = (TextView) convertView.findViewById(R.id.tv);
convertView.setTag(holder);
}else{
holder = (ViewHolder) convertView.getTag();
}
holder.tv.setText(list.get(position));
return convertView;
}
class ViewHolder{
public TextView tv;
}
}
MyScrollview代码
public class MyScrollView extends ScrollView {
public MyScrollView(Context context) {
super(context);
}
public MyScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
}
private ScrollViewListener scrollViewListener = null;
public void setScrollViewListener(ScrollViewListener scrollViewListener) {
this.scrollViewListener = scrollViewListener;
}
private boolean allowChildViewScroll = true;
public void setAllowChildViewScroll(boolean allowChildViewScroll) {
this.allowChildViewScroll = allowChildViewScroll;
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
if(!allowChildViewScroll){
return true;
}
return super.onInterceptTouchEvent(ev);
}
@Override
protected void onScrollChanged(int x, int y, int oldx, int oldy) {
super.onScrollChanged(x, y, oldx, oldy);
if (scrollViewListener != null) {
scrollViewListener.onScrollChanged(this, x, y, oldx, oldy);
}
}
}
public interface ScrollViewListener {
void onScrollChanged(ScrollView scrollView,int x, int y, int oldx, int oldy);
}
MainActivity代码
public class MainActivity extends AppCompatActivity implements View.OnTouchListener {
private RelativeLayout main;
private MyScrollView scroller;
private MyListView listview1, listview2;
private MyAdapter adapter1, adapter2;
private boolean listview1Scroll = true;
private boolean listview2Scroll = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
main = (RelativeLayout) findViewById(R.id.main);
scroller = (MyScrollView) findViewById(R.id.scroller);
scroller.setOnTouchListener(this);
listview1 = (MyListView) findViewById(R.id.listview1);
adapter1 = getAdapter("s1");
listview1.setAdapter(adapter1);
listview1.setScrollView(scroller);
listview2 = (MyListView) findViewById(R.id.listview2);
adapter2 = getAdapter("s2222222222222");
listview2.setAdapter(adapter2);
listview2.setScrollView(scroller);
listview1.setOnScrollListener(new AbsListView.OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
switch (scrollState) {
case AbsListView.OnScrollListener.SCROLL_STATE_IDLE:
// 判断滚动到底部,scrollview滚动,listview1滚动屏蔽
if (view.getLastVisiblePosition() == (view.getCount() - 1)) {
listview1.setNotAllowParentScroll(false);
scroller.setAllowChildViewScroll(false);
}
break;
}
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
}
});
listview2.setOnScrollListener(new AbsListView.OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
switch (scrollState) {
case AbsListView.OnScrollListener.SCROLL_STATE_IDLE:
// 判断滚动到顶部,listview2开始滚动,scrollview滚动屏蔽
if (view.getFirstVisiblePosition() == 0) {
scroller.setAllowChildViewScroll(false);
listview2.setNotAllowParentScroll(false);
scroller.requestDisallowInterceptTouchEvent(true);
}
break;
}
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
}
});
scroller.setScrollViewListener(new ScrollViewListener() {
@Override
public void onScrollChanged(ScrollView scrollView, int x, int y, int oldx, int oldy) {
int[] listview2location = new int[2];
listview2.getLocationOnScreen(listview2location);
int[] location1 = new int[2];
scroller.getLocationOnScreen(location1);
//在scrollview滚动过程中,如果listview2正好填满整个屏幕,此时需要屏蔽scrollview的滚动
if (listview2location[1] == location1[1]) {
listview2.setNotAllowParentScroll(true);
scroller.setAllowChildViewScroll(true);
return;
}
int[] listview1location = new int[2];
listview1.getLocationOnScreen(listview1location);
//在scrollview滚动过程中,如果listview1正好填满整个屏幕,此时需要屏蔽scrollview的滚动
if (listview1location[1] == location1[1]) {
scroller.setAllowChildViewScroll(true);
listview1.setNotAllowParentScroll(true);
return;
}
//在scrollview滚动过程中,屏蔽listview的滚动
scroller.setAllowChildViewScroll(false);
}
});
main.post(new Runnable() {
@Override
public void run() {
//设置listview1的高度
LinearLayout.LayoutParams layoutParams1 = (LinearLayout.LayoutParams) listview1.getLayoutParams();
layoutParams1.height = main.getHeight();
listview1.setLayoutParams(layoutParams1);
//设置listview2的高度
LinearLayout.LayoutParams layoutParams2 = (LinearLayout.LayoutParams) listview2.getLayoutParams();
layoutParams2.height = main.getHeight();
listview2.setLayoutParams(layoutParams2);
}
});
}
@Override
public boolean onTouch(View v, MotionEvent event) {
//屏蔽listview的滚动造成listview
switch(event.getAction()){
case MotionEvent.ACTION_DOWN:
scroller.setAllowChildViewScroll(false);
break;
case MotionEvent.ACTION_UP:
scroller.setAllowChildViewScroll(true);
break;
}
return false;
}
private MyAdapter getAdapter(String str) {
List<String> list = new ArrayList<>();
for (int i = 0; i < 20; i++) {
list.add(str);
}
return new MyAdapter(list, this);
}
}