您的位置:首页 > 其它

自定义ListView,解决ScrollView中嵌套ListView的问题

2016-12-03 21:31 260 查看
在项目开发中我们经常会遇到在ScrollView中嵌套ListView的情况,我参考了网上的一些大神的方法,自己在这里总结一下,并贴出代码供以后方便学习与使用。

首先自定义一个ListView:

MyListView.java

package com.xbmu.snl;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.ListView;

/**
*  自定义ListView,完美解决ScrollView嵌套ListView
* Created by bitaotao on 2016/12/3.
*/

public class MyListView extends ListView {

private static final String TAG = "MyListView";
public MyListView(Context context) {
super(context);
}

public MyListView(Context context, AttributeSet attrs) {
super(context, attrs);
}

public MyListView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int defaultSize = measureHight(Integer.MAX_VALUE >> 2,heightMeasureSpec);
int expandSpec = MeasureSpec.makeMeasureSpec(defaultSize, MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, expandSpec);
}

/**
* 测量高度
* @param size
* @param heightMeasureSpec
* @return
*/
private int measureHight(int size, int heightMeasureSpec) {
int result = 0;
int specMode = MeasureSpec.getMode(heightMeasureSpec);
int specSize = MeasureSpec.getSize(heightMeasureSpec);
if(specMode == MeasureSpec.EXACTLY){
Log.d(TAG,"exactly");
result = specSize;
}else{
result = size;//最小值是200px,自己设定
if(specMode == MeasureSpec.AT_MOST){
result = Math.min(result,specSize);
}
Log.d(TAG,"specMode:"+specMode+"---result:"+result);
}
return  result;
}

/**
* 判断该ListView是否滑到低端了
* @return
*/
public boolean isBottom(){
int firstVisibleItem = getFirstVisiblePosition();//屏幕上显示的第一条是ListView中的第几条
int childCount = getChildCount();//屏幕上显示多少条item
int totalItemCount = getCount();//一共有多少条
if((firstVisibleItem + childCount) >= totalItemCount){
return  true;
}else{
return  false;
}
}

public boolean isTop(){
int firstVisibleItem = getFirstVisiblePosition();
if(firstVisibleItem == 0){
return true;
}else{
return  false;
}
}
float down = 0;
float y;
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
switch (ev.getAction()){
case MotionEvent.ACTION_DOWN:

down = ev.getRawY();
getParent().requestDisallowInterceptTouchEvent(true);

break;
case MotionEvent.ACTION_MOVE:
y = ev.getRawY();
if(isTop()){
if(y - down > 1){
//到顶端,向下滑动把事件交给父类
getParent().requestDisallowInterceptTouchEvent(false);
}else {
//到顶端,向上滑动把事件拦截,由自己处理
getParent().requestDisallowInterceptTouchEvent(true);
}
}

if(isBottom()){
if(y - down > 1){
//到底端,向下滑动把事件拦截,由自己处理
getParent().requestDisallowInterceptTouchEvent(true);
}else{
//到底端,向上滑动,把事件交给父类
getParent().requestDisallowInterceptTouchEvent(false);
}
}
break;
}
return super.dispatchTouchEvent(ev);
}
}

接下来,我在MainActivity中使用

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:background="@color/colorPrimary">

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="@dimen/activity_horizontal_margin"
android:text="Hello World!"
android:textSize="30sp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="@dimen/activity_horizontal_margin"
android:text="Hello World!"
android:textSize="30sp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="@dimen/activity_horizontal_margin"
android:text="Hello World!"
android:textSize="30sp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="@dimen/activity_horizontal_margin"
android:text="Hello World!"
android:textSize="30sp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="@dimen/activity_horizontal_margin"
android:text="Hello World!"
android:textSize="30sp"/>

<com.xbmu.snl.MyListView
android:layout_width="wrap_content"
android:layout_height="400dp"
android:id="@+id/id_mylistview"
android:background="@color/colorAccent">

</com.xbmu.snl.MyListView>

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="@dimen/activity_horizontal_margin"
android:text="Hello World!"
android:textSize="30sp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="@dimen/activity_horizontal_margin"
android:text="Hello World!"
android:textSize="30sp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="@dimen/activity_horizontal_margin"
android:text="Hello World!"
android:textSize="30sp"/>

</LinearLayout>
</ScrollView>

MainActivity.java

package com.xbmu.snl;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.ArrayAdapter;

import java.util.ArrayList;

public class MainActivity extends AppCompatActivity {

private MyListView myListView;
private ArrayList<String> data = new ArrayList<>();

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
adddata();
myListView = (MyListView) findViewById(R.id.id_mylistview);
ArrayAdapter<String> adapter = new ArrayAdapter<>(getApplicationContext(), android.R.layout.simple_expandable_list_item_1, data);
myListView.setAdapter(adapter);
}

private void adddata() {
for (int i = 0; i < 100; i++) {
data.add("第" + i + "项");
}
}
}


同时网上还有另外一种解决方法,代码下载地址:事件分发机制解决解决ScollView中嵌套ListView的问题
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: