直接在scrollView中写listview等可滚动控件会出现子控件高度计算的问题,为了解决这个问题,找到的方案是重写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);
}

但是这样造成的问题是listview会显示出所有的内容,如果listview的数量有100条,那么就很酸爽了.其实说到底还是listview不能滚动,只要让listview可以滚动,问题可以完美解决.

    @Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// Sets up mListPadding
super.onMeasure(widthMeasureSpec, heightMeasureSpec); final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);

     ....
if (heightMode == MeasureSpec.AT_MOST) {
// TODO: after first layout we should maybe start at the first visible position, not 0
heightSize = measureHeightOfChildren(widthMeasureSpec, 0, NO_POSITION, heightSize, -1);
} setMeasuredDimension(widthSize, heightSize); mWidthMeasureSpec = widthMeasureSpec;
}

再来看看measureHeightOfChildren是怎么实现的

    final int measureHeightOfChildren(int widthMeasureSpec, int startPosition, int endPosition,
int maxHeight, int disallowPartialChildPosition) {
final ListAdapter adapter = mAdapter;
if (adapter == null) {
return mListPadding.top + mListPadding.bottom;
} // Include the padding of the list
int returnedHeight = mListPadding.top + mListPadding.bottom;
final int dividerHeight = ((mDividerHeight > 0) && mDivider != null) ? mDividerHeight : 0;
// The previous height value that was less than maxHeight and contained
// no partial children
int prevHeightWithoutPartialChild = 0;
int i;
View child; // mItemCount - 1 since endPosition parameter is inclusive
endPosition = (endPosition == NO_POSITION) ? adapter.getCount() - 1 : endPosition;
final AbsListView.RecycleBin recycleBin = mRecycler;
final boolean recyle = recycleOnMeasure();
final boolean[] isScrap = mIsScrap; for (i = startPosition; i <= endPosition; ++i) {
child = obtainView(i, isScrap); measureScrapChild(child, i, widthMeasureSpec, maxHeight); if (i > 0) {
// Count the divider for all but one child
returnedHeight += dividerHeight;
} // Recycle the view before we possibly return from the method
if (recyle && recycleBin.shouldRecycleViewType(
((LayoutParams) child.getLayoutParams()).viewType)) {
recycleBin.addScrapView(child, -1);
} returnedHeight += child.getMeasuredHeight(); if (returnedHeight >= maxHeight) {
// We went over, figure out which height to return. If returnedHeight > maxHeight,
// then the i'th position did not fit completely.
return (disallowPartialChildPosition >= 0) // Disallowing is enabled (> -1)
&& (i > disallowPartialChildPosition) // We've past the min pos
&& (prevHeightWithoutPartialChild > 0) // We have a prev height
&& (returnedHeight != maxHeight) // i'th child did not fit completely
? prevHeightWithoutPartialChild
: maxHeight;
} if ((disallowPartialChildPosition >= 0) && (i >= disallowPartialChildPosition)) {
prevHeightWithoutPartialChild = returnedHeight;
}
} // At this point, we went through the range of children, and they each
// completely fit, so return the returnedHeight
return returnedHeight;
}

如此看来,就知道,我们可以在listview的onmeasure方法中判断一下,如果listview是写死的高度,那么就将这个死的高度作为listview的最大高度值传给super.measure();否则,传入INTEGER.MAX_VALUE >> 2,这样一来,如果xml文件里面的listview的高度是wrapconten,那么就会显示所有的listview,如果写死,那么listview就是写死的高度,接下来的问题是,如果listview的高度是死的,怎么让listview自由滚动,很简单,android系统提供给我们一个方法,可以拦截或者不拦截touch事件.

getParent().requestDisallowInterceptTouchEvent(true);
true:touch事件由子控件处理
false:touch事件由父类处理

最后附上完整代码:

package com.bbd.picturesel.widgets;

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.ListView; /**
* Created by penny on 2016/4/25.
*/
public class ScrollListView extends ListView { public ScrollListView(Context context) {
this(context, null);
} public ScrollListView(Context context, AttributeSet attributeSet) {
this(context, attributeSet, 0);
} public ScrollListView(Context context, AttributeSet attributeSet, int defStyleAttr) {
super(context, attributeSet, defStyleAttr);
} @Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int maxsize = measureHeight(Integer.MAX_VALUE >> 2, heightMeasureSpec);
int expandSpec = MeasureSpec.makeMeasureSpec(maxsize, MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, expandSpec);
} /**
* @param defaultMaxSize listview的最大高度默认值
* @param heightMeasureSpec
* @return 计算之后的listview的最大高度
*/
private int measureHeight(int defaultMaxSize, int heightMeasureSpec) {
int result = 0;
int measureMode = MeasureSpec.getMode(heightMeasureSpec);
int measureSize = MeasureSpec.getSize(heightMeasureSpec);
if (measureMode == MeasureSpec.EXACTLY) {
result = measureSize;
} else {
result = defaultMaxSize;
if (measureMode == MeasureSpec.AT_MOST) {
result = Math.min(defaultMaxSize, measureSize);
} }
return result;
} /**
* 判断listview是否处于最底部
*
* @return
*/
private boolean isBottom() {
boolean isBottom = false;
int firstItemId = getFirstVisiblePosition();
int currentScreenCount = getChildCount();
int total = getCount();
if (firstItemId + currentScreenCount >= total) {
isBottom = true;
}
return isBottom;
} /**
* 判断listview是否处于最顶部
*
* @return
*/
private boolean isTop() {
int firstVisiblePosition = getFirstVisiblePosition();
if (firstVisiblePosition == 0) {
return true;
} else
return false;
} private float y = 0;
private float touchDown = 0; @Override
public boolean dispatchTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
touchDown = ev.getRawY();
getParent().requestDisallowInterceptTouchEvent(true);
break;
case MotionEvent.ACTION_MOVE:
y = ev.getRawY();
if (isTop() && isBottom()) {//listview已全部显示,不自由滚动
getParent().requestDisallowInterceptTouchEvent(false);
} else if (isTop()) {//listview目前在最上部
if (y - touchDown > 1) {
getParent().requestDisallowInterceptTouchEvent(false);
} else {
getParent().requestDisallowInterceptTouchEvent(true);
}
} else if (isBottom()) {//listview目前在最下部
if (y - touchDown > 1) {//由listview处理touch事件
getParent().requestDisallowInterceptTouchEvent(true);
} else {//由父控件处理touch事件
getParent().requestDisallowInterceptTouchEvent(false);
}
}
break;
default:
break;
} return super.dispatchTouchEvent(ev);
}
}

