ListView는 실제로 모든 항목을 표시 할만큼 충분히 키가 큰 것으로 측정 할 수 있지만 wrap_content (MeasureSpec.UNSPECIFIED)를 지정하면이 작업을 수행하지 않습니다. MeasureSpec.AT_MOST로 높이가 주어지면이 작업을 수행합니다. 이 지식을 통해이 문제를 해결하기 위해 매우 간단한 서브 클래스를 생성 할 수 있습니다.이 문제는 위에 게시 된 솔루션보다 훨씬 효과적입니다. 이 서브 클래스에는 여전히 wrap_content를 사용해야합니다.
public class ListViewForEmbeddingInScrollView extends ListView {
public ListViewForEmbeddingInScrollView(Context context) {
super(context);
}
public ListViewForEmbeddingInScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ListViewForEmbeddingInScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 4, MeasureSpec.AT_MOST));
}
}
heightMeasureSpec을 매우 큰 크기 (Integer.MAX_VALUE >> 4)의 AT_MOST로 조작하면 ListView가 모든 하위를 주어진 (매우 큰) 높이까지 측정하고 그에 따라 높이를 설정합니다.
몇 가지 이유로 다른 솔루션보다 더 효과적입니다.
- 모든 것을 정확하게 측정합니다 (패딩, 분배기)
- 측정 단계 동안 ListView를 측정합니다.
- # 2로 인해 추가 코드없이 너비 또는 항목 수의 변경을 올바르게 처리합니다.
단점은이 작업을 수행하는 것이 SDK에서 문서화되지 않은 동작에 의존하여 변경 될 수 있다고 주장 할 수 있습니다. 반면에 wrap_content가 실제로 ListView에서 작동하는 방식이며 현재 wrap_content 동작이 손상되었다고 주장 할 수 있습니다.
앞으로 동작이 변경 될까 걱정이되면 onMeasure 함수 및 관련 함수를 ListView.java에서 자신의 하위 클래스로 복사 한 다음 onMeasure를 통해 AT_MOST 경로를 UNSPECIFIED에 대해 실행해야합니다.
그건 그렇고, 나는 이것이 적은 수의 목록 항목으로 작업 할 때 완벽하게 유효한 접근법이라고 생각합니다. LinearLayout과 비교할 때 비효율적 일 수 있지만 항목 수가 적은 경우 LinearLayout을 사용하는 것은 불필요한 최적화이므로 불필요한 복잡성입니다.