私はそれを考え出した; 少し複雑ですが、ほとんどの場合うまくいくようです:
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 のレイアウト パラメータを設定します。親ビューはありません。
2 番目の if ステートメントは、一番上までスクロールしたい行の位置を含む行のすべての行の高さを計算します。rowHeights は SparseIntArray です。
最後の if ステートメントは、ビューのリストの一番下に、レイアウト パラメータが既に設定されている追加のビューが 1 つあると想定しています。usedHeightForAndAfterDesiredRow 呼び出しは、親ビューの高さから差し引かれるすべての事前計算された高さを合計します (最小値が 0 であるため、負の高さは取得されません)。これにより、他のアイテムの高さに基づいて自由に拡大するビューが下部に作成されるため、特定の行は、リスト内のどこにあるかに関係なく、常にリストの上部にスクロールできます。