ListViewの高さを設定する方法って、意外と複雑です。
wrap_contents
だと一つになっちゃったり、デバイスによって要素が溢れてはみ出してしまったり...。
調べてもたくさん出てくるのですが、参照が深くなったり、ライフサイクルを意識しないと崩れたり、意外とまどろっこしいものが多く、スパッと簡単に出来ないものかなと思ってました。
そこで、後述する関数を使うと楽に実装できます。
Adapterをあてがい、表示したいデータをセット済みのListviewに、この関数を用意して引数にそのListviewを渡してあげるだけです。
一部の高さを動的に変えたりしたい場合は、for文の中で制御構文等々、追加してあげるときれいになるかと思います。
Java
ListViewUtil.java
public static void setListViewHeightBasedOnChildren(ListView listView) {
//ListAdapterを取得
ListAdapter listAdapter = listView.getAdapter();
if (listAdapter == null) {
// nullチェック
return;
}
//初期化
int totalHeight = 0;
//個々のアイテムの高さを測り、加算していく
for (int i = 0; i < listAdapter.getCount(); i++) {
View listItem = listAdapter.getView(i, null, listView);
listItem.measure(0, 0);
totalHeight += listItem.getMeasuredHeight();
}
//LayoutParamsを取得
ViewGroup.LayoutParams params = listView.getLayoutParams();
//(区切り線の高さ * 要素数の数)だけ足してあげる
params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1));
//LayoutParamsにheightをセットしてあげる
listView.setLayoutParams(params);
}
Kotlin
ListViewUtil.kt
fun setListViewHeightBasedOnChildren(listView:ListView) {
//ListAdapterを取得
val listAdapter = listView.getAdapter()
if (listAdapter == null)
{
// nullチェック
return
}
//初期化
val totalHeight = 0
//個々のアイテムの高さを測り、加算していく
for (i in 0 until listAdapter.getCount())
{
val listItem = listAdapter.getView(i, null, listView)
listItem.measure(0, 0)
totalHeight += listItem.getMeasuredHeight()
}
//LayoutParamsを取得
val params = listView.getLayoutParams()
//(区切り線の高さ * 要素数の数)だけ足してあげる
params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1))
//LayoutParamsにheightをセットしてあげる
listView.setLayoutParams(params)
}
もし、もっと素敵な実装方法あれば、ご教授頂きたいです。