您的位置:首页 > 其它

ListView嵌套GridView使用解析

2018-03-14 14:13 441 查看

ListView嵌套GridView使用解析

前言

本文是ListView嵌套GridView的结构。

网上已经解决,不过还是自己做个记录,顺带的了解了解view的测量方案。

问题是嵌套后GridView只能显示一行,这里就涉及到view的高度计算了。

因为GridView是在ListView的条目中,所以他的高度是受到条目高度的控制,item的高度是受到ListView的控制。

解决的方案:

通过改变GridView的高度测量规则来显示完整的GridView。

方案1.

直接改变测量规则,真正的测量工还是交给GridView的默认测量方法。

方案2.

我们手动的去测量每个Item的高度,然后做累加。

上述方案要注意的是,不适合数据量较大的列表,因为上述方案会导致条目无法复用,一次性都加载出来。

看一下GridView的测量源码部分:

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// Sets up mListPadding
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//取出测量规则和期望的宽度和高度
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);

if (widthMode == MeasureSpec.UNSPECIFIED) {
if (mColumnWidth > 0) {
widthSize = mColumnWidth + mListPadding.left + mListPadding.right;
} else {
widthSize = mListPadding.left + mListPadding.right;
}
widthSize += getVerticalScrollbarWidth();
}
//计算出出子view的宽度
int childWidth = widthSize - mListPadding.left - mListPadding.right;
boolean didNotInitiallyFit = determineColumns(childWidth);
//开始高度计算
int childHeight = 0;
int childState = 0;
//mAdapter中一共多少个子view
mItemCount = mAdapter == null ? 0 : mAdapter.getCount();
final int count = mItemCount;
if (count > 0) {
final View child = obtainView(0, mIsScrap);

AbsListView.LayoutParams p = (AbsListView.LayoutParams) child.getLayoutParams();
if (p == null) {
p = (AbsListView.LayoutParams) generateDefaultLayoutParams();
child.setLayoutParams(p);
}
p.viewType = mAdapter.getItemViewType(0);
p.isEnabled = mAdapter.isEnabled(0);
p.forceAdd = true;
//获取子view的测量规则进行测量
int childHeightSpec = getChildMeasureSpec(
MeasureSpec.makeSafeMeasureSpec(MeasureSpec.getSize(heightMeasureSpec),
MeasureSpec.UNSPECIFIED), 0, p.height);
int childWidthSpec = getChildMeasureSpec(
MeasureSpec.makeMeasureSpec(mColumnWidth, MeasureSpec.EXACTLY), 0, p.width);
child.measure(childWidthSpec, childHeightSpec);

childHeight = child.getMeasuredHeight();
childState = combineMeasuredStates(childState, child.getMeasuredState());

if (mRecycler.shouldRecycleViewType(p.viewType)) {
mRecycler.addScrapView(child, -1);
}
}
//进行高度的测量
if (heightMode == MeasureSpec.UNSPECIFIED) {
heightSize = mListPadding.top + mListPadding.bottom + childHeight +
getVerticalFadingEdgeLength() * 2;
}
//此处是关键,这里是我们使用的最大值模式,就是把所有的view都显示出来。也是我们去干预测量来实现自己想要的显示地方。
if (heightMode == MeasureSpec.AT_MOST) {
int ourSize =  mListPadding.top + mListPadding.bottom;

final int numColumns = mNumColumns;
for (int i = 0; i < count; i += numColumns) {
ourSize += childHeight;
if (i + numColumns < count) {
ourSize += mVerticalSpacing;
}
//我们传入的值很大,所以不会走到这里面。
if (ourSize >= heightSize) {
ourSize = heightSize;
break;
}
}
//最后的高度在这里生成。
heightSize = ourSize;
}

if (widthMode == MeasureSpec.AT_MOST && mRequestedNumColumns != AUTO_FIT) {
int ourSize = (mRequestedNumColumns*mColumnWidth)
+ ((mRequestedNumColumns-1)*mHorizontalSpacing)
+ mListPadding.left + mListPadding.right;
if (ourSize > widthSize || didNotInitiallyFit) {
widthSize |= MEASURED_STATE_TOO_SMALL;
}
}

setMeasuredDimension(widthSize, heightSize);
mWidthMeasureSpec = widthMeasureSpec;
}


三种测量模式(网上摘取):

1、EXACTLY

精确值模式,当我们的控件的layout_width属性和layout_height属性指定为具体数值时,如android:layout_width="100dp",或者为match_parent时系统使用的是EXACTLY模式。

2、AT_MOST

最大值模式,当控件layout_width属性和layout_height属性为wrap_content时,控件大小随控件子控件或内容变化,此时控件的尺寸只要不超过父控件允许的最大尺寸即可。

3、UNSPECIFIED

不指定大小测量模式。


下面接着说具体的方法:

以上就是通过改变测量方式来完成全部展示GridView的item的方法。下面给出具体代码。

public class MyGridView extends GridView {
public MyGridView(android.content.Context context,
android.util.AttributeSet attrs) {
super(context, attrs);
}

/**
* 设置不滚动
*/
@Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        //第一个参数传入一个较大的值就可以了
int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,
MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, expandSpec);

}

}


结束语

就这么多了��。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  gridview listview