만족

[Android] setListViewHeightBasedOnChildren 사용 시 주의점 본문

[Android] setListViewHeightBasedOnChildren 사용 시 주의점

FrontEnd/Android Satisfaction 2020. 4. 14. 23:49

안드로이드 개발자라면 누구나 한 번쯤은 ScrollView아래의 ListView를 사용했을 때

ListView의 높이가 쪼그라드는 문제를 경험해본적이 있을 것이다.

 

구글에 android listview height is weired처럼 검색하면 가장 많이 나오는 솔루션은

 

요런 함수를 쓰라는 내용이다.

 

웬만하면 리사이클러뷰를 사용하는 방법으로 회피해가려 하지만 

"스크롤뷰+리스트뷰"조합으로 된 모든 코드를 뒤집어버릴 순 없으니

해당 부분에만 위의 함수를 적용시켜주고 있었다.

 

그런데 예상했던 것과는 달리 위의 함수는 연산시간을 꽤 잡아먹는 녀석이다.

(특히 listItem.measure 부분)

 

200개의 요소가 있는 리스트뷰의 높이를 계산하려고 하니 소요시간이 1초가 넘어가버려서 앱 애니메이션이 뚝뚝 끊기는 느낌이 난 것이다.

 

사실 생각해보면 listview를 사용할 때, 각각의 뷰들의 높이는 크게 다르지 않다.

(다른 경우에는 어쩔 수 없이 다른 방법을 찾아봐야 할 것이다만... 높이가 제각각인 경우에는 그냥 RecyclerView를 사용하는 편이 낫다)

 

그러니, measure는 한번만 호출하고 뷰의 갯수만큼 곱해준 뒤, totalHeight에 더하는 것이 더 효율적이다.

 

public static long setListViewHeightBasedOnChildren(@NonNull ListView listView) {
  long timer= System.currentTimeMillis();
  ListAdapter listAdapter = listView.getAdapter();

  int totalHeight = 0;
  if(listAdapter.getCount()> 0){
    View listItem = listAdapter.getView(0, null, listView);
    listItem.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
    View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
    totalHeight = listItem.getMeasuredHeight()* listAdapter.getCount();
  }

  ViewGroup.LayoutParams params = listView.getLayoutParams();
  params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1));
  listView.setLayoutParams(params);
  listView.requestLayout();

  return System.currentTimeMillis()- timer;
}

위 방법으로 했을 경우 소요시간이 1067ms-> 48ms로 크게 단축되었다.

 

measure는 꽤나 비용이 큰 작업이니 리스트 갯수가 많을 때는 좀 더 고려해 볼 필요가 있다.

 



Comments