I am currently trying to use a ListView inside of a ScrollView. I know from what I've read that this is looked down upon, but I'm trying to get the ListView to expand completely by showing all of its rows so there is no need for it to scroll. I've been struggling, however, with how to tell the ListView to completely expand to show all of its rows since it needs a defined height. How do I calculate the height of a fully expanded ListView before it is drawn?
This problem mainly stems from the fact that you can't put a scrollable view inside of another scrollable view. I am okay with the fact that the ListView won't be able to scroll as long as I can make it expand to show all of its rows. I cannot do this, however, without being able to give it a defined height, which it seems I would need to calculate.
My full layout is too big for the "physical" screen and needs to scroll in order to show the rest of the list and buttons at the bottom. I'm trying to get across that the "virtual" screen is too big to fit on one screen even without the ListView there.
Well, thanks to Rudy, his suggestions was very helpful. Here is how it can be implemented.
1) Create a new class that extends ListView:
package com.example.android.views;
import android.content.Context;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.widget.ListView;
public class ExpandedListView extends ListView {
private android.view.ViewGroup.LayoutParams params;
private int old_count = 0;
public ExpandedListView(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onDraw(Canvas canvas) {
if (getCount() != old_count) {
old_count = getCount();
params = getLayoutParams();
params.height = getCount() * (old_count > 0 ? getChildAt(0).getHeight() : 0);
setLayoutParams(params);
}
super.onDraw(canvas);
}
}
2) ... and finally add the new view to your xml layout file:
<com.example.android.views.ExpandedListView
android:id="@+id/list"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scrollbars="none"
android:padding="0px"
/>
The correct way to calculate the height is precisely:
int height = 0;
for (int i = 0; i < listView.getChildCount(); i++) {
height += listView.getChildAt(i).getMeasuredHeight();
height += listView.getDividerHeight();
}
Attention! Correct way to calculate height is not
params.height = getCount() * (old_count > 0 ? getChildAt(0).getHeight() : 0);
We have to add height of each (minus one) divider heights.
if(oldCount > 0 && getCount() > 0)
params.height = getCount()
* (getChildAt(0).getHeight() + getDividerHeight())
- getDividerHeight();
else
params.height = 0;
@Override
public void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) {
if (this.isExpanded) {
final int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, expandSpec);
final ViewGroup.LayoutParams params = this.getLayoutParams();
params.height = this.getMeasuredHeight();
} else {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With