ExpandableListView, how to set the child height? - android

I'm trying to set the ExpandableListView item (ViewGroup) height. Can it be set via xml (I don't need the divider height):
<ExpandableListView
android:id="#+id/lvExp"
android:layout_height="match_parent"
android:layout_width="match_parent"/>
or it should be used this method, by manipulating the convertView:
#Override
public View getGroupView(int groupPosition, boolean isExpanded, View convertView,
ViewGroup parent) { ... }
Thanks in advance.

ListView child views can be different heights, so we don't set a one-size-fits all height in the ListView's xml. Rather you can set a specific height in each of the different convertView xml's that you are inflating.

Are you trying to set the height of the group row item in the listview? Also the ViewGroup would be your ExpandableListView and all of its groups and group children row items.
Or are you asking to set the height of the child items in the expandable list view?
The group item and its children in the listview are the same as any other listview row item.
You can just simply provide fixed height in row layout XML:
android:layout_height="25dp"
Or you could use ViewGroup.LayoutParams
http://developer.android.com/reference/android/view/ViewGroup.LayoutParams.html

Question is a bit old, but someone may be useful. As others said, height is not strict value (it changes according to its content). If you want to generally make more space between items (whether it is group or child), you can set padding to corresponding layouts.
This can be done either in XML layout or programmatically in list adapter.

Related

Getting child view to match_parent in Android

