`

scrollview与listview共存

 
阅读更多

最近因为项目的需要,要在一个 ScrollView 中放入一个ListView,虽然不推荐这样的设计,尽量不要让两者嵌套,但有时候还是要不得已而为之。发现 ScrollView中放入ListView后,后者的高度有问题,无论怎么设置高度,大约只显示一行半的高度,除非将ListView的高度设定死,但ListView高度根据数据的不同,高度肯定也不同,如果设置死的话滑动又成问题,想来,ListView本身应该具备滑动功能,两个具备滑动功能的控件嵌套在一起的话,可能就会出问题了吧,父容器可能将子控件的滑动事件覆盖掉了吧,再说,两个控件的高度都无法计算,所以不推荐嵌套在一起使用。

         解决思路也很简单, 就是在设置完ListView的Adapter后,根据ListView的子项目重新计算ListView的高度,然后把高度再作为LayoutParams设置给ListView,这样它的高度就正确了。代码如下:

public void setListViewHeightBasedOnChildren(ListView listView) {
		ListAdapter listAdapter = listView.getAdapter();
		if (listAdapter == null) {
			return;
		}

		int totalHeight = 0;
		for (int i = 0; i < listAdapter.getCount(); i++) {
			View listItem = listAdapter.getView(i, null, listView);
			listItem.measure(0, 0);
			totalHeight += listItem.getMeasuredHeight();
		}

		ViewGroup.LayoutParams params = listView.getLayoutParams();
		params.height = totalHeight
				+ (listView.getDividerHeight() * (listAdapter.getCount() - 1));
		((MarginLayoutParams) params).setMargins(10, 10, 10, 10);
		listView.setLayoutParams(params);
	}

 

         在设置ListView的Adapter后调用此方法即可让ListView正确的显示在 ScrollView中。但是要注意的是,ListView的每个Item必须是LinearLayout,不能是其他的,因为其他的Layout(如RelativeLayout)没有重写onMeasure(),所以会在onMeasure()时抛出异常。

 

 

解决办法二

重写ListView的onMeasure方法:

 

@Override 
    public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 

        int expandSpec = MeasureSpec.makeMeasureSpec( 
                Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST); 
        super.onMeasure(widthMeasureSpec, expandSpec); 
    } 

 

 

 

 

详细代码如下:

(1)方法一:

 

ListViewTest1Activity.java

 

 

package com.biao.listview;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.MarginLayoutParams;
import android.widget.ListAdapter;
import android.widget.ListView;


/**
 * 手工计算listview高度,再设置回去
 * 
 * @date 2014-5-5 下午4:34:57
 * @version V1.0
 */
public class ListViewTest1Activity extends Activity {
	
	
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.scrollview_listview_1);
		ListView listView = (ListView) findViewById(R.id.moreItemsListView);
		MyAdapter adapter = new MyAdapter(this, map());
		listView.setAdapter(adapter);
		setListViewHeightBasedOnChildren(listView);
	}

	
	/**
	 * 计算listview高度的方法
	 * @param listView
	 */
	public void setListViewHeightBasedOnChildren(ListView listView) {
		ListAdapter listAdapter = listView.getAdapter();
		if (listAdapter == null) {
			return;
		}

		int totalHeight = 0;
		for (int i = 0; i < listAdapter.getCount(); i++) {
			View listItem = listAdapter.getView(i, null, listView);
			listItem.measure(0, 0);
			totalHeight += listItem.getMeasuredHeight();
		}

		ViewGroup.LayoutParams params = listView.getLayoutParams();
		params.height = totalHeight
				+ (listView.getDividerHeight() * (listAdapter.getCount() - 1));
		((MarginLayoutParams) params).setMargins(10, 10, 10, 10);
		listView.setLayoutParams(params);
	}

	
	/**
	 * 测试数据
	 */
	private List<HashMap<String, String>> map() {
		List<HashMap<String, String>> data = new ArrayList<HashMap<String, String>>();

		for (int i = 0; i < 20; i++) {
			HashMap<String, String> map = new HashMap<String, String>();
			map.put("name", "测试" + i);
			data.add(map);
		}

		return data;
	}

}

 

 

scrollview_listview_1.xml

 

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="#FFF4F4F4"
    android:orientation="vertical" >

    <ScrollView
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:fadingEdge="none" >

        <LinearLayout
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:gravity="center_horizontal"
            android:orientation="vertical" >

            <ListView
                android:id="@+id/moreItemsListView"
                android:layout_width="fill_parent"
                android:layout_height="fill_parent"
                android:cacheColorHint="#00000000"
                android:divider="@null"
                android:dividerHeight="0.0dip"
                android:fadingEdge="none" />
        </LinearLayout>
    </ScrollView>

</LinearLayout>

 

 

 

(2)方法二:

ListViewTest2Activity.java

 

 

package com.biao.listview;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import android.app.Activity;
import android.os.Bundle;
import android.widget.ListView;


/**
 * 使用改写过的onMeasure的listview来重新计算listview高度
 * 
 * @date 2014-5-5 下午4:35:42
 * @version V1.0
 */
public class ListViewTest2Activity extends Activity {

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.scrollview_listview_2);
		ListView listView = (MyListView) findViewById(R.id.moreItemsListView);
		MyAdapter adapter = new MyAdapter(this, map());
		listView.setAdapter(adapter);
	}

	
	/**
	 * 测试数据
	 */
	private List<HashMap<String, String>> map() {
		List<HashMap<String, String>> data = new ArrayList<HashMap<String, String>>();
		
		for(int i = 0 ; i < 20 ; i++){
			HashMap<String, String> map = new HashMap<String, String>();
			map.put("name", "测试" + i);
			data.add(map);
		}
		
		return data;
	}

}

 

改写listview

MyListVew.java

 

package com.biao.listview;

import android.content.Context;
import android.util.AttributeSet;
import android.widget.ListView;


/**
 * 唯一有用的是改写了onMeasure,重新计算高度
 * 
 * @date 2014-5-5 下午4:46:12
 * @version V1.0
 */
public class MyListView extends ListView {

	public MyListView(Context context) {
		super(context);
	}

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

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

	/**
	 * 重写listview高度计算
	 * 
	 * 个人理解,widthMeasureSpec,heightMeasureSpec由父类传过来,这里将高度设置最大为Integer.MAX_VALUE/2的足够高的高度,
	 * 让listview可以完全展现出来,展现完后,再由父类包裹起来,那整个listview就可以展现出来了
	 * 
	 */
	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2	, MeasureSpec.AT_MOST);
		super.onMeasure(widthMeasureSpec, expandSpec);
	}
	
}

 

布局文件scrollview_listview_2.xml

 

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="#FFF4F4F4"
    android:orientation="vertical" >

    <ScrollView
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:fadingEdge="none" >

        <LinearLayout
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:gravity="center_horizontal"
            android:orientation="vertical" >

            <com.biao.listview.MyListView
                android:id="@+id/moreItemsListView"
                android:layout_width="fill_parent"
                android:layout_height="fill_parent"
                android:cacheColorHint="#00000000"
                android:divider="@null"
                android:dividerHeight="0.0dip"
                android:fadingEdge="none" />
        </LinearLayout>
    </ScrollView>

</LinearLayout>

 

效果图:

 

 

 

比较方便是重写onMeasure方式,这方式同样适用于scrollview嵌套gridview的情况。

 

 

代码见附件

 

  • 大小: 219.9 KB
分享到:
评论

相关推荐

    android中scrollview与listview共存

    总结来说,处理ScrollView和ListView共存的关键在于理解它们各自的特性和需求,合理设计布局,以及利用Android提供的API来协调滚动行为。通过学习和实践`ListViewTest`项目,你将能够掌握这些技巧,并在自己的应用中...

    scrollview与listview,viewpager共存

    本文将深入探讨如何正确地在Android应用中实现ScrollView与ListView、ViewPager的共存。 首先,我们来看ScrollView。ScrollView是一个可以包含多个子视图并允许用户滚动查看这些视图的容器。它通常用于包含内容过多...

    srollview与listview共存

    标题"ScrollView与ListView共存"涉及到的问题主要集中在如何在同一个界面中合理地结合这两个组件,同时避免出现UI冲突。描述中提到的“在setAdapter之前计算出ListView的宽高”,这是解决两者冲突的一个关键策略。 ...

    Android_ScrollView与ListView_GridView共存冲突解决方案

    总之,通过上述重写onMeasure方法的方式,可以解决Android中ScrollView与ListView或GridView嵌套导致的冲突问题。这种方法不仅适用于简单的嵌套,也能在数据量较大时保证应用的流畅性和用户体验。

    解决ListView 和 ScrollView 共存冲突的问题

    要解决ListView和ScrollView共存的冲突,有以下几种策略: 1. **嵌套ScrollView**: 可以尝试将ListView放在ScrollView中,但这不是最佳实践,因为ListView已经具备了自身的滚动功能。这种做法可能导致性能问题,...

    ScrollView中嵌套ListView,还可以嵌套多个listview 解决无法共存问题

    ScrollView中嵌套ListView,还可以嵌套多个listview 解决无法共存问题。放到项目中可以直接用

    ScrollView与ListView合用(正确计算Listview的高度)的问题解决

    在Android开发中,有时我们需要在一个页面中同时使用ScrollView和ListView,以便实现滚动效果并展示大量可...通过以上步骤,我们可以使ScrollView和ListView在同一个布局中和谐共存,确保ListView的显示效果符合预期。

    安卓listview相关相关-解决ScrollView里面嵌套ListVIew引起的高度和滚动问题.zip

    例如,你可以将ListView的部分内容转换为静态视图,或者使用RecycleView,它的滚动性能更好,也更容易与ScrollView协同工作。 4. **限制ListView的高度**:如果ListView的内容不多,可以设定一个固定高度,使其不会...

    Android圆角ListView并完美解决和ScrollView共存问题

    本文将深入探讨如何实现一个带有圆角的ListView,并解决其与ScrollView共存时可能出现的问题。 首先,实现圆角ListView的关键在于自定义ListView的背景。这可以通过创建一个自定义的Shape XML文件来完成,例如`...

    "ListView与ScrollView兼容性解决方案"

    在Android开发中,ListView与ScrollView的共存常引发显示问题,困扰不少开发者。本文分享两大常见解决方案:一是精准计算ListView总高度以适配;二是采用自定义LinearLayout方式绕过默认布局限制。两者均能有效缓解...

    Android滑动冲突的完美解决方案

    不同方向的滑动冲突可能出现在水平和垂直滑动共存的场景,如水平滑动的ViewPager与垂直滑动的ScrollView并存。解决这类冲突通常需要自定义视图组,通过重写`onInterceptTouchEvent()`和`onTouchEvent()`来判断滑动...

    Android开发滑动界面效果

    在实际开发中,可能会遇到多个滑动组件共存的情况,如ViewPager嵌套ScrollView,这时需要处理滑动冲突,确保用户的滑动意图能够被正确响应。 8. **自定义动画**: Android提供了丰富的动画API,如ObjectAnimator...

Global site tag (gtag.js) - Google Analytics