The listView is filled programmatically and is among other layout. The root element is ScrollView. After drawing the list, he is allocated a height of just one line, while the others are available by scrolling through the list. Tried to set both wrap_content and match_parent, does not help. How to make the list in the list display all the lines?
3 answers
Both ScrollView and ListView are scrolling items. When one is placed in another, conflits of scrolling begin - the system cannot understand what exactly it should scroll. And in your particular case, the ListView is compressed to the height of the first element.
You have 2 options:
All that is above the
ListView
make it Header-ohm, and everything below-Footer-ohm. This is the correct option.Set a fixed height for the ListView by calculating in advance the total height of all its elements. This is a hack and a crutch - do not do so.
- Concerning the scrolling conflict, I agree, but this could be solved by blocking the scrolling of the container when the scrolling occurs in the list area. And just for the same cases, as it seems to me, the blocking property of the list and the full display of its contents arise. Maybe I misunderstand the essence of the lists .. - Alexander Tymchuk
1) Set the height of the ListView programmatically, so that it does not have the ability to scroll: take the height of one element and multiply it by the number of elements
int baseListViewHeight = getResources().getDimensionPixelSize(R.dimen.size_72); LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) list.getLayoutParams(); lp.height = baseListViewHeight * items.size(); list.setLayoutParams(lp);
2) Inherit from ListView and set its height there - the essence is the same but on the other hand the approach
public class NonScrollListView extends ListView { public NonScrollListView(Context context) { super(context); } public NonScrollListView(Context context, AttributeSet attrs) { super(context, attrs); } public NonScrollListView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int heightMeasureSpec_custom = MeasureSpec.makeMeasureSpec( Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST); super.onMeasure(widthMeasureSpec, heightMeasureSpec_custom); ViewGroup.LayoutParams params = getLayoutParams(); params.height = getMeasuredHeight(); super.onMeasure(widthMeasureSpec, heightMeasureSpec); } }
Then use it in the markup as a normal view.
The decision in fact is not recommended by Google, I do not remember for what reasons - something is there with performance, but on small lists it is quite justifying.
- ListView clears the memory for himself while running away elements over the edge of the screen. I think if you deprive him of this opportunity, setting the height of the content and filling it with pictures, then the application may fall on OutOfMemomryError - YuriySPb ♦
- I applied this solution in practice, everything was ok - you need to make your assumption hard - Roman Novoselov
- I added a comment - it is more likely to fall in the presence of images in the elements) - YuriySPb ♦
- @YuriSPb Honestly, I’ve almost matured to use the programmatically crafted item in the form of a linearLayout with three textViews. And how it turns out a lot of trouble = \ - Alexander Tymchuk
A little googling found such a working version: create a function
public static void setListViewHeightBasedOnChildren(ListView listView) { ListAdapter listAdapter = listView.getAdapter(); if (listAdapter == null) return; int desiredWidth = MeasureSpec.makeMeasureSpec(listView.getWidth(), MeasureSpec.UNSPECIFIED); int totalHeight = 0; View view = null; for (int i = 0; i < listAdapter.getCount(); i++) { view = listAdapter.getView(i, view, listView); if (i == 0) view.setLayoutParams(new ViewGroup.LayoutParams(desiredWidth, LayoutParams.WRAP_CONTENT)); view.measure(desiredWidth, MeasureSpec.UNSPECIFIED); totalHeight += view.getMeasuredHeight(); } ViewGroup.LayoutParams params = listView.getLayoutParams(); params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1)); listView.setLayoutParams(params); }
and after installing the adapter, we give it the list itself, that's it!