I have a simple linear layout which I'm inflating in an adapter:
#Override
public View getView(final int position, View convertView, final ViewGroup parent) {
if (convertView == null) {
convertView = inflater.inflate(R.layout.category_listview_row, parent, false);
} else {
((LinearLayout)convertView).removeAllViews();
}
if (LAYOUT_TYPES.GRID.equals(layoutType)) {
convertView = CategoryFragment.getViewForGridLayout(context, displayArray, position, convertView, listener);
} else {
convertView = CategoryFragment.getViewForListLayout(context, displayArray, position, convertView, listener);
}
return convertView;
}
Here, category_listview_row is the following:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:gravity="top"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
The getViewForGridLayout method programmatically creates one or more views and adds them to convertView.
I would like all the child views to match this parent view in height, however I can't get this to work. This is the outer linear layout of the child views that are added programmatically:
<?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:id="#+id/base_listview_style_one_layout"
android:orientation="horizontal"
android:padding="#dimen/node_default_spacing"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:background="#5ab9c6">
This layout has subviews which are removed according to the actual data to be displayed, so some will be longer than others. However I want them all to be the height of the parent so it doesn't look weird.
This is a screenshot of what I'm seeing:
The first row is ok since both items have a title and a subtext
On the second row, the second item doesn't have a subtext so that view is smaller. However, I'd like it to take the full height of the row so all items in a single row will have the same height.
Any tips? Thanks!
I would advise using a Recyclerview with GridLayoutManager.
If you want certain items spanning multiple columns, you can do so by setting SpanSizeLookup on the GridLayoutManager.
Here is a simple example https://stackoverflow.com/a/26907508/4498224.
Propably your layout params are ignored. Be sure that you are adding child views to your convertView like this:
View view = inflater.inflate( R.layout.item /* resource id */,
convertView /* parent */,
true /*attachToRoot, you dont need to call addView then*/);
Instead of removing the textview, why not just make it invisible or set its color to white to it occupies the space?
Please change your linearlayout height from wrap content to "match_parent".
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:gravity="top"
android:layout_width="match_parent"
android:layout_height="wrap_content" />`
Set the height of parent layout to wrap_content.
Set the height of child view to match-parent.
Try this i hope it will resolve your issue.
#zundi you can use view holder design pattern with recycler view adapter and define which row needs to have two images and which one needs to have one. Its pretty much simpler than doing it with linear layout.
Recycleview show different view types has a pretty decent explanation on how to do this.
And also to answer you question of making
some rows with 2 items and other rows with 1 item
you can use setSpanSizeLookup (GridLayoutManager.SpanSizeLookup spanSizeLookup) method of GridLayoutManager and define it in the activity.
RecycleView's span size gives you more info on how to achieve that.
mLayoutManager.setSpanSizeLookUp(new GridLayoutManager.SpanSizeLookUp() {
#Override
public int getSpanSize(int position) {
if(position == 0)
return 2; //here the view takes up two spaces in a row(header)
else return 1; //here view takes 1 space i.e., 2 views in a total row
} });
In the above example my grid layout manager takes 2 view holders based on different positions and decides if its header or not and populates the data.
Other Solution:
Rather than giving match parent and wrap parent inside your layout give a fixed 'dp' for height. That should make the views look consistent.
#zundi if doing it right way with RecyclerView and LayoutManager which would simplify you life dramatically but have a bit of learning curve doesn't suits you, here is an option that hasn't been mentioned yet:
You can define android:lines=x on TextView which contains subtext.
Just match_parent is not going to work for you because you want LinearLayout to wrap height of its children and its children to match_parent which is a circular dependency
This method can be performed on both Linear Layout or TextView you are using
You have set
android:layout_height="match_parent"
but not the height, so it is simple case
android:layout_height="match_parent"
So, in case even if there will be no value in the string it will still contain the height allotted to it

Header View height in a ListView

I'm working with a ListView that is part of an ListFragment. I want to add a header with a specific/custom height but it does not matter what I put in the height of the header view, always it has the same height. Is possible to modify the header view height of a ListView?
Below the code I use:
header.xml
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="100dp" />
ListFragment
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
TextView fakeHeader = (TextView)getActivity().getLayoutInflater().inflate(R.layout.header, null);
getListView().addHeaderView(fakeHeader);
}
When you pass in null as the second parameter to inflate(), you are saying there is no parent associated with the view. This has the unfortunate side effect where any layout_ attribute you use is ignored as layout_ parameters affect how the parent lays out the child view rather than directly affect the child (like other views): this pro-tip godes into more details on layout_ attributes.
You can use inflate(R.layout.header, getListView(), false) to pass in the ListView which will eventually the parent of your header view (note the false says to not add the view directly - ListView will do this automatically for you).

ListView / GridView: Setting child layout properly

I want to create a ListView (same question is relevant for a GridView) where the items have very specific LayoutParams. Take this example where I want each row to be a LinearLayout with a height of 100dp:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="100dp">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/pd_textview"
android:gravity="center_vertical"/>
</LinearLayout>
When I use this XML layout with a standard BaseAdapter implementation of getView() that inflates the views none of the LayoutParams for my LinearLayout get applied (each row simply wraps around the size of the text in the TextView):
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// Inflate view if necessary
if (convertView == null) {
convertView = ((Activity) mContext).getLayoutInflater().inflate(ID_LAYOUT, null, false);
}
// Return the view
return convertView;
}
Fishing around in the appropriate section of the Android documentation, it says the following about getView() which explains the current behaviour:
Get a View that displays the data at the specified position in the
data set. You can either create a View manually or inflate it from an
XML layout file. When the View is inflated, the parent View (GridView,
ListView...) will apply default layout parameters unless you use
inflate(int, android.view.ViewGroup, boolean) to specify a root view
and to prevent attachment to the root.
My question is simply, how should I actually be doing this? The suggestion of using a root view with the desired LayoutParams seems convoluted given that the LayoutParams I want to inflate the view with are in the view that I'm trying to inflate (yes I could inflate a static view and leave it as a member of the class to reference against... but that seems silly). The other option would be to only define the contents of the row item in XML and manually create the container and its LayoutParams every time?
Is there a 'correct' way (i.e. not a wasteful hack) that I'm missing to simply create items with the LayoutParams defined in the XML?
I'd have preferred to put this in a comment, but I don't have the 50 reputation needed to do that...
There is detailed explanation of the issue here:
http://www.doubleencore.com/2013/05/layout-inflation-as-intended/
The main point is this:
"The problem with this is android:layout_xxx attributes are always be evaluated in the context of the parent view. As a result, without any known parent, all LayoutParams you declared on the root element of your XML tree will just get thrown away [,...]"
So, indeed, the solution is:
convertView = ((Activity) mContext).getLayoutInflater().inflate(ID_LAYOUT, parent, false);

How to make an empty space between Expandable ListView groups [duplicate]

This question already has answers here:
android expandablelistview how to set space between groups items
(6 answers)
Closed 8 years ago.
Can somebody tell me how to make an empty space between the groups of Expandable ListView. I tried many solutions but whenever I give height to divider it always increase the height of child divider too. I tried separately android:divider="#drawable/group_separator" and android:childDivider="#drawable/child_separator" and also tried to set the height programmatically separately in getChildView and in getGroupView but the same result. It always increase the space between child divider too but i just want to make space only between the groups even if there no item between them. Like to give the space of 40dp even if there is no item just like in the below image. Any help will be highly appreciated. Thanks in advance.
and after I applied the divider height it become like
Answering to my own question so that anybody else may happen this problem so here is a solution after trying to much.I have done it through a single condition by just checking that if the group has no child then it should set the white layout that will be shown as a white blank space and no other things like padding, dividers or margin needed. just like in the below code in getGroupView() and you don't have to do anything else. The layout (blank_white_layout) I use is just a relativelayout having white background and you can give it height according to your needs.
if (getChildrenCount(groupPosition) == 0) {
view = inflater.inflate(R.layout.blank_white_layout, null);
}
and below is the complete getGroupView code in my adapter class
public View getGroupView(int groupPosition, boolean isExpanded, View convertView,
ViewGroup parent) {
if (groupPosition == 0 ) {
convertView = inflater.inflate(R.layout.group_layout1, null);
}
if (getChildrenCount(groupPosition) == 0) {
convertView = inflater.inflate(R.layout.blank_white_layout, null);
}else{
convertView = inflater.inflate(R.layout.group_layout2, null);
}
TextView text1 = (TextView) convertView.findViewById(android.R.id.text1);
return convertView;
}
From your getView() method detect the rows that you want to separate( by position and type)
and just add to them padding or margin, very simple.
Just make sure to remove that padding or margin when the listview recycles that view.
Create separate xml layout for group and child views. Set padding to the group layout xml file.
Simply add this tag in the group2 xml view.
android:layout_marginTop="40dp"

Background drawable shape margin

I have an xml drawable shape with rounded corners which is background of listview(with margin 10dp).
Now I added header/footer to the listview.
But how can I make background not affect header/footer? I want it to start from the first(not header) element in array and finish at the last(not footer). The size of items in listview is known.
Thanks!
If you can provide the code of your listView item XML and the listView adapter, i can give you a detailed answer.
basically this is what you have to do
1) in your listView item XML, add the header and footer. set id's and set the visibility property to gone
2) in your adapter, in the getView (int position, View convertView, ViewGroup parent) method; check the position. if the position is 0, set the header visibility to View.VISIBLE
and if the position size is equal to the getCount(), set View.VISIBLE to the footer.

Categories

Resources