I want to be able to expand the rows in my ListView with an animation. Therefore I need to know the height of the view that is expanding. I'm using this in the getView()
method of my ArrayAdapter
:
mDetailsView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
mDetailsView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
onClickListener.setHeight(mDetailsView.getHeight());
mDetailsView.setVisibility(View.GONE);
}
});
This works fine for the rows that are visible on screen at start, but when I scroll down, the onGlobalLayout
method doesn't get called for the rows that weren't visible at first.
How can I get the height for those rows?
It is possible that implementations of ListView
don't do an entire layout so the ViewTreeObserver
never actually sees a layout in progress.
Unless there's some specific phone case I'm not aware of, you can use the post
method in Views to execute runnable when they're in view.
mDetailsView.post(new Runnable() {
@Override
public void run() {
onClickListener.setHeight(mDetailsView.getHeight());
mDetailsView.setVisibility(View.GONE);
}
});
EDIT:
I don't know how the entire getView()
method is laid out. The issue, if I had to guess, is the ListView
simply isn't requesting a layout. Instead it's doing the work itself for each view to speed things up. What you can try is this:
public void getView(int position, View convertView, ViewGroup parent) {
/*
* set your view up
*/
mDetailsView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
mDetailsView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
onClickListener.setHeight(mDetailsView.getHeight());
mDetailsView.setVisibility(View.GONE);
}
});
notifyDataSetInvalidated(); // Notify the ListView() and any other listeners that your views are invalid.
return view;
}
New edit: Using notifyDataSetInvalidated()
in usually a bad idea and especially if used in getView()
.
To pre-measure the layout you would take it's layout params or give it new ones if they don't exist.
LayoutParams params = newView.getLayoutParams();
if (params == null) {
params = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
}
final int widthSpec = MeasureSpec.makeMeasureSpec(parent.getWidth(), MeasureSpec.UNSPECIFIED);
final int heightSpec = MeasureSpec.makeMeasureSpec(parent.getHeight(), MeasureSpec.UNSPECIFIED);
newView.measure(widthSpec, heightSpec);
In ListView or RecyclerView instead of using OnGlobalLayoutListener
I always use OnPreDrawListener
. This callback is fired also for non visible rows at start. From the official documentation:
At this point, all views in the tree have been measured and given a frame.
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