scrollView中可以自由滚动的listview
直接在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的更多相关文章
- 解决android的ListView嵌套在ScrollView中不能被滚动的问题
使用滚动条容易带来一个后果,就是高度和宽度不受控制了, 之前就遇到一个已经有ScrollView的页面需要加个列表listView,然后就发现listView只看到前两行数据,下面的看不到,拉滚动条也 ...
- Android 设置ListView不可滚动 及在ScrollView中不可滚动的设置
http://m.blog.csdn.net/blog/yusewuhen/43706169 转载请注明出处: http://blog.csdn.net/androiddevelop/article/ ...
- 解决ScrollView中嵌套ListView滚动效果冲突问题
在ScrollView中嵌套使用ListView,ListView只会显示一行到两行的数据.起初我以为是样式的问题,一直在对XML文件的样 式进行尝试性设置,但始终得不到想要的效果.后来在网上查了查, ...
- 嵌套在ScrollView中的TextView控件可以自由滚动
//设置TextView控件可以自由滚动,由于这个TextView嵌套在ScrollView中,所以在OnTouch事件中通知父控件ScrollView不要干扰. mContractDesc.setO ...
- 禁用滚动视图ListView、ViewPager、ScrollView、HorizontalScrollView、WebView边界颜色渐变
禁用滚动视图ListView.ViewPager.ScrollView.HorizontalScrollView.WebView边界颜色渐变 ListView.ViewPager.ScrollView ...
- ScrollView中嵌套ListView的问题
网上关于怎样在ScrollView中嵌套ListView的讨论有很多,我大概是搜索了一下,简单总结如下: 1.不要在ScrollView中嵌套ListView a.用一个LinearLayout来代替 ...
- ScrollView中嵌套ListView时,listview高度显示的问题
方法一:直接更改listview的控件高度,动态获取(根据条目和每个条目的高度获取) 前几天因为项目的需要,要在一个ListView中放入另一个ListView,也即在一个ListView的每个Lis ...
- ScrollView中嵌套ScrollView或ListView而且内部ScrollView或ListView也可滑动
1.ScrollView中嵌套ScrollView而且内部ScrollView也可滑动 (1)ScrollView继承类 public class InnerScrollView extends Sc ...
- ListView在ScrollView中不显示全部的问题
在实际应用中,我们可能会遇到把ListView放到ScrollView中的情况,在这种情况下,ListView的滑动属性与ScrollView的滑动出现冲突,从而ListView只显示一项.这里提供一 ...
随机推荐
- Delphi 中同类型方法的说明
对象的方法能定义成静态(static).虚拟(virtual).动态(dynamic)或消息处理(message).请看下面 的例子: TFoo = class procedure IAmAStati ...
- hammer.js实现背景图手势缩放调整位置
<!DOCTYPE html> <html> <head> <script> function getxy(e){ var a=new Array() ...
- 使用ajaxfileupload.js实现文件上传
ajaxFileUpload是一个异步上传文件的jQuery插件 语法:$.ajaxFileUpload([options]) options参数说明: 1.url 上传处理程序地址. 2,file ...
- centos下在线安装mysql
1 首先查看是否有安装过,如果已经安装过,就不必再安装了 yum list installed mysql* rpm -qa | grep mysql* 2 查看有没有安装包: yum list my ...
- MicroERP软件更新记录2.1
最新版本:2.1 更新内容:新增客户关系管理(CRM) 下载地址:http://60.2.39.130/microerp 因部分企业用户或个人(开发者)的实际应用水平或技术开发能力参差不齐,且软件开发 ...
- extern引发的闹剧
最近一个朋友让我帮他解决一个问题,由于源代码不方便贴出来,所以就自己写了个demo把问题重现一次 1.新建一个application,添加一个继承于NSObject的类 本来是随便写的,就将此类命名为 ...
- Informatica Lookup Transformation组件的Connect 与Unconnected类型用法
Informatica Lookup Transformation组件的Connect 与Unconnected类型用法及区别:下面是通一个Lookup在不同Mapping中的使用: 1. Conne ...
- 不是SELECTed表达式
sql语句如下: select distinct(p.project_name) name,p.pkid pkid, p.report_year year, q.cor_name cor_name,g ...
- Java中main函数只能调用同类中的静态方法?
如果想调用本类中的非静态方法可以这么来写: public class TT{ public static void main(String[] args){ TT t = new TT(); t.fu ...
- It will affect staff as well.
Premier Foods has reduced its number of suppliers dramatically in the last 12 months. In 2013 it mad ...