感谢原作者:http://blog.csdn.net/wanghao200906/article/details/51084975

scrollView中可以自由滚动的listview的更多相关文章

  1. 解决android的ListView嵌套在ScrollView中不能被滚动的问题

    使用滚动条容易带来一个后果,就是高度和宽度不受控制了, 之前就遇到一个已经有ScrollView的页面需要加个列表listView,然后就发现listView只看到前两行数据,下面的看不到,拉滚动条也 ...

  2. Android 设置ListView不可滚动 及在ScrollView中不可滚动的设置

    http://m.blog.csdn.net/blog/yusewuhen/43706169 转载请注明出处: http://blog.csdn.net/androiddevelop/article/ ...

  3. 解决ScrollView中嵌套ListView滚动效果冲突问题

    在ScrollView中嵌套使用ListView,ListView只会显示一行到两行的数据.起初我以为是样式的问题,一直在对XML文件的样 式进行尝试性设置,但始终得不到想要的效果.后来在网上查了查, ...

  4. 嵌套在ScrollView中的TextView控件可以自由滚动

    //设置TextView控件可以自由滚动,由于这个TextView嵌套在ScrollView中,所以在OnTouch事件中通知父控件ScrollView不要干扰. mContractDesc.setO ...

  5. 禁用滚动视图ListView、ViewPager、ScrollView、HorizontalScrollView、WebView边界颜色渐变

    禁用滚动视图ListView.ViewPager.ScrollView.HorizontalScrollView.WebView边界颜色渐变 ListView.ViewPager.ScrollView ...

  6. ScrollView中嵌套ListView的问题

    网上关于怎样在ScrollView中嵌套ListView的讨论有很多,我大概是搜索了一下,简单总结如下: 1.不要在ScrollView中嵌套ListView a.用一个LinearLayout来代替 ...

  7. ScrollView中嵌套ListView时,listview高度显示的问题

    方法一:直接更改listview的控件高度,动态获取(根据条目和每个条目的高度获取) 前几天因为项目的需要,要在一个ListView中放入另一个ListView,也即在一个ListView的每个Lis ...

  8. ScrollView中嵌套ScrollView或ListView而且内部ScrollView或ListView也可滑动

    1.ScrollView中嵌套ScrollView而且内部ScrollView也可滑动 (1)ScrollView继承类 public class InnerScrollView extends Sc ...

  9. ListView在ScrollView中不显示全部的问题

    在实际应用中,我们可能会遇到把ListView放到ScrollView中的情况,在这种情况下,ListView的滑动属性与ScrollView的滑动出现冲突,从而ListView只显示一项.这里提供一 ...

随机推荐

  1. 自定义带动画的Toast

    一.style样式: 1.  // 移动和透明渐变结合的动画 <style name="anim_view">        <item name="@ ...

  2. iosOpenDev-install 失败官方wiki无法解决看这里(尝试有效)

    https://github.com/kokoabim/iOSOpenDev/wiki/Troubleshoot http://blog.csdn.net/bluesky_03/article/det ...

  3. SharePoint Calculated Columns 分类: Sharepoint 2015-07-09 01:49 8人阅读 评论(0) 收藏

    SharePoint Calculated Columns are powerful tools when creating out-of-the-box solutions. With these ...

  4. MFC-01-Chapter01:Hello,MFC---1.3 第一个MFC程序(04)

    1.3.3 框架窗口对象 MFC的CWnd类及其派生类为窗口或应用程序创建的窗口提供了面向对象的接口. CMainWindow是从CFrameWnd类派生而来,CFrameWnd模仿框架窗口的行为,可 ...

  5. 第一篇:初识bootstrap

    Bootstrap是一款目前非常流行的前端框架,简单的说,就是html,css,javascript的工具集,我们可以用bootstrap搭建出简洁,清新的网站或软件界面,有了bootstrap这个利 ...

  6. gucci fake bags is usually really a sign of luxurious

    As soon as the violent trembling from the planet, standing company, people will certainly need to st ...

  7. 【转】tomcat性能调优

    一.总结前一天的学习 从"第三天"的性能测试一节中,我们得知了决定性能测试的几个重要指标,它们是: ü   吞吐量 ü   Responsetime ü   Cpuload ü   ...

  8. JAVA第二次作业展示与学习心得

    JAVA第二次作业展示与学习心得 在这一次作业中,我学习了复选框,密码框两种新的组件,并通过一个邮箱登录界面将两种组件运用了起来.具体的使用方法和其他得组件并没有什么大的不同. 另外我通过查阅资料使用 ...

  9. JS刷新父窗口的几种方式

    浮层内嵌iframe及frame集合窗口,刷新父页面的多种方法   <script language=JavaScript>       parent.location.reload(); ...

  10. shape的简单用法

    shap节点-----------------------------------定义shape的值,必须是下面的之一:"rectangle" 矩阵,这也是默认的shape&quo ...