I have an activity which contains text and a fragment:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="bla.HomeActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="A Text"
android:id="#+id/home_text_view"/>
<fragment
android:name="bla.CalendarAgendaFragment"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/cf"
tools:layout="#layout/fragment_calendar_agenda" />
</LinearLayout>
</ScrollView>
</LinearLayout>
The fragment only contains a ListView which is filled dynamically:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="wrap_content">
<ListView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/calendar_agenda_listview"
android:layout_gravity="center_horizontal" />
</LinearLayout>
The onCreateView method of the fragment looks like this:
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_calendar_agenda, container, false);
agenda_dates = new ArrayList<CalendarDate>();
agenda_dates.add(new CalendarDate("10.10.2015", "Kuchen backen"));
agenda_dates.add(new CalendarDate("10.10.2015", "Fenster putzen"));
list = (ListView) v.findViewById(R.id.calendar_agenda_listview);
adapter = new AgendaAdapter(getActivity(), R.layout.calendar_agenda_listview_item, agenda_dates);
list.setAdapter(adapter);
return v;
}
The code works and both CalendarDates are added to the fragment.
The problem is that the fragment is only about 40dp high and so only the first ListView item is shown. I can only see the second item by inline scrolling inside of the list view. How can I set the fragment's hight according to it's content?
You can set the height programatically, as seen here
Function:
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;
}
}
The problem is that the ListView doesn't work correctly with wrap_content.
See this question about it:
Android: wrap_content is not working with ListView
You should change the size of your ListView programmatically, as Rafael suggested.
Related
In row.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.sample.utils.ExpandableTextView
android:id="#+id/tv_item_treatment"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="2"
android:minLines="2"
android:paddingBottom="5dp"
android:paddingLeft="10dp"
android:paddingTop="5dp"
android:singleLine="false"
android:text="Test treatments"
android:textColor="#android:color/black" />
For calculating listview hight programeticaly in Activity Class:
public void setListViewHeightBasedOnRow(ListView listView) {
if (listView == null) {
return;
}
ListAdapter listAdapter = listView.getAdapter();
if (listAdapter == null) {
// pre-condition
return;
}
int totalHeight = listView.getPaddingTop() + listView.getPaddingBottom();
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();
}
LayoutParams params = listView.getLayoutParams();
params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1));
listView.setLayoutParams(params);
}
I am using ListView in between ScrollView so i have to set hight programmatically of ListView for full activity scrolling.
But when the ExpandableTextView of row is expand then lower row are goes to hidden.
how to calculate and set the ListView hight in ExpandableTextView is in expand state?
Taken from ScrollView | Android Developers:
You should NEVER use a ScrollView with a ListView, because ListView takes care of its own vertical scrolling. Most importantly, doing this defeats all of the important optimizations in ListView for dealing with large lists, since it effectively forces the ListView to display its entire list of items to fill up the infinite container supplied by ScrollView.
I want to achieve Fig-1 but I am stuck with Fig-2 and not able to see full gridview as a header of Listview.
As you can see the gridview is not showing fully and hiding behind Listview in Fig-2
Gridview xml :
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<GridView
android:id="#+id/gridview"
android:numColumns="2"
android:stretchMode="columnWidth"
android:cacheColorHint="#ffffffff"
android:gravity="center"
android:verticalSpacing="5dp"
android:horizontalSpacing="5dp"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</RelativeLayout>
Listview xml :
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:android="http://schemas.android.com/apk/res/android" >
<ListView
android:id="#+id/listview"
android:scrollbars="vertical"
android:background="#fff"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</ListView>
</RelativeLayout>
Fragment code :
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
view=inflater.inflate(R.layout.fragmentpage_layout, null);
listView=(ListView)view.findViewById(R.id.listview);
header=inflater.inflate(R.layout.gridview_layout,null);
gridView=(GridView)header.findViewById(R.id.gridview);
listView.addHeaderView(header);
gridViewAdapter=new CustomGridViewAdapter(getActivity(),images,toptexts, bottomtexts);
listViewAdapter=new CustomListViewAdapter(getActivity(),images,toptexts,bottomtexts);
gridView.setAdapter(gridViewAdapter);
listView.setAdapter(listViewAdapter);
return view;
}
Thanks In Advance.
Hey Guys I got my Answer using Gridview as a Header of Listview.
I just Calculated the Divider Height for Gridview using below method and it worked perfectly as I wanted.
public static void setDynamicHeightGridView(GridView mListView,String oddeven) {
ListAdapter mListAdapter = mListView.getAdapter();
if (mListAdapter == null) {
return;
}
int height = 0;
int desiredWidth = View.MeasureSpec.makeMeasureSpec(mListView.getWidth(), View.MeasureSpec.UNSPECIFIED);
for(int i = 0; i < mListAdapter.getCount(); i++){
View listItem = mListAdapter.getView(i, null, mListView);
listItem.measure(desiredWidth, View.MeasureSpec.UNSPECIFIED);
height += listItem.getMeasuredHeight();
itemHeight=listItem.getMeasuredHeight()/3;
}
ViewGroup.LayoutParams params = mListView.getLayoutParams();
if(oddeven.equals("odd")){
if(mListAdapter.getCount()>=5){
int count=((mListAdapter.getCount()-5)/2) + 1;
params.height = ((height - (height / 3)) - (itemHeight * count)) + 20 + (count * 5);
}else{
params.height = height - (height / 3) + 20;
}
}else if(oddeven.equals("even")) {
params.height = height/2 + 20;
}
mListView.setLayoutParams(params);
mListView.requestLayout();
}
Edited :
Finally the Exact Answer :
For Even number of views set :
params.height = height/2 + 20;
For Odd number of Views set :
params.height = ((height - (height / 3)) - (itemHeight * count)) + 20 + (count * 5);
where :
I have used 5 as the number for comparision
bcoz after this value of Adapters Count the variation in the space between
gridview and listview is increasing with fixed values.
For the space before 5 is handled in the else part.
itemHeight is the incremental value with which the space is increasing
20 is the margin space between gridview and listview
(count x 5) is the value for managing the margin as the elements increases.
bcoz it was giving me double the space for Gridview height above Listview for Even number of views
and Gridview + half it's height space for Odd number of views
Hope It Helps :)
Try this way , Taking your Grid and List in single layout and using android:weightSum to differentiate so that it will be applicable in all devices ,
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:padding="3dp"
android:weightSum="2">
<GridView
android:id="#+id/gridview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:cacheColorHint="#ffffffff"
android:gravity="center"
android:numColumns="2"
android:stretchMode="columnWidth" />
<ListView
android:id="#+id/listview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="#fff"
android:scrollbars="vertical" />
</LinearLayout>
Fragment code :
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
view=inflater.inflate(R.layout.fragmentpage_layout, null);
listView=(ListView)view.findViewById(R.id.listview);
gridView=(GridView)header.findViewById(R.id.gridview);
//your code
gridView.setAdapter(gridViewAdapter);
listView.setAdapter(listViewAdapter);
return view;
}
OR
If you want the whole gridview to be displayed fully first and below it should be the listview and when you scroll the gridview should go upwards and the listview should follow it behind as in Fig-1
Checkout this Awesome-MaterialDesign library with simple explaination.As shown in below figure
try adding android:layout_marginTop="some_value" in the RelativeLayout of the ListView
When you want to inflate your GridLayout also reference your listView With something like this :
header = LayoutInflater.from(getActivity()).inflate(R.layout.your_header, mListView, false);
And one more things : pass your relativeLayout instead of your GrideLayout as header.
Basically I need to have some content that is dynamically available through an adapter to populate the header of my expandableListView, this must be possible but it's been a really hard time finding any resources on this issue.
Here is a representation of what I'm looking to do.
Yes, but you'll need to override onGlobalLayout(), and set a height for the listView in the header e.g.
final ExpandableListView lExpView = (ExpandableListView) view.findViewById(R.id.expandable_list);
View viewHdr = getActivity().getLayoutInflater().inflate(R.layout.pager_header, lExpView, false);
final ListView lView = (ListView) viewHdr.findViewById(R.id.item_hdr_list);
...
lView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#SuppressLint("NewApi")
#SuppressWarnings("deprecation")
#Override
public void onGlobalLayout() {
if (lView.getVisibility() == View.VISIBLE) adjustTotalHeightOfListView(lView, lExpView);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN)
lExpView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
else
lExpView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
});
Where adjustTotalHeightOfListView() is a method of your own devising that can calculate and set the height of your listView, while contained in the header of the expandable list view. If the individual items in the listView can be more than one Text line in height (wider than the expandable list views width and you have WRAP_CONTENT set) this get's a bit complex, as the actual width of the containing ExpandableListView won't be available till it's rendered, but we need at least a guess before to allow this to happen. So you'll want some code that looks a bit like (not tested):
if (listView == null) return;
ListAdapter mAdapter = listView.getAdapter();
if (mAdapter == null) return;
int totalHeight = listView.getPaddingBottom() + listView.getPaddingTop();
int viewWidth = ( parent == null || parent.getWidth() <= 0 )
? listView.getWidth()
: parent.getWidth();
....
for (int i = 0; i < mAdapter.getCount(); i++) {
View mView = mAdapter.getView(i, null, listView);
mView.measure(
View.MeasureSpec.makeMeasureSpec(viewWidth, (viewWidth > 0)
? View.MeasureSpec.AT_MOST
: View.MeasureSpec.UNSPECIFIED
),
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)
);
totalHeight += mView.getMeasuredHeight() + listView.getDividerHeight();
}
....
ViewGroup.LayoutParams params = listView.getLayoutParams();
params.height = totalHeight;
listView.setLayoutParams(params);
listView.requestLayout();
Note: The ? View.MeasureSpec.AT_MOST : View.MeasureSpec.UNSPECIFIED hack in the measure() statement, essentially it's there to cope with a call being made before the parent view has been expanded / had a width set. If a width has been set don't exceed it, so if WRAP_CONTENT is specified and the width is greater than the parent the height will be adjusted, else assume you can be as wide as the content.
Where: pager_header.xml
<?xml version="1.0" encoding="utf-8"?>
<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="center">
<ListView
android:id="#+id/item_hdr_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" />
</GridLayout>
and the main layout contains:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center">
<ExpandableListView
android:id="#+id/expandable_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center_horizontal"
android:paddingBottom="10dp" />
</LinearLayout>
I have a profile page contains a linearlayout with some textviews and imageviews and a listview. (See picture)
The problem is that I want to make the whole page scrollable like in the twitter app instead of only the listview. So the listview need to extend to max height.
How can i force the listview to extend to max size and not be scrollable.
I linearlayout would be a second option but then it need to be possible to add a custom arrayadapter with a custom row like in the listview.
You can make this in two ways:
#1 Adding Header to your Listview
View header = inflater.inflate(R.layout.your_header_layout, null);
yourlistview.addHeader(header);
#2 You can set the list view height based on children.Call this fxn with your listview and keep all your widgets inside scrollview.
public static void setListViewHeightBasedOnChildren(ListView listView) {
ListAdapter listAdapter = listView.getAdapter();
if (listAdapter == null) {
return;
}
int totalHeight = 0;
for (int i = 0, len = listAdapter.getCount(); i < len; 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);
}
Yes you can put the scroll view as parent view and make your custom class for your list view.
You can check my answer by this link
list view in scroll view
Use ScrollView to wrap your layout:
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/scrollview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:fillViewport="true">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
......
</LinearLayout
</ScrollView>
Keep in mind that ScrollView takes in only one child. So adjust your original layout accordingly.
I am trying to have a listview with listviews as items, only the first row is visible in the inner listview(listview item).
My listview Item xml is :
<?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="wrap_content"
android:background="#drawable/main_bg" >
<ListView
android:id="#+id/numbers_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:cacheColorHint="#null"
android:divider="#null" >
</ListView>
</RelativeLayout>
You can't have scrollable view in other scrollable views. The same happens if you put a list view in a ScrollView.
For your purpose, why not implement multiple view items type? Examples here or here.
inside of one scrollable view another won't scroll..
call this method after u set adapter and pass your listview..
private void setListViewHeight(ListView listView) {
ListAdapter listAdapter = listView.getAdapter();
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);
listView.requestLayout();
}
http://kirukkupayal-mani.blogspot.in/2012/11/android-expandable-listview-inside.html