我想到了; 它有点复杂,但它似乎主要工作:
public int usedHeightForAndAfterDesiredRow() {
int totalHeight = 0;
for (int index = 0; index < rowHeights.size(); index++) {
int height = rowHeights.get(rowHeights.keyAt(index));
totalHeight += height;
}
return totalHeight;
}
@Override
public View getView(int position, View convertView, final ViewGroup parent) {
View view = super.getView(position, convertView, parent);
if (measuringLayout.getLayoutParams() == null) {
measuringLayout.setLayoutParams(new AbsListView.LayoutParams(parent.getWidth(), parent.getHeight()));
}
// measure the row ahead of time so that we know how much space will need to be added at the end
if (position >= mainRowPosition && position < getCount()-1 && rowHeights.indexOfKey(position) < 0) {
measuringLayout.addView(view, new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
measuringLayout.measure(MeasureSpec.makeMeasureSpec(parent.getWidth(), MeasureSpec.EXACTLY), MeasureSpec.UNSPECIFIED);
rowHeights.put(position, view.getMeasuredHeight());
measuringLayout.removeAllViews();
view.setLayoutParams(new AbsListView.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
}
if (position == getCount()-1 && view.getLayoutParams().height == 0) {
// we know how much height the prior rows take, so calculate the last row with that.
int height = usedHeightForAndAfterDesiredRow();
height = Math.max(0, parent.getHeight() - height);
view.getLayoutParams().height = height;
}
return view;
}
这是在我的适配器中。它是合并适配器的子类,但您可以将其放入您的代码中,然后用生成行的方式替换超级调用。
getView() 中的第一个 if 语句设置仅用于测量的框架布局成员 var 的布局参数,它没有父视图。
第二个 if 语句计算行的所有行高,包括我关心滚动到顶部的行的位置和之后的位置。rowHeights 是一个 SparseIntArray。
最后一个 if 语句假设有一个额外的视图,其布局参数已经设置在视图列表的底部,其唯一目的是透明和随意扩展。usedHeightForAndAfterDesiredRow 调用将所有预先计算的高度相加,这些高度从父视图的高度中减去(最小值为 0,因此我们不会得到负高度)。这最终会在底部创建一个视图,该视图会根据其他项目的高度随意扩展,因此特定行始终可以滚动到列表顶部,无论它在列表中的哪个位置。