I'm having some issues with setting my ListView's height.
My ListView is inside a ScrollView and it's populated with some elements. In order to have my ListView expanded I programmatically calculate the height of the elements and set the ListView height accordingly.
For some reasons it's like my measures are not correct.
Here's my ListView item layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:orientation="horizontal"
>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#android:drawable/ic_media_play"
android:tint="#android:color/black"
android:background="#android:color/transparent"
android:padding="12dp"
/>
<TextView android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/tv_trailer_item_title"
android:textSize="22dp"
android:textColor="#000000"
android:textStyle="italic"
android:padding="12dp"
/>
</LinearLayout>
And here's my piece of code for setting the ListView height:
public void setListViewHeightBasedOnChildren(ListView listView) {
TrailersAdapter listAdapter = (TrailersAdapter) listView.getAdapter();
if (listAdapter == null) {
return;
}
int elements = listAdapter.getCount();
Log.d("AAA","Got " + elements + " elements");
if (elements>0) {
View listItem = listAdapter.getView(0, null, listView);
listItem.measure(0,0);
//get the height of a single item, multiply by the number of items and get the total height for the items
int totalHeight = listItem.getMeasuredHeight() * elements;
ViewGroup.LayoutParams params = listView.getLayoutParams();
//calculate the total height summing the height of the dividers too
params.height = totalHeight
+ (listView.getDividerHeight() * (listAdapter.getCount()-1));
//set the height
listView.setLayoutParams(params);
}
}
Heres how the Activity looks like:
The trailers should be five, but only 4 are shown (in other cases half is shown)
What am I doing wrong?
Related
this is my layout for the same. my issue is, the list view in it is not increase the height with item count.
when I used wrap_content a given height like 210 pixel its shows the data... when I set height as wrap_content, it is showing only one item.
<LinearLayout
android:layout_width="match_parent"
android:id="#+id/rl_createPro_option"
android:orientation="vertical"
android:layout_marginTop="5dp"
android:visibility="gone"
android:layout_marginBottom="5dp"
android:layout_height="wrap_content">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Please provide option-wise price:"/>
<ListView
android:layout_marginTop="5dp"
android:layout_width="match_parent"
android:id="#+id/rv_createPro"
android:layout_height="wrap_content" />
<RadioGroup
android:layout_width="match_parent"
android:id="#+id/rg_createPro"
android:layout_marginTop="5dp"
android:layout_height="wrap_content">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="Option highlight??"/>
<RadioButton
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="yes"/>
<RadioButton
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="no"/>
</RadioGroup>
</LinearLayout>
please help me!!
This is because of your linearlayout with vertical orientation its keeping space for the lower views like radioGroups .Set height of listview dynamically use
public static void setListViewHeightBasedOnChildren(final ListView listView) {
listView.post(new Runnable() {
#Override
public void run() {
ListAdapter listAdapter = listView.getAdapter();
if (listAdapter == null) {
return;
}
int totalHeight = listView.getPaddingTop() + listView.getPaddingBottom();
int listWidth = listView.getMeasuredWidth();
for (int i = 0; i < listAdapter.getCount(); i++) {
View listItem = listAdapter.getView(i, null, listView);
listItem.measure(
View.MeasureSpec.makeMeasureSpec(listWidth, View.MeasureSpec.EXACTLY),
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
totalHeight += listItem.getMeasuredHeight();
Log.d("listItemHeight " + listItem.getMeasuredHeight(), "********");
}
Log.d("totalHeight " + totalHeight, "********");
ViewGroup.LayoutParams params = listView.getLayoutParams();
params.height = (totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1)));
listView.setLayoutParams(params);
listView.requestLayout();
}
});
}
I have a Listview in which I need to obtain the total height sum of all the items so that the ListView height equals that height of all the items. I tried to implement the following class to accomplish that.
public class UIUtils {
/**
* Sets ListView height dynamically based on the height of the items.
*
* #param listView to be resized
* #return true if the listView is successfully resized, false otherwise
*/
public static boolean setListViewHeightBasedOnItems(ListView listView) {
ListAdapter listAdapter = listView.getAdapter();
if(listAdapter != null)
{
int numberOfItems = listAdapter.getCount();
WindowManager wm = (WindowManager) listView.getContext().getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
int deviceWidth;
if(android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) {
Point size = new Point();
display.getSize(size);
deviceWidth = size.x;
} else {
deviceWidth = display.getWidth();
}
int desiredWidth = View.MeasureSpec.makeMeasureSpec(deviceWidth, View.MeasureSpec.AT_MOST);
int desiredHeight = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
// 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(desiredWidth, desiredHeight);
totalItemsHeight += item.getMeasuredHeight();
}
// Get total height of all item dividers.
int totalDividersHeight = listView.getDividerHeight() * (numberOfItems - 1);
int totalPadding = listView.getPaddingBottom() + listView.getPaddingTop();
// Set list height.
ViewGroup.LayoutParams params = listView.getLayoutParams();
params.height = totalItemsHeight + totalDividersHeight + totalPadding;
listView.setLayoutParams(params);
listView.requestLayout();
return true;
}
else
{
return false;
}
}
}
Here is how I finally make use of the class described before:
ListView list = (ListView) findViewById(R.id.bills);
BillsListViewAdapter listViewAdapter = new BillsListViewAdapter(context, R.layout.item_bill, bills);
list.setAdapter(listViewAdapter);
UIUtils.setListViewHeightBasedOnItems(list);
The mentioned class will only return a static value for all the items even though on some instances the height may vary because the text of a TextView inside the item might have two or more lines.
item_bil.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?android:attr/activatedBackgroundIndicator"
android:padding="10dp"
android:weightSum="1">
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.9"
android:orientation="vertical">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginBottom="5dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/number"
android:layout_marginEnd="2dp"
android:textSize="12sp"/>
<TextView
android:id="#+id/number"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="{{number}}"
android:textSize="12sp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/hour"
android:layout_marginStart="#dimen/activity_horizontal_margin"
android:layout_marginEnd="2dp"
android:textSize="12sp"/>
<TextView
android:id="#+id/hour"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="{{hour}}"
android:textSize="12sp"/>
</LinearLayout>
<TextView
android:id="#+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="{{name}}"
android:textSize="16sp"
android:textColor="#color/colorPrimary"
android:layout_marginBottom="5dp"
android:gravity="center_vertical"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginBottom="5dp">
<TextView
android:id="#+id/address"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="{{address}}"
android:textStyle="bold"
android:textSize="12sp"
android:gravity="center_vertical"/>
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_weight="0.1">
<TextView
android:id="#+id/amount"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="{{amount}}"
android:textSize="18sp"
android:gravity="right"/>
</LinearLayout>
</LinearLayout>
ListView:
<ListView
android:id="#+id/charges"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbars="none"/>
Try this code. It's working fine in my App.
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListAdapter;
import android.widget.ListView;
/**
* Created by Zohaib Hassan on 5/25/2015.
*/
public class ListviewHelper {
public static void getListViewSize(ListView myListView) {
ListAdapter myListAdapter = myListView.getAdapter();
if (myListAdapter == null) {
//do nothing return null
return;
}
//set listAdapter in loop for getting final size
int totalHeight = 0;
for (int size = 0; size < myListAdapter.getCount(); size++) {
View listItem = myListAdapter.getView(size, null, myListView);
listItem.measure(0, 0);
totalHeight += listItem.getMeasuredHeight();
}
//setting listview item in adapter
ViewGroup.LayoutParams params = myListView.getLayoutParams();
View listItem = myListAdapter.getView(myListAdapter.getCount() - 1, null, myListView);
listItem.measure(0, 0);
params.height = totalHeight + 10
+ (myListView.getDividerHeight() * (myListAdapter.getCount() - 1));
myListView.setLayoutParams(params);
// print height of adapter on log
Log.i("height of listItem:", String.valueOf(totalHeight));
}
}
There is another thing that can cause problem, please have a look on that issue as well. Please make sure your Screen is at-least showing one item of your listview completely before scrolling. Otherwise some part of your last item of list will be hidden. If this is the case then you have to add a static value to the total height in "ListViewHelper" class. Let's say:
params.height = totalHeight + 10 + 100
+ (myListView.getDividerHeight() * (myListAdapter.getCount() - 1));
Hope this'll help!
I have a main activity and its layout is a scrollView and has a "linear layout" called [taskLayout].
setContentView(R.layout.my_jobs_view_single_holder);
final LinearLayout taskLayout = (LinearLayout)findViewById(R.id.TaskLayout);
Then i'm inflating another view and adding the view to the main scrollviews.TaskLayout section.
LayoutInflater pickup_inflater = (LayoutInflater)getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = pickup_inflater.inflate(R.layout.my_jobs_view_single_pickup,null);
taskLayout.addView(view);
the newly added view has a listView which used an
ADAPTER_PICKUP_PASSENGER extends BaseAdapter
where it loads data Asynchronously from an external database.
The main scrollview layout looks like this:
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/fullscreen_content"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="5dp"
android:background="#0099cc">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:id="#+id/TaskLayout"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="top"
android:orientation="vertical">
</LinearLayout>
the Layout which contains listView looks like this:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/fullscreen_content"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_gravity="top"
android:background="#color/bg"
android:orientation="vertical">
<ListView
android:padding="2dp"
android:background="#drawable/border"
android:id="#+id/lst_passenger_pickup"
android:layout_width="fill_parent"
android:minHeight="200dp"
android:layout_height="fill_parent">
</ListView>
Everything works fine except the listView's height is not WRAP_CONTENT it only shows one item. When i change the ListView's
android:layout_height="fill_parent"
to
android:layout_height="200dp"
then the ListView gets 200dp height. For some reasons android:minHeight does not have any effect.
Ideally i would want to set the hight as WRAP_CONTENT so all items could be viewed but it doesn't work but either WRAP_CONTENT or FILL_PARENT just shows one item and setting manual height as 200dp is sometime too big if the list has only one item.
I have tried following steps so far:
In the Adapter just before returning convertView, i tried to do parent.requestLayout();
After setting the adapter to the listview, listview.requestLayout()
Nothing happens. could anyone shed some light please?
It will expand your listview as per your row height and width dynamically.
public static void getTotalHeightofListView(ListView listView) {
ListAdapter mAdapter = listView.getAdapter();
int totalHeight = 0;
for (int i = 0; i < mAdapter.getCount(); i++) {
View mView = mAdapter.getView(i, null, listView);
mView.measure(
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
totalHeight += mView.getMeasuredHeight();
}
ViewGroup.LayoutParams params = listView.getLayoutParams();
params.height = totalHeight
+ (listView.getDividerHeight() * (mAdapter.getCount() - 1));
listView.setLayoutParams(params);
listView.requestLayout();
}
I am using the method below to set the height of the ListView to the height of the items. The problem is that I have a few items where the text is too long so it continues on the next line. For those items I don't get the proper height but the height of a single line item. How can I get it to work for multiple lines items too?
public 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);
float px = 300 * (listView.getResources().getDisplayMetrics().density);
item.measure(View.MeasureSpec.makeMeasureSpec((int)px, View.MeasureSpec.AT_MOST), View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
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;
}
}
My item layout:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:paddingTop="3dp"
android:paddingBottom="3dp"
android:layout_height="wrap_content">
<TextView
android:textColor="#color/black"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="New Text"
android:id="#+id/itemName"
android:layout_marginRight="5dp"
android:layout_gravity="right"
android:layout_centerVertical="true"
android:layout_toStartOf="#+id/itemData"
android:layout_alignParentStart="true" />
<TextView
android:textColor="#color/black"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="New Text"
android:id="#+id/itemData"
android:layout_marginRight="10dp"
android:layout_alignBaseline="#+id/itemName"
android:layout_alignParentEnd="true" />
</RelativeLayout>
I want a Fragment that has 2 ListView. I dont want the listView to scroll instead i just want the whole Fragment to scroll. Heres the code:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#fff" >
<TextView
android:id="#+id/day"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:gravity="center_horizontal"
android:paddingTop="15dp"
android:text="Monday"
android:textColor="#000"
android:textSize="55sp" />
<TextView
android:id="#+id/date"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#id/day"
android:gravity="center_horizontal"
android:text="27 April, 2014"
android:textColor="#000"
android:textSize="45sp" />
<ListView
android:id="#+id/home_list_time"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#id/date"
android:layout_margin="10dp"
android:background="#color/list_home_time_bg"
android:divider="#android:color/white"
android:dividerHeight="20.0sp" />
<ListView
android:id="#+id/home_list_stime"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#id/home_list_time"
android:layout_margin="10dp"
android:background="#color/list_home_stime_bg"
android:divider="#android:color/white"
android:dividerHeight="20.0sp" />
</RelativeLayout>
When i run this code the 2nd listView gets its own scroll bar, is there a way to stop this and make the entire Fragment to scroll?
To stop the listview scrolling use -
listView.setScrollContainer(false);
To scroll fragment put it inside ScrollView -
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<!-- everything you already have -->
</ScrollView>
For more check - how-to-get-a-non-scrollable-listview.
NOTE:
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);
listView.requestLayout();
}
To use this method just pass the ListView inside this method :
ListView list1 = (ListView) view.findViewById(R.id.home_list_time);
setListViewHeightBasedOnChildren(list1);
ListView list2 = (ListView) view.findViewById(R.id.home_list_stime);
setListViewHeightBasedOnChildren(list2);
More here - android-list-view-inside-a-scroll-view.