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.
Related
I have an android layout which has a scrollView with a number of elements with in it. At the bottom of the scrollView I have a listView which is then populated by an adapter.
The problem that I am experiencing, is that android is excluding the listView from the scrollView as the scrollView already has a scroll-able function. I want the listView to be as long as the content is and for the master scroll view to be scroll-able.
i want to set the scrollView scroling if the listView has complete her scroling
#Gaurav Roy
You do not have to do anything special in layout.xml file nor handle anything on the parent ScrollView. You only have to handle the child ListView. You can also use this code to use any type of child view inside a ScrollView & perform Touch operations.
Just add these lines of code in your java class :
ListView lv = (ListView) findViewById(R.id.layout_lv);
lv.setOnTouchListener(new OnTouchListener() {
// Setting on Touch Listener for handling the touch inside ScrollView
#Override
public boolean onTouch(View v, MotionEvent event) {
// Disallow the touch request for parent scroll on touch of child view
v.getParent().requestDisallowInterceptTouchEvent(true);
return false;
}
});
If you put ListView inside a ScrollView then all the ListView does not stretch to its full height. Below is a method to fix this issue.
/**** Method for Setting the Height of the ListView dynamically.
**** Hack to fix the issue of not showing all the items of the ListView
**** when placed inside a ScrollView ****/
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);
}
To use this method just pass the ListView inside this method :
ListView list = (ListView) view.findViewById(R.id.ls);
setListViewHeightBasedOnChildren(list);
For using with ExpandableListView - credit Benny
ExpandableListView: view = listAdapter.getView(0, view, listView);
int widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(ViewGroup.LayoutParams.MATCH_PARENT, View.MeasureSpec.EXACTLY);
int heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(ViewGroup.LayoutParams.WRAP_CONTENT, View.MeasureSpec.EXACTLY);
view.measure(widthMeasureSpec, heightMeasureSpec);
For ListView with variable items height use the below link :
ListView inside ScrollView is not scrolling on Android
For Library to directly implementing in your code - credit Paolo Rotolo
https://github.com/PaoloRotolo/ExpandableHeightListView
Instead of embedding a ListView inside of a ScrollView, add the contents of the scrollview to a single viewgroup, then add those programatically to the top of the ListView with addHeaderView.
For instance, have the root element of your layout be a ListView, and inflate a separate layout with the rest of the views via a LayoutInflater. Then just pass that reference to the inflated view into the addHeaderView method.
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
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);
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);
}