I'm aware that there's been a lot Q&A on this topic, but i still didn't find the right answer.
I want my ListView (inside of a ScrollView) to 'expand' over the bottom edge of the screen to show all of the items without need for scrollbar therefore it wouldn't be a problem to put ListView inside ScrollView and we would be able to scroll whole activity.
Puting items collection in LinearLayout is not a solution - it's just to damn slow. It takes 2-3 sec to draw 100 items while ListView does it instantly.
You could set the ListView's layout_height to wrap_content, but then it would be as slow as the LinearLayout. The whole point of ListView is that its content is fake; it only creates the rows that are visible within its height. Making it as tall as its content would take away its advantage.
I'd suggest re-thinking what you're trying to do. Perhaps you can put all of your widgets inside the ListView and then you wouldn't need a ScrollView.
You can try set Listview's height at runtime by using this snippet
public static void setListViewHeightBasedOnChildren(ListView listView) {
ListAdapter listAdapter = listView.getAdapter();
if (listAdapter == null) {
// pre-condition
return;
}
int totalHeight = 0;
for (int i = 0; i < listAdapter.getCount(); i++) {
View listItem = listAdapter.getView(i, null, listView);
if (listItem instanceof ViewGroup)
listItem.setLayoutParams(new LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
listItem.measure(0, 0);
totalHeight += listItem.getMeasuredHeight();
}
ViewGroup.LayoutParams params = listView.getLayoutParams();
params.height = totalHeight
+ (listView.getDividerHeight() * (listAdapter.getCount() - 1));
listView.setLayoutParams(params);
}
And example to use this
listComment.setAdapter(new CommentAdapter(comment,
AppDetailActivity.this));
listComment.postDelayed(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
Utils.setListViewHeightBasedOnChildren(listComment);
}
}, 500);
Related
I understand that putting a ListView inside a ScrollView is not recommmender. But I must use a ListView, simply because I'm using an adapter and various other methods.
I have used this code, which I found on StackOverflow and it shows me the majority of my list. However, in portrait mode some items are cut off from the bottom and in landscape mode the same.
How can this be rectified? To clarify, I've got a ScrollView containing a LinearLayout containing some elements and my ListView in my XML.
In addition, if I go to a new activity, then return I can briefly see the scroll bars for listview show up and disappear. How can this be rectified too?
public static boolean setListViewHeightBasedOnItems(ListView listView) {
ListAdapter listAdapter = listView.getAdapter();
if (listAdapter != null) {
int numberOfItems = listAdapter.getCount();
// Get total height of all items.
int totalItemsHeight = 0;
for (int itemPos = 0; itemPos < numberOfItems; itemPos++) {
View item = listAdapter.getView(itemPos, null, listView);
item.measure(0, 0);
totalItemsHeight += item.getMeasuredHeight();
}
// Get total height of all item dividers.
int totalDividersHeight = listView.getDividerHeight() *
(numberOfItems - 1);
// Set list height.
ViewGroup.LayoutParams params = listView.getLayoutParams();
params.height = totalItemsHeight + totalDividersHeight;
listView.setLayoutParams(params);
listView.requestLayout();
return true;
} else {
return false;
}
}
Use recycler-view or list-view and make use of view-type to inflate different layouts instead of using scroolview and nesting up other viewgroups inside.
I think your question is a bit misleading. How on earth can a listview displays its all items without scrolling as long as we are dealing with these tiny mobile screens?
Maybe you want that scroll bar to not show up, then you can set attribute like this on your ScrollView:
android:scrollbars="none"
I have a RelativeLayout activity contains a list-view. I want to make the list-view height based on its items, I searched in the internet and found many methods do this but all methods give the list-view height greater than items height.
The method I use as following:
public static void setListViewHeightBasedOnChildren(ListView listView) {
ListAdapter listAdapter = listView.getAdapter();
if (listAdapter == null) {
// pre-condition
return;
}
int totalHeight = 0;
int desiredWidth = View.MeasureSpec.makeMeasureSpec(listView.getWidth(),
View.MeasureSpec.AT_MOST);
for (int i = 0; i < listAdapter.getCount(); i++) {
View listItem = listAdapter.getView(i, null, listView);
listItem.measure(desiredWidth, View.MeasureSpec.UNSPECIFIED);
totalHeight += listItem.getMeasuredHeight();
}
ViewGroup.LayoutParams params = listView.getLayoutParams();
params.height = totalHeight
+ (listView.getDividerHeight() * (listAdapter.getCount() - 1));
listView.setLayoutParams(params);
listView.requestLayout();
}
when I debug the method If found that there are some items height equal to "45" and some items height equal to "66" while all items in the list-view have the same height when the activity appear.
Here is a snapshot of the activity, the list-view background is light-gray to show the list-view height:
Activity snpapshot
if you want the whole list to be visible then don't use list view
listview is not made for this it's made to fill the screen and the reusing it's views
use a scrollview with linear and inflate them inside but the is a bad approach and will take a long time
so please revisit the reasons you are doing this maybe you will find a better Widget for it or maybe share a screenshot of the ui you are trying to achieve
Currently i am displaying listview using visibility "GONE" and then "VISIBLE" on button click, But its displaying only 1 item in listview, other elements in scrollview ( i need to scroll), so i decided to keep listview showing atleast 3 items first and rest element on listview scroll.
how to work out this, thanks in advance.
1st image is my code
i need to have like 2nd image
A ListView inside a ScrollView is a bad idea in general.
Instead you should use a LinearLayout and inflate your ListItems in there.
Not too hard to do. Just use a for loop or something.
If you MUST use a ListView you can call the following method on your ListView after it has been populated.
(change listAdapter.getCount() to the number of cells you want to show
public static void setListViewHeightBasedOnChildren(ListView listView) {
ListAdapter listAdapter = listView.getAdapter();
if (listAdapter == null) {
// pre-condition
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();
}
ViewGroup.LayoutParams params = listView.getLayoutParams();
params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1));
listView.setLayoutParams(params);
}
I have added Button and ListView on a ScrollView. Button is added below to the ListView in ScrollView but Problem is that it shows large space between button and ListView. Here is my code
ReservationDrinkListAdapter adp = new ReservationDrinkListAdapter(this,
KukumberApplication.getInstance().getBottleService().menuItems);
list.setAdapter(adp);
Util.setListViewHeightBasedOnChildren(list);
following method is used to show ListView in ScrollView.
public static void setListViewHeightBasedOnChildren(ListView listView)
{
ListAdapter listAdapter = listView.getAdapter();
if (listAdapter == null) {
// pre-condition
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();
}
ViewGroup.LayoutParams params = listView.getLayoutParams();
params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1));
listView.setLayoutParams(params);
}
What am I doing wrong? Any Suggestion and sample code Would be appreciated.
Using a listview inside of a scrollview is technically possible but is not at all recommended, doing as you have (expanding the whole list so the scrollview accomodates all the list) goes against the whole point of adapterviews (performance) and will cause you lots of issues such as those you have encountered.
You can see more about this in answers such as:
How can I put a ListView into a ScrollView without it collapsing?
How to add two listview in scrollview
Why ListView cannot be used in a ScrollView?
ListView inside ScrollView is not scrolling on Android
And there are even more out there.
I have a number of vertically stacked panels in my UI. Each panel contains a ListView. Based on user interaction, the number of items in the ListView gets updated.
My problem is that if I increase the number of items being shown in the ListView, the containing panel will not expand to show them. Instead, my ListView just gets cut off with a fade to black. I am programmatically creating each of these stacked panels - this is the body of the creating function:
LinearLayout containingPanel = new LinearLayout(TestActivity.this);
containingPanel.setOrientation(LinearLayout.VERTICAL);
// create title
TextView titleText = new TextView(TestActivity.this);
titleText.setText("a title");
titleText.setGravity(Gravity.CENTER);
titleText.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
// create dynamic list view of costs
ListView dynamicContentListView = new ListView(TestActivity.this);
dynamicContentListView.setAdapter(new MyDynamicAdapter());
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT);
params.weight = 1;
dynamicContentListView.setLayoutParams(params);
// build up GUI
containingPanel.addView(titleText);
containingPanel.addView(dynamicContentListView);
return containingPanel;
I thought that setting the weight on the ListView should be enough, but it is not. All GUI updating is working fine - new items are automatically added to data backing the Adapter, and the ListView updates itself properly. But after I add three or four new items, the containingPanel refuses to update itself and the new items get blended out.
try this function. I think, it might help you. The function is used to set ListView's height based on its children.
public static void setListViewHeightBasedOnChildren(ListView listView) {
ListAdapter listAdapter = listView.getAdapter();
if (listAdapter == null) {
// pre-condition
return;
}
int totalHeight = 0;
int desiredWidth = MeasureSpec.makeMeasureSpec(listView.getWidth(), MeasureSpec.AT_MOST);
for (int i = 0; i < listAdapter.getCount(); i++) {
View listItem = listAdapter.getView(i, null, listView);
listItem.measure(desiredWidth, MeasureSpec.UNSPECIFIED);
totalHeight += listItem.getMeasuredHeight();
}
ViewGroup.LayoutParams params = listView.getLayoutParams();
params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1));
listView.setLayoutParams(params);
listView.requestLayout();
}
(You can add a ListView inside a ScrollView but not without a little work (as they are both Scrollable components - how would the OS know which one you're trying to scroll?). You would need to add isScrollContainer="false" on your ListView.)
<ListView
android:id="#+id/list"
android:layout_width="match_parent"
android:layout_height="wrap_contents"
android:isScrollContainer="false"/>
The entire point of a ListView is it has a set height as dictated by the layout of your page. It only becomes scrollable when it's children's combined height exceed the area required to display it.
It sounds like what you actually want is something more akin to a LinearLayout which is backed by an Adapter, there are several implementations out there on the web or you can create your own.
However, you can hack a ListView into this behaviour by dynamically resizing your ListView programatically by setting it's Height to: listCount * itemHeight. This would have the effect of consistently expanding your ListView.
You will likely find that as you develop your UI design you will no longer require such a component.
If your listview is a default size, it might not be able to fit them in the layout. You could try to wrap the listview in a scrollview and then you can scroll through them.